出力リダイレクトとプロセス置換の実験中に、偶然に次のコマンドとその結果の出力が見つかりました。
me@elem:~$ echo foo >>(cat);echo 列 バー 私 @elem:~$ foo
(はい、最後に空白の改行は意図的なものです。)
したがって、bash echoのバーは一般的なプロンプト、echoのfoo、echoの改行を印刷し、そこにカーソルを置きます。もう一度Enterを押すと、新しい行にプロンプトが表示され、その後にカーソルが残ります(誰かが空のコマンドラインでEnterを押したときに期待どおり)。
私はファイル記述子にfooを書き、catを読んでfooをエコーし、2番目はecho barに書き込んでからコマンドプロンプトに戻ることを期待しています。しかし、これは明らかに真実ではありません。
何が起こっているのかを説明できる人はいますか?
答え1
時間に応じて、プロンプトの前foo
、bar
後、または後にコンテンツが表示されることがあります。bar
一貫したタイミングのために少しの遅延を追加します。
$ echo foo > >(sleep 1; cat); echo bar; sleep 2
bar
foo
$
bar
すぐに表示され、foo
1秒後に表示され、1秒後に次のプロンプトが表示されます。
何が起こるかは、bashがバックグラウンドでプロセス交換を実行することです。
- 基本的なbashプロセスは実行のためにサブシェルを起動し、
sleep 1; cat
それらのパイプを設定します。 - 基本bashプロセスが実行されます
echo foo
。これはパイプのバッファを埋めないため、echo
コマンドはブロックせずに終了します。 - 基本bashプロセスが実行されます
echo bar
。 - 基本bashプロセス開始コマンド
sleep 2
。 - 同時に、サブシェルはコマンドを実行します
sleep 1
。 - 約1秒後に
sleep 1
子プロセスに戻ります。サブプロセスは引き続き実行されますcat
。 cat
入力を出力(画面に表示)にコピーし、その逆にコピーします。- サブシェルが操作を終了して終了します。
- 1秒後に
sleep 2
戻ってください。デフォルトのシェルプロセスが実行を完了し、次のプロンプトが表示されます。
答え2
この効果を得るためにプロセスを交換する必要はありません。この試み:
( echo foo | cat & )
ほとんど同じ結果が得られ(何もありませんbar
。練習のままにします)、同じ理由があります。どちらの場合も、cat
バックグラウンドジョブから始まります。私の場合、これは明らかです。プロセス置換の場合も明確です(名前ファイル記述子に添付されている別のプロセスです)。しかし、それほど明確ではないかもしれません。
bash
次のプロンプトを印刷する前に、子プロセスが必ずしも終了するわけではありません。出力はバッファリングされるため、終了するまでは何も出力されません。この時点で、bash は stderr に印刷されただけで、印刷とラップの後に$
バックグラウンド プロセスが終了します。foo