在Linux中使用Java执行命令并获取输出
我正在使用Groovy在我的Linux机器上执行命令并返回输出,但不知何故(我认为)我无法使用在Linux中使用Java执行命令并获取输出,java,groovy,Java,Groovy,我正在使用Groovy在我的Linux机器上执行命令并返回输出,但不知何故(我认为)我无法使用管道,或者它可能没有等待命令完成 代码中有什么错误或遗漏了什么 我的呼叫功能: def test() { String result="N" HashMap<String,String> params = IntermediateResults.get("userparams") Map env=AppContext.get(AppCtxProperties.env
管道,或者它可能没有等待命令完成
代码中有什么错误或遗漏了什么
我的呼叫功能:
def test()
{
String result="N"
HashMap<String,String> params = IntermediateResults.get("userparams")
Map env=AppContext.get(AppCtxProperties.environmentVariables)
def fClass = new GroovyClassLoader().parseClass( new File( 'plugins/infa9/Infa9CommandExecUtil.groovy' ) )
List<String> frows=["uname -a",
"uname -a | awk '{print\$2}'",
"uname -a | cut -d ' ' -f 2"]
List<String> resultRows = fClass.newInstance().fetchCommandOutput( params, env, frows )
return result
}
我的输出(更新:添加的exitVal值):
注意:我在内部使用的是
sh-c
管道|
是类似shell的bash的一个特性。要使用管道,需要运行外壳,如
"/bin/bash", "-c", "uname -a | awk '{print $2}'"
要将ProcessBuilder与重定向一起使用,可以执行以下操作
public static void main(String... args) throws IOException, InterruptedException {
final String cmd = "uname -a | awk '{print $1 \" \" $3}'";
System.out.println(cmd + " => " + run(cmd));
}
private static String run(String cmd) throws IOException, InterruptedException {
final ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", cmd);
pb.redirectErrorStream();
final Process process = pb.start();
final InputStream in = process.getInputStream();
final byte[] bytes = new byte[1024];
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
// you must read the output as the program runs or it can stall.
for (int len; (len = in.read(bytes)) > 0;)
baos.write(bytes, 0, len);
process.waitFor();
return baos.toString(); // assuming the default char encoding is ok.
}
印刷品
uname -a | awk '{print $1 " " $3}' => Linux 2.6.18-274.3.1.el5
管道是外壳的一个特征。因此,如果希望支持管道,则必须在shell上下文中运行命令,即在java中传递给
exec
的命令行应该类似于/bin/sh您的_命令
不能使用String.execute()
执行管道或重定向。这在Java中不起作用,所以在Groovy中也不起作用
您可以将Process.pipeTo
与Groovy结合使用,以简化操作:
Process proca = 'uname -a'.execute()
Process procb = 'awk {print\$2}'.execute()
(proca | procb).text
更通用的版本可以是:
String process = 'uname -a | awk {print\$2}'
// Split the string into sections based on |
// And pipe the results together
Process result = process.tokenize( '|' ).inject( null ) { p, c ->
if( p )
p | c.execute()
else
c.execute()
}
// Print out the output and error streams
result.waitForProcessOutput( System.out, System.out )
那么,你仍然没有用Groovy的方式来做这件事(我已经向你展示了好几次)?@tim:我落后于计划,我想我会先满足需求,然后重构代码。抱歉:)我也会读取错误流,或者使用ProcessBuilder将错误定向到输出。我会将输出复制到ByteArrayOutputStream,并将其转换为字符串。@Peter Lawrey:请您举个例子,这将是一个很大的帮助。谢谢,我以为你不应该从Java调用非Java程序。否则,为什么要麻烦首先用Java编写呢?谢谢,还有什么是
.inject(null)
和p,c->
在这里做什么?@Ab从一个初始累加器值开始(在本例中是null
),然后沿着集合依次应用闭包到每个元素(闭包被放入下一个元素的累加器中的结果)。因此,在本例中,我们从null
开始,然后第一次迭代将其设置为c.execute()
(其中c是列表中的第一个元素),然后第二个循环,p
是由此产生的结果进程,因此它将累加器设置为p.execute()
。希望这有意义吗?您如何捕获输出???@AbhishekSimon我不理解问题…结果。waitForProcessOutput(System.out,System.out)
将输出流和错误流从流程链重定向到System.out
。因此,所有内容都显示在同一个流上…谢谢,它工作得很好。我将在我的问题中发布完整的函数,作为对其他人的更新:)
Process proca = 'uname -a'.execute()
Process procb = 'awk {print\$2}'.execute()
(proca | procb).text
String process = 'uname -a | awk {print\$2}'
// Split the string into sections based on |
// And pipe the results together
Process result = process.tokenize( '|' ).inject( null ) { p, c ->
if( p )
p | c.execute()
else
c.execute()
}
// Print out the output and error streams
result.waitForProcessOutput( System.out, System.out )