【问题标题】:Create a command line interface to a Java program, run from terminal创建 Java 程序的命令行界面,从终端运行
【发布时间】:2017-12-23 18:40:16
【问题描述】:

目前,我正在处理一个现有的 Java 项目,我的目标是创建一个命令行界面,用于向它传递参数、“运行”它,可以这么说。

我正在使用Apache commons cli library,如下所示:

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class CommandLineParameters {

  public static void main(String[] args) {
    CommandLineParser parser = new DefaultParser();
    Options options = new Options();

    options.addOption("a", "abc", true, "First Parameter");
    options.addOption("x", "xyz", true, "Second Parameter");
    options.addOption("h", "help", false, "Shows this Help");

    try {
      CommandLine commandLine = parser.parse(options, args);

      System.out.println(commandLine.getOptionValue("a"));
      System.out.println(commandLine.getOptionValue("x"));

      if (commandLine.hasOption("h")) {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("CommandLineParameters", options);
      }

    } catch (ParseException e) {
      e.printStackTrace();
    }
  }
}

在 Eclipse 中,我可以通过修改传递给 Run Configurations...Arguments 来运行它,但是,我实际上想要做的是,能够从终端 shell,类似于“正常”终端程序,例如 grepipconfig

如何使用 Java 来实现?

注意: 我不是试图从命令行编译/构建这个程序,我试图在命令行中为程序创建一个接口

【问题讨论】:

  • 如果您询问命令行语法本身,这些命令是javajavaw,它们在documentation page. 上有描述
  • 您的“注释”毫无意义。您可能想举一个“程序”的示例以及您现在如何尝试调用它。我怀疑这里有一个很大的 XY 问题。
  • 您需要创建一个 shell 脚本来执行此操作,因此答案取决于您的操作系统。
  • 这个想法是你调用shell脚本,然后用你的程序启动JVM并传递参数。
  • 不,我的意思是您创建一个单独的脚本,其中仅包含用于运行程序的命令,然后您可以将该脚本放入您的路径变量中(例如,使用您的 bash 配置文件)

标签: java terminal command-line-interface


【解决方案1】:

提供的答案描述了如何构建一个可以使用java -jar 命令执行的 jar。下面的文章解释了如何获取这样一个“可执行”jar并将其转换为sh可执行的“程序”文件(因此可以使用./program而不是java -jar program.jar调用):https://coderwall.com/p/ssuaxa/how-to-make-a-jar-file-linux-executable

这个想法是zip 存档(和jar 基本上是zip 存档的一种风格)可能有一个任意的序言。序言是从文件开头到zip 文件签名的所有内容(4 个字符,前两个是'PK')。当 java 读取 jar 存档时,它会跳过该序言(签名之前的所有内容)。

所以从java 的角度来看,这样的jar 将是一个有效的jar。但如果该序言是一个 shell 脚本,那么这样的 jar 也将是一个您可以使用 shell 解释器执行的文件。

这意味着您可以在通常的 jar 内容之前添加一个 shell 脚本,该脚本将调用 java -jar 并使用相同的 jar 存档作为参数。 java 会很乐意执行 jar 忽略序言。

文章的序言是这样的:

#!/bin/sh
MYSELF=`which "$0" 2>/dev/null`
[ $? -gt 0 -a -f "$0" ] && MYSELF="./$0"
java=java
if test -n "$JAVA_HOME"; then
    java="$JAVA_HOME/bin/java"
fi
exec "$java" $java_args -jar $MYSELF "$@"
exit 1

它查找java 并使用所需的参数启动它。这只是一个示例,您可以调整用于查找java 命令的算法以使其适合您的需求。

生成的文件将包含此启动器 shell 脚本和应使用 java -jar 运行的 jar 文件(包含主类和清单)的串联。

【讨论】:

    【解决方案2】:

    我认为你更好的选择是重写现有程序的另一个 main 方法以接受 CLI args,但如果你想这样做,无论哪种方式,你都需要将程序编译为类或 jar 文件

    您可以像从 CLI 中运行任何其他 Java 程序一样运行它,但在此处为其提供 -h 之类的参数。注意:您需要在此处包含 Apache Commons 的类路径。

    java - cp <classpath> fully.qualified.CommandLineParameters -h
    

    或者,如果您的 JAR 在其清单中具有 Main 类属性,并且还包括 Apache Commons(通过 uber jar),则无需设置类名或类路径。不过,请给出论据

    java -jar jarFile.jar -h
    

    我希望它是一个独立的程序,从命令行访问,例如ls

    打开你的 bashrc 和 put in an alias or function。事实上,你必须调用java,或者你可以使用不同的JVM脚本语言,比如Groovy

    $ cat my-ls
    #!/usr/bin/env groovy 
    println "Run my other program"
    $ chmod +x my-ls
    

    $ ./my-ls
    Run my other program
    

    【讨论】:

    • 我不是这个意思。我希望它是一个独立的程序,从命令行访问,例如ls
    • 那么 java 是错误的编程语言使用...或者你只是做一个别名
    【解决方案3】:

    这当然是可能的。解析参数后,您可以从System.in 读取并写入System.out。这是一个将输入转换为大写的非常简单的示例 - 不完整(错误处理等),只是为了展示如何开始:

    package sf;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    public class Sample {
    
        public static void main(String[] args) {
            processArguments(args);
            try {
                processInput(System.in);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private static void processArguments(String[] args) {
            // whatever
        }
    
        private static void processInput(InputStream in) throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line.toUpperCase());
            }
            in.close();
        }
    }
    

    并执行它只需使用像

    这样的类型
    java sf.Sample -a <input.txt >out.txt
    

    Sample.class所在的包含sf目录的目录必须在CLASSPATH中,或者您必须使用java命令的-cp选项:How Classes are Found

    【讨论】:

    • 我不是这个意思。我希望它是一个独立的程序,从命令行访问,例如ls
    • @s.matthew.english 你的意思是你不想输入“java -jar”?我不确定这是否可能,您必须调用 JVM 解释器。
    • 我只是希望它是一个可以从命令行调用的普通程序——它必须是可能的
    • @s.matthew.english “普通程序”?您可能指的是二进制可执行文件或 Shell 脚本。您可以使用 java -jar CommandLineParameters.jar --param1 -param2 构建一个简单的 shell 脚本...如果您要检查命令行参数,则将此脚本多作为一行。您问“如何使用 Java 实现这一点?” - 你有答案
    【解决方案4】:

    你应该从你的 java 代码创建一个可执行的 jar:

    1. 在 Eclipse 中右键单击您的主文件
    2. 选择导出->可执行jar文件
    3. 填写表格。从您的测试中获取“启动配置”您的运行配置

    从命令行启动您的应用程序:

    java -jar CommandLineParameters.jar --param1 -param2 ...
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-27
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多