在java中执行linux命令并将输出存储在变量中

时间:2015-06-03 17:52:28

标签: java linux

我想在我的java程序中获得媒体服务器上的总免费E1通道。我使用以下代码来获得我想要的结果:

String command = "asterisk -rx " + '"' + "ss7 linestat " + '"' + " |grep " + '"' + "Idle" + '"' + " |wc -l";
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = buf.readLine()) != null)


    {
        freeE1s += line + "\n";
    }            

System.out.println(freeE1s);

当我使用kitty在linux shell中执行上述命令时,它工作正常并返回计数但是当我使用这个jar时,我得到异常。我通过日志调试代码,发现buf.readLine()返回null。

修改1:

不要担心异常它只解析输出到整数导致异常实际上有问题的是当我记录buf.readlin()它返回null当然无法解析为int。

1 个答案:

答案 0 :(得分:4)

首先,不要使用Runtime.exec。始终使用ProcessBuilder,它具有更可靠和可预测的行为。

其次,字符串中的所有内容都作为单个命令传递,包括垂直条。你没有把它传递给shell(比如/ bin / bash),所以彼此的管道命令不起作用。

第三,您需要在运行时使用命令的输出。如果您调用waitFor()然后尝试读取输出,它有时可能会起作用,但它也会在很多时候失败。此行为依赖于高度操作系统,甚至可能因Linux和Unix内核和shell而异。

最后,您不需要grepwc。你有Java。在Java中做同样的事情非常简单(并且可能比尝试调用shell更容易,因此管道可以工作):

ProcessBuilder builder =
    new ProcessBuilder("asterisk", "-rx", "ss7 linestat");
builder.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
Process p = builder.start();

int freeE1s = 0;
try (BufferedReader buf =
        new BufferedReader(new InputStreamReader(p.getInputStream()))) {
    String line;
    while ((line = buf.readLine()) != null) {
        if (line.contains("Idle")) {    // No need for 'grep'
            freeE1s++;                  // No need for 'wc'
        }
    }
}

p.waitFor();

System.out.println(freeE1s);

从Java 8开始,你可以缩短它:

ProcessBuilder builder =
    new ProcessBuilder("asterisk", "-rx", "ss7 linestat");
builder.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
Process p = builder.start();

long freeE1s;
try (BufferedReader buf =
        new BufferedReader(new InputStreamReader(p.getInputStream()))) {
    freeE1s = buf.lines().filter(line -> line.contains("Idle")).count();
}

p.waitFor();

System.out.println(freeE1s);