收集Linux命令的输出结果

14

我现在在一台Linux机器上。我有一个Java程序,它需要运行一些Linux命令,比如pstopls或者free -m

在Java中运行命令的方式如下:

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

我该如何在Java程序中获取输出?我需要处理输出中的数据。

5个回答

14
使用 Process.getInputStream() 获取表示新创建的进程的标准输出(stdout)的 InputStream
请注意,在Java中启动/运行外部进程可能非常棘手,并且存在许多陷阱。这些在 这篇优秀文章 中有所描述,其中还介绍了解决方法。

但是我注意到,如果命令是"free -m",示例会正常工作,但如果是"top -n 1",它就不起作用了。 - user84592
@user:这可能是因为free -m的输出比top -n 1的输出短得多,仍适合我在与@spoon的答案中提到的OS缓冲区。在尝试调用waitFor()之前,您必须读取流的内容。有关详细信息,请参阅我链接的文章(如果您真的想使用Runtime.exec()ProcessBuilder,则必须阅读它。没有其他方法)。 - Joachim Sauer
我按照List4.7的步骤,在命令行中输入了"top -n 1",结果打印出了错误信息:"ERROR> top: failed tty get ERROR> ExitValue: 1"。 - user84592
2
@user:在这种情况下,你可能遇到了top的限制:它需要一个真正的终端作为输出,而不仅仅是一个流。你可以尝试添加-b选项以批处理模式运行它。 - Joachim Sauer

6
为了收集输出,您可以执行以下操作:
 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);

这将运行您的脚本,然后将脚本的输出收集到一个变量中。Joachim Sauer答案中的链接有更多关于如何做到这一点的例子。

4
小心!你正在掉入一个坑(实际上是几个):当命令输出大于操作系统stdout缓冲区的大小(而且该缓冲区通常只有几KB)时,你的waitFor()调用将会无限期地阻塞。 - Joachim Sauer
1
我还注意到,如果终端命令是“free -m”,程序可以工作。但如果是“top -n 1”,它就无法工作。 - user84592

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;

}

这个函数将会返回任何Linux命令的结果。


对我不起作用。没有返回结果。程序卡住了。 - MeineHTMLCodes

1
如果某些命令需要等待一段时间,请根据需要添加 p.waitFor()。
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();

    }

1
调用外部进程的技术细节相当复杂。jproc库通过自动消费命令输出并将结果提供为字符串来帮助抽象化这些内容。上面的示例将被写成:

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

它还允许设置超时,以便您的应用程序不会被无法终止的外部命令阻塞。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接