「インライン」で実行される外部プログラム(つまり「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 にコピーすることですか? 例はありますか?