简体   繁体   English

创建从终端运行的Java程序的命令行界面

[英]Create a command line interface to a Java program, run from terminal

At the moment I'm wrangling with an existing Java project, my goal is to create a command line interface for passing arguments to it, to "run" it, so to speak. 现在,我正在与一个现有的Java项目进行争执,我的目标是创建一个命令行界面,以将参数传递给它,“运行”它。

I'm using the Apache commons cli library , like so: 我正在使用Apache commons cli库 ,如下所示:

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();
    }
  }
}

In Eclipse I can run this by modifying the Arguments passed to the Run Configurations... , however, what I would in fact like to do is, to be able to run this programme from a terminal shell, in an analogous way to " normal " terminal programmes such as grep , or ipconfig . 在Eclipse中,我可以通过修改传递给“ Run Configurations...ArgumentsRun Configurations... ,但是, 实际上 ,我想做的是能够从终端外壳运行该程序,类似于“ 常规” “终端程序,如grepipconfig

How can this be achieved using Java? 使用Java如何做到这一点?

NOTE: I'm not trying to compile/build this programme from the command line, I'm trying to make an interface to the program in the command line. 注意:我不是试图从命令行编译/构建该程序,而是试图在命令行中创建程序的接口

The provided answers describe how to build a jar that can be executed using java -jar command. 提供的答案描述了如何构建可以使用java -jar命令执行的jar。 The following article explains how to take such an 'executable' jar and convert it to a 'program' file executable by sh (so it can be invoked with ./program and not with java -jar program.jar ): https://coderwall.com/p/ssuaxa/how-to-make-a-jar-file-linux-executable 下面的文章解释了如何获取这样一个“可执行” jar并将其转换为sh可执行的“ program”文件(因此可以使用./program而不是java -jar program.jar来调用它): https:// coderwall.com/p/ssuaxa/how-to-make-a-jar-file-linux-executable

The idea is that a zip archive (and a jar is basically a flavor of a zip archive) may have an arbitrary prologue. 这个想法是,一个zip存档(而jar基本上是zip存档的一种味道)可能具有任意的序言。 The prologue is everything from the beginning of a file till zip file signature (4 characters, first two of which are 'PK'). 序言是从文件开头到zip文件签名(4个字符,其中前两个为“ PK”)的所有内容。 When java reads a jar archive, it skips that prologue (everything before the signature). 当java读取jar归档文件时,它会跳过该序言(签名之前的所有内容)。

So from the point of view of java , such a jar will be a valid jar. 因此,从java的角度来看,这样的jar将是有效的jar。 But if that prologue is a shell script, such a jar will also be a file that you can execute using a shell interpreter. 但是,如果该序言是Shell脚本,则这样的jar也会是您可以使用Shell解释器执行的文件。

That means that you can prepend usual jar content with a shell script that will just invoke that java -jar with that same jar archive as an argument. 这意味着您可以在常规的jar内容之前添加一个shell脚本,该脚本将使用相同的jar存档作为参数来调用java -jar And java will happily execute that jar ignoring the prologue. java将忽略该序幕而愉快地执行该jar

The prologue in the article looks like this: 本文的序言如下:

#!/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

It looks for java and starts it with the needed parameters. 它会查找java并以所需的参数启动它。 This is just an example, you can tune the algorithm used to find java command to make it suit your needs. 这只是一个示例,您可以调整用于查找java命令的算法以使其适合您的需求。

And the resulting file will consist of the concatenation of this launcher shell script and that jar file (containing main class and manifest) that should be run using java -jar . 生成的文件将包括该启动程序shell脚本和应使用java -jar运行的jar文件(包含主类和清单)的串联。

I think your better option is to rewrite the other main method of the existing program to accept CLI args, but if you want to do so, either way, you need to compile the program to a class or jar file 我认为您更好的选择是重写现有程序的其他主要方法以接受CLI arg,但是,无论哪种方式,您都需要将该程序编译为类或jar文件

And you run it like any other Java program from the CLI, but give it arguments like -h here. 您可以像从CLI的任何其他Java程序一样运行它,但是在这里给它类似-h参数。 Note: you'll need to include a classpath for Apache Commons here. 注意:您需要在此处包括Apache Commons的类路径。

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

Or, if you have a JAR with a Main class attribute in its manifest and also includes Apache Commons (via an uber jar), there's no need to set the class name or classpath. 或者,如果清单中有一个具有Main class属性的JAR,并且还包含Apache Commons(通过uber jar),则无需设置类名或类路径。 Still, give the arguments, though 尽管如此,尽管给出论点

java -jar jarFile.jar -h

I want it to be an independent programme, accessed from the command line, such as ls 我希望它是一个独立的程序,可以从命令行访问,例如ls

Open your bashrc and put in an alias or function . 打开您的bashrc并放入别名或函数 The fact of the matter is, you must invoke java , or you can use a different JVM scripting language like Groovy 事实是,您必须调用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

That sure is possible. 那肯定是可能的。 After parsing the parameters you can read from System.in and write to System.out . 解析完参数后,您可以从System.in读取并写入System.out Here a very simple sample to convert input to uppercase - incomplete (error handling and such), just to show how to start: 这里是一个非常简单的示例,用于将输入转换为大写-不完整(错误处理等),只是为了展示如何开始:

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();
    }
}

and to execute it just use type like 并执行它就像使用类型

java sf.Sample -a <input.txt >out.txt

the directory containing the sf directory where the Sample.class is located must be in the CLASSPATH or you must use the -cp option to the java command: How Classes are Found . 包含Sample.class所在的sf目录的目录必须位于CLASSPATH中,或者您必须对java命令使用-cp选项: 如何找到类

you should create an executable jar from your java code: 您应该通过Java代码创建一个可执行jar:

  1. In Eclipse Right click on your main file 在Eclipse中,右键单击您的主文件
  2. Choice Export->excecutable jar file 选择导出->可执行jar文件
  3. fill out the form. 填写表格。 Take for "Launch configuration" your running configuration from your test 从测试中获取“启动配置”以运行配置

Start your application from command line: 从命令行启动您的应用程序:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM