コマンドライン通訳はどのように機能しますか?
-
01-10-2019 - |
質問
私は、オペレーティングシステムのプロセスには3つの標準ストリームがあるという印象を受けています。 stdin, stdout, and stderr
. 。また、VIMのようなテキスト編集者が入力して作業していると考えました。 stdin
ANSIエスケープキャラクターを送信します stdout
. 。ただし、コマンドライン通訳者がこの1つのケースでどのように耐えられないかについての私の見解
コマンドを実行するとき C:\cygwin\bin\bash.exe
, 、私は次のように求められています:
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\masson>C:\cygwin\bin\bash.exe
bash-3.2$
...しかし、次のスニペットでJavaで実行すると、Stdinストリームは空です。
ProcessBuilder pb = new ProcessBuilder("C:\\cygwin\\bin\\bash.exe");
pb.redirectErrorStream(true);
Process proc = pb.start();
final InputStream in = proc.getInputStream();
new Thread(new Runnable() {
public void run() {
// Blocks forever...
in.read(new byte[1024]);
}
}).start();
ここで何が起こっているのですか? bash.exeはインタラクティブモードで実行されていると言われています。これは、標準のストリームが使用されていないことを意味しますか?これらのプログラムで作業するにはどうすればよいですか?最終的には、独自のバージョンのcmd.exeを実装するにはどうすればよいですか?コマンドライン通訳者がどのように機能するかについての基本的なことを理解していないと思います...
(関連する主題について議論する記事へのリンクは非常に高く評価されます。私はあまり運がありませんでした。
解決
インタラクティブモードであることは、標準のストリームが使用されていないことを意味しません。しかし、この場合、バッシュはおそらく走っています 非-Iteractiveモード(端末アプリに直接話しかけていないことを検出しているため、プログラムで使用されていると仮定しているため、歓迎バナーを印刷しません)。この場合、標準のストリームはまだ使用されていますが、それはまさに出力されていないということです。
エルゴシスが指摘したように、あなたは本当に頼ることはできません in.read(new byte[1024])
完全な1024バイトを読む前に戻ることはおそらくそれがそうなると仮定しても大丈夫です - しかし、少なくとも1つのバイトを読む前にそれは確かに戻りません、そして、私はここで問題だと思います - あなたは偶数を得ていません1バイトの出力。
「-I」を渡して、インタラクティブモードで実行するようにしてみてください。
他のヒント
C標準ライブラリを使用するプログラムは、関数ISATTY()を使用してTTYデバイス(別名コマンドライン)と話しているかどうかを判断できます。 Bashは、おそらくTTYの代わりにパイプと話していることを検出し、プロンプトを出力しないことを検出します。
私はJavaの男よりもPythonの男です(だから私があなたに言うことはすべてJavadocからの迅速な推測です)が、あなたはマルチプロセスのデッドロックを設定しているようです。
in.read(new byte[1024]);
1024バイトのデータを読み取るまで戻りません bash.exe
入力を待つために停止する前に、1024バイト全体を出力しません。 (それを行うには、使用してください proc.getOutputStream()
そして、応答するためにいくつかのコマンドを与えてください。)
その結果、JavaはBashが応答するのを待っていて、BashがJavaが応答するのを待っており、両方が退屈したり疲れたりせずに宇宙の死まで待つのを完璧に満足させます。
私のアドバイスは使用することです in.available()
通話ごとに in.read()
ブロッキングを避けるため。そうすれば、給餌データを供給することとそれを引っ張らずに引き抜くことを前後に切り替えることができます。
実際、それを包むだけではるかにシンプルで賢いでしょう BufferedReader
.
コメントからの更新: また、BashのようなツールがStdinが端末ではないことを検出した場合(Isatty System Callを参照)、 彼らはバッファします 入力が非相互作用であるという仮定で、巨大な(4K以上)チャンク。それが助けになるかどうかはわかりませんが、-iフラグでバッシュを始めてみてください。