使用org.apache.commons.exec.DefaultExecutor执行Shell命令

3
我希望能够在Java代码中执行这样一个命令,
gzip -c /tmp/specificPreffix_2013-11-06.txt > /tmp/specificPreffix_2013-11-06.txt.gz

我的系统是RHEL5,我已经授予了文件访问权限。

当我使用开源的org.apache.commons.exec.DefaultExecutor时,它无法工作。请问有谁能指出这是为什么,或者告诉我是否有其他方法。提前感谢。

您可以按照以下方式使用:

CommandLine cmd = new CommandLine("gzip").addArgument("-c").addArgument("/tmp/specificPreffix_2013-11-06.txt").addArgument(">").addArgument("/tmp/specificPreffix_2013-11-06.txt.gz");

OutputStream outputStream = new ByteArrayOutputStream();
DefaultExecutor exec = new DefaultExecutor();
exec.setWatchdog(new ExecuteWatchdog(timeoutInMilliSeconds));
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
exec.setStreamHandler(streamHandler);
exec.execute(cmd);

我认为你需要一个 shell 来解释 >。尝试通过执行器运行 bash,将 -c作为第一个参数,将你要运行的整个字符串作为第二个参数。 - Dawood ibn Kareem
谢谢David。即使我没有使用“>”,它仍然无法正常工作,代码如下: CommandLine cmd = new CommandLine("bash").addArgument("-c").addArgument("gzip /tmp/specificPreffix_2013-11-06.txt"); 我做错了什么吗? - Junjie
你遇到了什么错误?你尝试过使用 Runtime.getRuntime().exec( ... ) 吗? - Dawood ibn Kareem
我没有收到任何异常,但是什么也没做。我尝试了 Runtime.getRuntime().exec( ... ),如果我不使用 >,它可以正常工作,一旦我在命令中添加 >,它就会失败。所以 Runtime.getRuntime().exec("gzip /tmp/specificPreffix_2013-11-06.txt) 可以工作,但我无法重定向标准输出。 - Junjie
1
嗨大卫,我应该发现你在之前的第一条评论中告诉了我正确的答案,它目前有效,谢谢你的帮助。Runtime.getRuntime().exec(new String[]{"sh","-c","gzip -c /tmp/specificPreffix_2013-11-06.txt > /tmp/specificPreffix_2013-11-06.txt.gz",}); 是正确的。非常感谢你。 - Junjie
1
好的,没问题。如果您已经找到了解决方案,您可以将其发布为答案,以使其他遇到相同问题的人受益。我必须承认,我的评论有些猜测,但我很高兴您最终解决了问题。 - Dawood ibn Kareem
2个回答

1
String myActualCommand =
    "gzip -c /tmp/specificPreffix_2013-11-06.txt > /tmp/specificPreffix_2013-11-06.txt.gz";

// able to execute arbitrary shell command sequence
CommandLine shellCommand = new CommandLine("sh").addArgument("-c");

// set handleQuoting = false so our command is taken as it is
shellCommand.addArgument(myActualCommand, false);

Executor exec = new DefaultExecutor();
// ... (configure the executor as you like, e.g. with watchdog and stream handler)

exec.execute(shellCommand);

commons.exec期望CommandLine对象仅表示具有参数的一个命令。例如,echo 'hello world!'是可以的,但是echo 'hello world!' > hello.txt需要使用我上面展示的解决方法才能正常工作。

了解解决方法

sh -c接受包含任意shell命令的字符串作为“参数”并执行它们。从bash man页中得知:

-c string:如果存在-c选项,则从字符串中读取命令。如果在字符串后面有参数,则将它们分配给位置参数,从$0开始。

这使我们可以将我们的shell命令序列作为“参数”传递,使commons.exec满意。最后,addArgument(...)中的false参数告诉commons.exec按原样采用我们的实际命令。


0

David@ 在评论中给出了正确的答案。

Runtime.getRuntime().exec(new String[]{"sh","-c","gzip -c /tmp/specificPreffix_2013-11-06.txt > /tmp/specificPreffix_2013-11-06.txt.gz",});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接