最近使用ProcessBuilder执行命令,命令内容正确,但始终报错命令实行失败,是因为不熟悉ProcessBuilder用法踩到了坑,记录一下。
先看一下我模拟出来的错误

要执行的命令:cp -rf /tmp/monkey/a.log /home/monkey/ 简单的cp命令拷贝一个文件,却报错说文件不存在。确认过文件确实存在该目录下。

查看jdk 中,我使用的ProcessBuilder(***) 源码实现如下,并不是一个单独的字符串String形式,而是支持多个字符串,同时还有List集合方式。


于是想到会不会是ProcessBuilderbuilder不支持包含空格的命令。
动手写了下面的代码进行测试
public class ProcessBuilderDemo {
/**
* 测试processBuilder执行cp命令
* cp /tmp/monkey/a.log /home/monkey/
* 源路径 args[1]: /tmp/monkey/a.log
* 目标路径 args[2]: /home/monkey/
* 方法名 args[3]
* @param args
*/
public static void main(String[] args) {
String src = args[0];
String tag = args[1];
String method = args.length == 3 ? args[2] : null;
if (method != null && method.equals("string")) {
cmdIsString(src, tag);
} else {
cmdIsListOrArray(src, tag);
}
}
/**
* 执行命令,命令用拼接成一个字符串形式(会包含空格)
* @param src 源路径
* @param tag 目标路径
*/
private static void cmdIsString(String src, String tag) {
String cmd = "cp";
cmd = cmd + " -rf" + " " + src + " " + tag;
System.out.println("command is: " + cmd);
ProcessBuilder builder = new ProcessBuilder(cmd);
try {
Process process = builder.start();
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.toString());
}
}
/**
* 执行命令,命令各个部分拼接成一个数组或者ArrayList集合
* 该方法采用数组实现
* @param src 源路径
* @param tag 目标路径
*/
private static void cmdIsListOrArray(String src, String tag) {
String cmd = "cp";
// 命令的各个部分组成一个字符串数组,用该数组创建ProcessBuilder对象
String[] cmds = new String[] {cmd, "-rf", src, tag};
ProcessBuilder builder = new ProcessBuilder(cmds);
try {
Process process = builder.start();
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.toString());
}
}
}
果然如我所猜想的一样:包含有空格的命令执行会报错。
以下是cmdIsListOrArray方法,将命令的内容组成字符串的形式执行的结果,而文章第一张图则是直接当做一条完整命令的执行结果。

至于为什么不能好有空格暂时未做深入了解,有带佬可以释疑吗?难道一条完整的命令当做一个字符串它不香嘛?
while(true) {
伸手党;
}

本文探讨了使用Java的ProcessBuilder执行包含空格命令时遇到的问题。通过对比字符串和数组/列表的不同用法,揭示了命令执行失败的原因,并提供了正确的实践方法。
726





