我正在使用Groovy在我的Linux机器上执行命令并取回输出,但我无法以某种方式使用|
管道(我认为)或者它可能没有等待命令完成。
我的代码中有什么问题或我缺少什么?
我的通话功能:
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
}
Infa9CommandExecUtil.groovy
文件内容(更新:添加了exitVal println):
package infa9
import java.io.BufferedReader;
public class Infa9CommandExecUtil {
StringBuffer result
public Infa9CommandExecUtil() {
result = new StringBuffer()
}
public List<String> fetchCommandOutput( Map<String,String> params, Map env, List<String> rows )
{
List<String> outputRows = new ArrayList<String>()
try
{
for(item in rows)
{
String temp=item.toString()
println "CMD:$temp"
Process proc = Runtime.getRuntime().exec(temp);
InputStream stdin = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
result = new StringBuffer()
line=null
int exitVal = proc.waitFor() //do I need to wait for the thread/process to finish here?
while ((line = br.readLine()) != null)
{
result.append(line+System.getProperty("line.separator")) //to maintain the format (newlines)
}
String tRes=result
tRes=tRes.trim()
println "OUTPUT:$tRes\nEXITVAL:$exitVal"
outputRows.add(tRes)
}
}
catch (IOException io) { io.printStackTrace();}
catch (InterruptedException ie) {ie.printStackTrace();}
return outputRows
}
}
我的输出(更新:添加了exitVal值):
CMD:uname -a
OUTPUT:Linux estilo 2.6.18-128.el5 #1 SMP Wed Dec 17 11:41:38 EST 2008 x86_64 x86_64 x86_64 GNU/Linux
EXITVAL:0
CMD:uname -a | awk '{print$2}'
OUTPUT:
EXITVAL:1
CMD:uname -a | cut -d ' ' -f 2
OUTPUT:
EXITVAL:1
注意:我在内部使用sh -c <command>
。
答案 0 :(得分:12)
您无法使用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 )
答案 1 :(得分:4)
管道|
是bash之类的shell的一个特性。要使用管道,您需要运行shell,例如
"/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
答案 2 :(得分:1)
管道是shell的一个特性。因此,如果要支持管道,则必须在shell上下文中运行命令,即在java中传递给exec
的命令行应该看起来像/bin/sh YOUR_COMMAND
。