Java 使用ApacheCommonsExec运行管道命令的更好方法
我正在使用ApacheCommonsExec运行命令:Java 使用ApacheCommonsExec运行管道命令的更好方法,java,arp,apache-commons-exec,Java,Arp,Apache Commons Exec,我正在使用ApacheCommonsExec运行命令:arp | wc-l 下面是我的代码: private String runCommand(String cmd, String params) { CommandLine commandLine = new CommandLine(cmd); commandLine.addArguments(params); ByteArrayOutputStream stdout = new ByteAr
arp | wc-l
下面是我的代码:
private String runCommand(String cmd, String params) {
CommandLine commandLine = new CommandLine(cmd);
commandLine.addArguments(params);
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdout, stderr);
ExecuteWatchdog watchdog = new ExecuteWatchdog(30000); // 30s timeout
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(pumpStreamHandler);
executor.setWatchdog(watchdog);
try {
int retCode = executor.execute(commandLine);
System.out.println("Executed '" + cmd + "'\n"
+ "returnCode: " + retCode + "\n"
+ "stdout:\n" + stdout.toString() + "\n"
+ "stderr:\n" + stderr.toString());
if (retCode == 0) {
return stdout.toString();
} else {
throw new NonZeroExitStatusReturnedException(commandLine.toString(), retCode);
}
} catch (IOException e) {
throw new RuntimeException("Could not run command "+ commandLine.toString(), e);
}
}
此处cmd为/bin/sh
,参数为-c arp|wc-l
代码给出以下输出:
Executed '/bin/sh'
returnCode: 0
stdout:
54 71 4321
stderr:
usage: arp [-n] [-i interface] hostname
arp [-n] [-i interface] [-l] -a
arp -d hostname [pub] [ifscope interface]
arp -d [-i interface] -a
arp -s hostname ether_addr [temp] [reject] [blackhole] [pub [only]] [ifscope interface]
arp -S hostname ether_addr [temp] [reject] [blackhole] [pub [only]] [ifscope interface]
arp -f filename
我这里有两个问题:问题1。我无法理解为什么我的输出中有三个数字(54714321)。不是只有一个号码吗
问题2。有没有更好的方法可以使用apache commons exec运行相同的命令?仔细阅读文档-。
以下是问题2的答案:
private String runCommand(String cmd, String[] params) {
CommandLine commandLine = new CommandLine(cmd);
commandLine.addArguments(params, false);
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdout, stderr);
ExecuteWatchdog watchdog = new ExecuteWatchdog(30000); // 30s timeout
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(pumpStreamHandler);
executor.setWatchdog(watchdog);
try {
int retCode = executor.execute(commandLine);
System.out.println("Executed '" + cmd + "'\n"
+ "returnCode: " + retCode + "\n"
+ "stdout:\n" + stdout.toString() + "\n"
+ "stderr:\n" + stderr.toString());
if (retCode == 0) {
return stdout.toString();
} else {
throw new NonZeroExitStatusReturnedException(commandLine.toString(), retCode);
}
} catch (IOException e) {
throw new RuntimeException("Could not run command "+ commandLine.toString(), e);
}
}
这里的命令是:/bin/sh
参数是:
newstring[]{“-c”,“arp | wc-l”}
关于第二个问题,我构建了一个纯Java解决方案:
/**
Run command $cmd1 and pipe its STDOUT to $cmd2, just like executing:
$ cmd1 | cmd2
from a Linux shell
*/
private String runCommand(String cmd1, String[] params1,
String cmd2, String[] params2) {
PipedOutputStream stdin = new PipedOutputStream();
PipedInputStream stdout = new PipedInputStream();
// - pipe STDOUT of first process to STDIN of second process
stdin.connect(stdout);
// - First process: arp
CommandLine commandLine = new CommandLine(cmd1).addArgument(params1);
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(new PumpStreamHandler(stdin));
executor.execute(commandLine, new DefaultExecuteResultHandler());
// - Second process: wc
CommandLine commandLine2 = new CommandLine(cmd2).addArguments(params2);
DefaultExecutor executor2 = new DefaultExecutor();
executor2.setStreamHandler(new PumpStreamHandler(System.out, System.err,
stdout));
executor2.execute(commandLine2, new DefaultExecuteResultHandler());
}
这就省去了对管道(“|”)的需要,它将增强代码的可移植性和安全性(更容易执行消毒检查)。如果您注意到问题代码和解决方案代码之间的差异,那就太好了:
commandLine.addArgument(params,false)代码>因为很难得到不同的结果。