4

私は、オペレーティングシステム上のプロセスには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を実装するにはどうすればよいですか。コマンドラインインタプリタがどのように機能するかについて、基本的なことを理解していないと思います...

(関連する主題について説明している記事へのリンクをいただければ幸いです。検索する運があまりありませんでした。最後の質問ですが、Windowsでは標準ストリームの扱いがほとんどのUnixライクなオペレーティングシステムとは異なりますか?)

4

3 に答える 3

4

c標準ライブラリを使用するプログラムは、関数isatty()を使用してttyデバイス(別名コマンドライン)と通信しているかどうかを判断できます。Bashはおそらく、ttyではなくパイプと通信していることを検出し、プロンプトを出力しません。

于 2010-09-05T05:37:00.783 に答える
1

私は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システムコールを参照)、入力が非対話型であると想定して、巨大な(4K以上の)チャンクにバッファリングします。それが役立つかどうかはわかりませんが、-iフラグを使用してbashを開始してみてください。

于 2010-09-05T05:29:06.660 に答える
1

インタラクティブモードであることは、標準ストリームが使用されていないことを意味するものではありません。ただし、この場合、Bashは対話型モードで実行されている可能性があります(ターミナルアプリと直接通信していないことを検出しているため、プログラムで使用されていると見なされるため、ウェルカムバナーは印刷されません)。この場合、標準ストリームが引き続き使用され、何も出力されていないだけです。

ergosysが指摘したように、in.read(new byte[1024])1024バイト全体を読み取る前に戻ることに頼ることはできませんが、おそらく1バイトを読み取る前に戻ることはないと想定してもかまいませんが、私はこれがここでの問題だと思います。1バイトの出力も得られません。

「-i」をbashに渡して、インタラクティブモードで実行してみてください。

于 2010-09-06T07:00:08.110 に答える