【问题标题】:Issue executing a piped ps unix command through Runtime.exec()通过 Runtime.exec() 执行管道 ps unix 命令的问题
【发布时间】:2018-01-17 05:08:20
【问题描述】:

问题:

当通过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 代码(Java 1.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);
    }

【问题讨论】:

  • 反引号、单引号、单引号只是这个工具输出它想要“引用”的项目的方式。不幸的是,许多其他工具也使用这种格式,但我想它可以避免在丢失的字符是"(可能还有其他)的情况下产生歧义。对于您的情况,您可以认为错误消息只是以"'"(dbl-quote,单引号,dbl-quote)结尾,而' 是有问题的字符。为什么会发生这种情况超出了我的工资等级。祝你好运!

标签: java unix runtime.exec java-6


【解决方案1】:

相关但不完全欺骗:Pass a string with multiple contiguous spaces as a parameter to a jar file using Windows command prompt called from a java program

The Runtime.exec methods that take a String 将其分解为标记 at whitespace only,因此这实际上运行带有以下参数的程序 /bin/sh(一个 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);

但是,您可以只运行ps 并将输入流作为行读取,然后使用String.contains 或类似方法在Java 中测试它们,而不是运行三个fgrep。此外,您向 ps 询问的大多数列将永远不会用于匹配的 结果,因此这只是浪费精力和混乱。

【讨论】:

  • 测试传递字符串数组,接下来。不想在 java 中处理 ps 命令的全部结果,因为有大量的记录,并且如果我不需要,将执行此命令的进程数量。一旦我们升级我们的 Java 版本,我将能够使用更好的工具,但现在这就是我所拥有的。
  • 使用字符串数组修复它。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
  • 2013-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多