はい、中bash
にあるようなksh
(機能はどこから来る)、プロセス置換内部のプロセスは(スクリプトの次のコマンドを実行する前に)を待っていません。
以下のために<(...)
、通常は罰金のようです1:
cmd1 <(cmd2)
シェルは、パイプ上のファイルの終わりが置換されるまで読み取りcmd1
をcmd1
行うため、通常待機しcmd2
ます。また、ファイルの終わりは、通常、終了時に発生しcmd2
ます。それは、いくつかのシェル(ではないが、同じ理由ですbash
)を待っている気にしないでくださいcmd2
の中でcmd2 | cmd1
。
以下のためには、cmd1 >(cmd2)
それはより多くのだとして、しかし、それは、一般的ケースではありませんcmd2
ため、通常は待機するcmd1
ので、一般的に後が終了します。
で固定だとzsh
するためにその待機cmd2
(ただし、あなたのようにそれを書く場合があるcmd1 > >(cmd2)
とcmd1
、組み込みされていない使用{cmd1} > >(cmd2)
の代わりとして文書化を)。
ksh
デフォルトでは待機しませんが、wait
組み込みで待機することができます(でpidを使用できるようにしますが$!
、実行した場合は役に立ちませんcmd1 >(cmd2) >(cmd3)
)
rc
(cmd1 >{cmd2}
構文を使用)、ksh
すべてのバックグラウンドプロセスのPIDを取得できることを除いて、と同じです$apids
。
es
(また付きcmd1 >{cmd2}
待ち)cmd2
などでzsh
も、そして待つcmd2
における<{cmd2}
プロセスリダイレクト。
bash
のpid cmd2
(またはサブシェルcmd2
の子プロセスで実行されるサブシェルの最後のコマンドであってもより正確に)をで使用可能にしますが$!
、待機させることはできません。
を使用する必要がある場合bash
、両方のコマンドを待機するコマンドを使用して問題を回避できます。
{ { cmd1 >(cmd2); } 3>&1 >&4 4>&- | cat; } 4>&1
それは両方になりcmd1
やcmd2
パイプへのFD 3が開いています。cat
もう一方の端にエンド・オブ・ファイルをお待ちしておりますので、通常時にのみ、両方終了するcmd1
とcmd2
死んでいます。そして、シェルはそのcat
コマンドを待ちます。あなたはすべてのバックグラウンドプロセスの終了をキャッチするネットとして見ることができます(&
、coprocs、またはデーモンが通常行うようにすべてのファイル記述子を閉じない限り、バックグラウンドで実行されるコマンドなど、バックグラウンドで開始された他のものに使用できます) )。
その無駄なサブシェルプロセスのおかげでそれがあっても動作しますが、上記のことを注意cmd2
そのFD 3閉じて(コマンドは通常はそれをしませんが、いくつかのようなsudo
またはssh
ください)。の将来のバージョンでbash
は、最終的に他のシェルと同様にそこで最適化が行われる可能性があります。次に、次のようなものが必要になります。
{ { cmd1 >(sudo cmd2; exit); } 3>&1 >&4 4>&- | cat; } 4>&1
そのsudo
コマンドを待っているfd 3を開いたままのシェルプロセスがまだあることを確認します。
cat
(プロセスはfd 3に書き込まないため)何も読み込まないことに注意してください。同期のためだけにあります。read()
最後に何も返さないシステムコールを1つだけ実行します。
cat
コマンド置換を使用してパイプの同期を実行することで、実際に実行を回避できます。
{ unused=$( { cmd1 >(cmd2); } 3>&1 >&4 4>&-); } 4>&1
今回は、シェルの代わりにcat
、パイプの読み取りが行われ、パイプのもう一方の端はfd 3 cmd1
およびで開かれcmd2
ます。変数の割り当てを使用しているため、終了ステータスはcmd1
で利用可能です$?
。
または、手動でプロセスの置換を行うこともできますし、システムのsh
標準的なシェル構文として使用することもできます。
{ cmd1 /dev/fd/3 3>&1 >&4 4>&- | cmd2 4>&-; } 4>&1
ただし、前述のように、すべてのsh
実装が終了cmd1
後に待機するわけではないことに注意してくださいcmd2
(ただし、他の方法よりも優れています)。その時間に$?
は、の終了ステータスが含まれcmd2
ます。しかしbash
やzsh
メイクcmd1
で利用できるの終了ステータス${PIPESTATUS[0]}
と$pipestatus[1]
それぞれ(も参照pipefail
ので、いくつかのシェルでオプションを$?
最後以外のパイプ部品の失敗を報告することができます)
yash
プロセスリダイレクト機能にも同様の問題があることに注意してください。そこcmd1 >(cmd2)
に書かれcmd1 /dev/fd/3 3>(cmd2)
ます。しかしcmd2
、待つことはできずwait
、待つこともできず、そのpidも$!
変数で利用できません。と同じ回避策を使用しbash
ます。