1

在 bash 脚本中,如果我执行“内联”执行的外部程序(即“bash”)。我的意思是该进程不在后台跨越,并且子进程的 stdin/stdout/stderr 与 bash 脚本本身的一个一致。

所以如果我的 bash 脚本包含

#!/bin/sh
bash

发生的情况是用户可以运行我的脚本,并且当执行 bash 时,他将能够在 bash 的标准输入中键入命令,并在 stdout/stderr 上查看命令的结果。

这就是我的意思是子进程是“内联”运行的。

在 java 中,进程在后台跨越,因此 Process.getOutputStream()/Process.getInputStream()/Process.getErrorStream 不是 System.in/System.out/System.err 的“内联”。

我想要在我的 java 程序中做的是重现当我执行一个进程时发生的行为,如上面的 bash 脚本示例所示。

经过一些谷歌搜索后,我得出了这个

public static void main(String[] args) throws IOException,
        InterruptedException {
    String[] cmdarray = {"bash"};
    Process proc = Runtime.getRuntime().exec(cmdarray);

    StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(),
            System.err);

    StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(),
            System.out);

    StreamGobbler inputGobbler = new StreamGobbler(System.in,
            proc.getOutputStream());

    errorGobbler.start();
    outputGobbler.start();
    inputGobbler.start();

    int exitVal = proc.waitFor();
    errorGobbler.join(); // Handle condition where the
    outputGobbler.join(); // process ends before the threads finish
    System.exit(exitVal);
}

class StreamGobbler extends Thread {
    InputStream is;
    OutputStream os;

    StreamGobbler(InputStream is, OutputStream os) {
        this.is = is;
        this.os = os;
    }

    public void run() {
        try {
            int c;
            while ((c = is.read()) != -1) {
                os.write(c);
                os.flush();
            }
        } catch (IOException x) {
            throw new RuntimeException(x);
        }
    }
}

但是,嘿,有 3 个线程!加上执行进程跨越的线程!

一定会有更好的办法。就像是:

Runtime.execForeground("bash", System.in, System.out, System.err);

要不就:

Runtime.execForeground("bash");

它执行“内联”过程,因为它适用于许多脚本语言。

也许另一种可能性是使用非阻塞 I/O 在单个线程中将 stdin/stdout/stderr 复制到 System.in/out/err?有什么例子吗?

4

0 回答 0