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

我想在我的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); 

当我在linux shell中使用kitty执行上面的命令,那么它工作正常,并返回计数,但是当我使用这个jar然后我得到exception。 我通过日志loggingdebugging代码,发现buf.readLine()返回null。

编辑1:

不要担心exception它只是parsing输出为整数,导致exception实际上有问题的事情是当我loggingbuf.readlin()它返回null,当然不能被分析为int。

首先,不要使用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);