Java exec() does not return expected resul

2020-02-06 02:51发布

I'm calling command line programs connected by pipes. All this works on Linux for sure.

My method:

protected String execCommand(String command) throws IOException {
    String line = null;
    if (command.length() > 0) {
        Process child = Runtime.getRuntime().exec(command);
        InputStream lsOut = child.getInputStream();
        InputStreamReader r = new InputStreamReader(lsOut);
        BufferedReader in = new BufferedReader(r);

        String readline = null;
        while ((readline = in.readLine()) != null) {
            line = line + readline;
        }
    }

    return line;
}

If I'm calling some cat file | grep asd, I'm getting the expected result. But not all commands works correctly. For example with this:

cat /proc/cpuinfo | wc -l

or this:

cat /proc/cpuinfo | grep "model name" | head -n 1 | awk -F":" '{print substr($2, 2, length($2))}

the method will return null. I'm guessing this problem depends on output formatting commands like head, tail, wc, etc. How I can work around this problem and get the final result of the output?

6条回答
虎瘦雄心在
2楼-- · 2020-02-06 03:03

Probably a little too late but for others looking for a solution, try this...

String[] cmd = {
                        "/bin/sh",
                        "-c",
                        "cat /proc/cpuinfo | wc -l"
                    };

Process process = Runtime.getRuntime().exec(cmd);

All the best..

查看更多
走好不送
3楼-- · 2020-02-06 03:05

Everyone who uses Runtime.exec should read this.

查看更多
\"骚年 ilove
4楼-- · 2020-02-06 03:08

It might be a good idea to check the error stream of the Process as well.

查看更多
Luminary・发光体
5楼-- · 2020-02-06 03:16

The quick-and-dirty thing to do would be:

command = "/bin/sh -c '" + command.replaceAll("'", "'\''") + "'"

Normally, you'll have to watch out for shell injection (i.e. someone sneaks "; rm -rf /;" into the command). But that's only an issue if part of the command can be supplied from some other user input.

The slow and painful approach would be to do the Bash piping yourself in Java. If you go down this road, you'll find out all the wonderful things that Bash gives you that's not directly available from Process.exec (pipes, redirection, compound commands, variable expansion, arithmetic evaluation, ...).

  1. Parse the command for | characters. Be sure to watch out for || and quoted strings.
  2. Spawn a new Process for every piped command.
  3. Create Threads that read the output from one command and write it to the input of the next command.
查看更多
叼着烟拽天下
6楼-- · 2020-02-06 03:23

The pipe (like redirection, or >) is a function of the shell, and so execing directly from Java won't work. You need to do something like:

/bin/sh -c "your | piped | commands | here"

which executes a shell process with the command line (including pipes) specified after the -c (in quotes).

Note also that you have to consume stdout and stderr concurrently, otherwise your spawned process will block waiting for your process to consume the output (or errors). More info here.

查看更多
闹够了就滚
7楼-- · 2020-02-06 03:25

Still didn't found proper solution to execute piped commands with Runtime.exec, but found a workaround. I've simply wrote these scripts to separate bash files. Then Runtime.exec calls these bash scripts and gets expected result.

查看更多
登录 后发表回答