简体   繁体   中英

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.

I'm using the Apache commons cli library , like so:

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 .

How can this be achieved using 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. 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

The idea is that a zip archive (and a jar is basically a flavor of a zip archive) may have an arbitrary prologue. The prologue is everything from the beginning of a file till zip file signature (4 characters, first two of which are 'PK'). When java reads a jar archive, it skips that prologue (everything before the signature).

So from the point of view of java , such a jar will be a valid 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.

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. And java will happily execute that jar ignoring the prologue.

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. This is just an example, you can tune the algorithm used to find java command to make it suit your needs.

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 .

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

And you run it like any other Java program from the CLI, but give it arguments like -h here. Note: you'll need to include a classpath for Apache Commons here.

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. 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

Open your bashrc and put in an alias or function . The fact of the matter is, you must invoke java , or you can use a different JVM scripting language like 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 . 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 .

you should create an executable jar from your java code:

  1. In Eclipse Right click on your main file
  2. Choice Export->excecutable jar file
  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 ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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