14

I am now on a linux machine. I have a Java program which would run some linux command, for example ps, top, list or free -m.

The way to run a command in Java is as follows:

Process p = Runtime.getRuntime().exec("free -m");

How could I collect the output by Java program? I need to process the data in the output.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
user84592
  • 4,750
  • 11
  • 55
  • 91

5 Answers5

14

Use Process.getInputStream() to get an InputStream that represents the stdout of the newly created process.

Note that starting/running external processes from Java can be very tricky and has quite a few pitfalls.

They are described in this excellent article, which also describes ways around them.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • But I notice if the command is "free -m", the example works, but if it is "top -n 1" it does not work. – user84592 Jun 24 '11 at 10:55
  • @user: that's probably because the output of `free -m` is much shorter than the output of `top -n 1` and still fits in the OS buffer I mentioned in the common to the anwer by @spoon. You **must** read the content of the stream **before** trying to call `waitFor()`. The details are in the article I linked to (yes, you **must** read it if you seriously want to use `Runtime.exec()` or `ProcessBuilder`. There's no way around it). – Joachim Sauer Jun 24 '11 at 10:57
  • I follow the List4.7 and gave a command line "top -n 1", it prints out ERROR> top: failed tty get ERROR> ExitValue: 1 – user84592 Jun 24 '11 at 11:51
  • 2
    @user: in that case, you're probably running into a limitation of `top`: It wants a real terminal to be its output and not just a stream. You could try adding the `-b` option to run it in batch mode. – Joachim Sauer Jun 24 '11 at 12:29
6

To collect the output you could do something like

 Process p = Runtime.getRuntime().exec("my terminal command");

  p.waitFor();
  BufferedReader buf = new BufferedReader(new InputStreamReader(
          p.getInputStream()));
  String line = "";
  String output = "";

  while ((line = buf.readLine()) != null) {
    output += line + "\n";
  }

  System.out.println(output);

This would run your script and then collect the output from the script into a variable. The link in Joachim Sauer's answer has additional examples of doing this.

Nick DeFazio
  • 2,412
  • 27
  • 31
  • 4
    Be careful! You're falling into one of the pits (actually, several): When the output of the command is bigger than the buffer on stdout by the OS (and that buffer is often just a few Kb), then your `waitFor()` call will block indefinitely. – Joachim Sauer Jun 22 '11 at 14:25
  • 1
    I also notice if the terminal command is "free -m", the program works. But if it is "top -n 1", it does not work. – user84592 Jun 24 '11 at 11:01
1

As for some command need to wait for a while, add p.waitFor(); if necessary.

public static void main(String[] args) {

        CommandLineHelper obj = new CommandLineHelper();
        String domainName = "google.com";
        //in mac oxs
        String command = "ping -c 3 " + domainName;
        String output = obj.executeCommand(command);
        System.out.println(output);

    }

private String executeCommand(String command) {

        StringBuffer output = new StringBuffer();

        Process p;
        try {

            p = Runtime.getRuntime().exec(command);

            p.waitFor();
            BufferedReader reader = 
                            new BufferedReader(new InputStreamReader(p.getInputStream()));

                        String line = "";           
            while ((line = reader.readLine())!= null) {
                output.append(line + "\n");
            }

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

        return output.toString();

    }
Albert Chen
  • 1,331
  • 1
  • 12
  • 13
1

The technicalities of calling an external process are quite involved. The jproc library helps abstracting over these by automatically consuming the output of the command and providing the result as a string. The example above would be written like this:

String result = ProcBuilder.run("free", "-m");

It also allows to set a timeout, so that your application isn't blocked by an external command that is not terminating.

Felix Leipold
  • 1,064
  • 10
  • 17
1
public String RunLinuxGrepCommand(String command) {
    String line = null;
    String strstatus = "";
    try {

        String[] cmd = { "/bin/sh", "-c", command };
        Process p = Runtime.getRuntime().exec(cmd);
        BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while ((line = in.readLine()) != null) {
            strstatus = line;
        }
        in.close();
    } catch (Exception e) {

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        pw.flush();
        String stackTrace = sw.toString();
        int lenoferrorstr = stackTrace.length();
        if (lenoferrorstr > 500) {
            strstatus = "Error:" + stackTrace.substring(0, 500);
        } else {
            strstatus = "Error:" + stackTrace.substring(0, lenoferrorstr - 1);

        }
    }
    return strstatus;

}

This functioin will give result of any linux command