通过 Runtime.exec() 执行管道 ps unix 命令
Issue executing a piped ps unix command through Runtime.exec()
问题:
当通过 Runtime.exec(...)
执行以下命令时,它在寻找匹配的引号字符时失败并出现意外的 EOF。
一个奇怪的地方是错误消息有一个严重的字符后跟两个单引号。
但是,当我通过putty执行在日志中打印出来的命令时,它工作正常。
命令:
bin/sh -c 'ps -eo uname,pid,ppid,nlwp,pcpu,pmem,psr,start_time,tty,time,args | fgrep IAAPC | fgrep /f1/f2/a00-a/f3/server/server_1/env_1/javadriver | fgrep -v fgrep'
产生的错误:
-eo: -c: line 0: unexpected EOF while looking for matching `''
-eo: -c: line 1: syntax error: unexpected end of file
Java代码(Java1.6 ...不要判断):
String driverHome = trimToEmpty(System.getProperty("batchdriver.home"));
String cmd = "/bin/sh -c 'ps -eo uname,pid,ppid,nlwp,pcpu,pmem,psr,start_time,tty,time,args | fgrep "+jobName+" | fgrep "+driverHome+" | fgrep -v fgrep'";
String out = null, err = null;
Process proc = null;
try {
proc = Runtime.getRuntime().exec(cmd);
out = fullyRead(proc.getInputStream());
err = fullyRead(proc.getErrorStream());
int exitVal = proc.waitFor();
if(logger.isDebugEnabled()) {
logger.debug("Process Information: "+out);
}
if (isNotEmpty(err)) {
logger.error(failedCommandMessage(cmd, out, err));
this.processId = null;
this.processDesc = PROCESS_NOT_FOUND;
return;
}
String[] processes = StringUtils.split(out, "\r?\n");
if (processes == null || processes.length == 0) {
this.processDesc = PROCESS_NOT_FOUND;
}
else if (processes.length == 1) {
String[] processInfo = processes[0].split("\s+");
this.processId = processInfo[1];
if (!isNumeric(this.processId)) {
this.processId = null;
}
this.processDesc = out;
}
else {
this.processDesc = out;
}
if (logger.isDebugEnabled()) {
logger.debug("Call to the OS completed with exit value: " + exitVal);
}
} catch (Exception e) {
try {out = fullyRead(proc.getInputStream());} catch (Exception e1) {}
try {err = fullyRead(proc.getErrorStream());} catch (Exception e1) {}
this.processId = null;
this.processDesc = PROCESS_NOT_FOUND;
logger.error(failedCommandMessage(cmd, out, err), e);
}
相关但不完全欺骗:
The Runtime.exec
methods that take a String
break it into tokens at whitespace only 所以这实际上是 运行 程序 /bin/sh
(a shell) 具有以下参数:
-c
'ps
-eo
uname,pid,ppid,nlwp,pcpu,pmem,psr,start_time,tty,time,args
|
fgrep
...
shell 像这样解释这些参数:
-c 'ps -- the script to run consists of the apostrophe character, p, s (and nothing more)
-eo -- the name of the command being run is -eo
uname,pid,.... -- the first argument to the script is this
| -- the second argument to the script is this
fgrep -- the third argument to the script is this
...
-- but the script ignores the arguments and doesn't use them
这样你就得到了
-eo: -c: unexpected EOF while looking for matching `''
# the script named -eo, with the option -c having value 'ps,
# tried to find a closing ' to match the opening ' and it's not there
这 shell 显然是 (GNU) bash;许多将数据字符串放入错误消息中的 GNU 程序用反引号和撇号将其括起来,因为这些是几十年前流行的一种 ASCII 解释中的匹配引号。
而是使用 the String[]
overload of exec
为 shell 提供当您的上述命令行被 解析时获得的两个参数 shell而不是 StringTokenizer
:
String[] cmdary = {"/bin/sh", "-c", "ps -eo stuff | fgrep this | fgrep that | fgrep -v fgrep"};
... Runtime.getRuntime().exec(cmdary);
但不是 运行 宁三个 fgrep,你可以只 运行 ps
并将输入流读取为行并在 Java 中使用 [=21 测试它们=] 或类似的。此外,您向 ps
请求的大多数列永远不会用于您的匹配 或 结果,因此这只是浪费精力和混乱。
问题:
当通过 Runtime.exec(...)
执行以下命令时,它在寻找匹配的引号字符时失败并出现意外的 EOF。
一个奇怪的地方是错误消息有一个严重的字符后跟两个单引号。
但是,当我通过putty执行在日志中打印出来的命令时,它工作正常。
命令:
bin/sh -c 'ps -eo uname,pid,ppid,nlwp,pcpu,pmem,psr,start_time,tty,time,args | fgrep IAAPC | fgrep /f1/f2/a00-a/f3/server/server_1/env_1/javadriver | fgrep -v fgrep'
产生的错误:
-eo: -c: line 0: unexpected EOF while looking for matching `''
-eo: -c: line 1: syntax error: unexpected end of file
Java代码(Java1.6 ...不要判断):
String driverHome = trimToEmpty(System.getProperty("batchdriver.home"));
String cmd = "/bin/sh -c 'ps -eo uname,pid,ppid,nlwp,pcpu,pmem,psr,start_time,tty,time,args | fgrep "+jobName+" | fgrep "+driverHome+" | fgrep -v fgrep'";
String out = null, err = null;
Process proc = null;
try {
proc = Runtime.getRuntime().exec(cmd);
out = fullyRead(proc.getInputStream());
err = fullyRead(proc.getErrorStream());
int exitVal = proc.waitFor();
if(logger.isDebugEnabled()) {
logger.debug("Process Information: "+out);
}
if (isNotEmpty(err)) {
logger.error(failedCommandMessage(cmd, out, err));
this.processId = null;
this.processDesc = PROCESS_NOT_FOUND;
return;
}
String[] processes = StringUtils.split(out, "\r?\n");
if (processes == null || processes.length == 0) {
this.processDesc = PROCESS_NOT_FOUND;
}
else if (processes.length == 1) {
String[] processInfo = processes[0].split("\s+");
this.processId = processInfo[1];
if (!isNumeric(this.processId)) {
this.processId = null;
}
this.processDesc = out;
}
else {
this.processDesc = out;
}
if (logger.isDebugEnabled()) {
logger.debug("Call to the OS completed with exit value: " + exitVal);
}
} catch (Exception e) {
try {out = fullyRead(proc.getInputStream());} catch (Exception e1) {}
try {err = fullyRead(proc.getErrorStream());} catch (Exception e1) {}
this.processId = null;
this.processDesc = PROCESS_NOT_FOUND;
logger.error(failedCommandMessage(cmd, out, err), e);
}
相关但不完全欺骗:
The Runtime.exec
methods that take a String
break it into tokens at whitespace only 所以这实际上是 运行 程序 /bin/sh
(a shell) 具有以下参数:
-c
'ps
-eo
uname,pid,ppid,nlwp,pcpu,pmem,psr,start_time,tty,time,args
|
fgrep
...
shell 像这样解释这些参数:
-c 'ps -- the script to run consists of the apostrophe character, p, s (and nothing more)
-eo -- the name of the command being run is -eo
uname,pid,.... -- the first argument to the script is this
| -- the second argument to the script is this
fgrep -- the third argument to the script is this
...
-- but the script ignores the arguments and doesn't use them
这样你就得到了
-eo: -c: unexpected EOF while looking for matching `''
# the script named -eo, with the option -c having value 'ps,
# tried to find a closing ' to match the opening ' and it's not there
这 shell 显然是 (GNU) bash;许多将数据字符串放入错误消息中的 GNU 程序用反引号和撇号将其括起来,因为这些是几十年前流行的一种 ASCII 解释中的匹配引号。
而是使用 the String[]
overload of exec
为 shell 提供当您的上述命令行被 解析时获得的两个参数 shell而不是 StringTokenizer
:
String[] cmdary = {"/bin/sh", "-c", "ps -eo stuff | fgrep this | fgrep that | fgrep -v fgrep"};
... Runtime.getRuntime().exec(cmdary);
但不是 运行 宁三个 fgrep,你可以只 运行 ps
并将输入流读取为行并在 Java 中使用 [=21 测试它们=] 或类似的。此外,您向 ps
请求的大多数列永远不会用于您的匹配 或 结果,因此这只是浪费精力和混乱。