前言
最近在做JavaWeb项目的过程中,前端执行一些事件需要用java调用云端linux的命令,我按照网上的方法弄,发现要么执行命令没反应,要么遇上特殊字符报错。查阅了很久,终于自个解决了,写下来以防忘记。
一、使用Runtime.getRuntime().exec执行linux命令没反应
1、直接使用Runtime.getRuntime().exec(String cmd)时不支持空白符和管道符"|"
例如,执行这样的命令就不会有反应:
String cmd = "chown -R test:test test/";
// 或
String cmd2 = "netstat -antup | grep ftp";
Process ps = Runtime.getRuntime().exec(cmd);
ps.waitFor();
...
经过多次失败后,我理解为:
传参为String类型时,命令不能带有空格或管道符,否则会被截断,这样就不能执行了;
想要执行复杂点的命令,使用重载的方法public Process exec(String [] cmdArray):
String cmd = "chown -R test:test test/";
// 或
String cmd2 = "netstat -antup | grep ftp";
Process ps = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd});
ps.waitFor();
...
其中-c表示cmd是一条命令,从而不会被截断,我用此方法执行成功!
2、关于使用Runtime.getRuntime().exec执行文件操作时报以下错的问题解决
情景是这样,我在调用linux命令进行文件删除操作时,由于文件名含有英文"(“或”)",这在linux的命令中本来就有特殊含义,需要转义,然后我是这么测试的:
// 命令为rm -f (1)李柄桦(SlaughterKing)-so weak(female voice mix).mp3
String cmd = "rm -f \\(1\\)李柄桦\\(SlaughterKing)-so weak(female voice mix).mp3";
System.out.println(cmd);
这个的输出结果为"rm -f (1)李柄桦(SlaughterKing)-so weak(female voice mix).mp3",没有报错,我就认为把文件名中的每个英文"(“和”)“用replaceAll方法替换成”\\(“和”\\)",从而传入调用了,结果报以上的错误。
后来查阅了解到,replaceAll方法替换字符时用的是正则匹配,有个捕获组的概念使用了小括号,因此当正则表达式解析到左括号时,没有发现匹配的右括号,就会报错。
知道了原因,就这样处理:
// 命令为rm -f (1)李柄桦(SlaughterKing)-so weak(female voice mix).mp3
cmd = cmd.replaceAll("[(]", "\\\\(").replaceAll("[)]", "\\\\)");
System.out.println(cmd);
输出结果为"rm -f (1)李柄桦(SlaughterKing)-so weak(female voice mix).mp3",没有报错。这样在文件名是个变量时,就都可以用这个方法转义,再传入函数调用,就能成功执行了。