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