web-dev-qa-db-ja.com

パイプを閉じるときに早く終了する方法は?

複雑すぎてbash関数として表現できないプログラムを作成するためにgolangを使用します。プログラムはstdinを1行ずつ読み取り、変更された出力をstdoutに書き込みます。

Stdinアプローチのすべての行でこの反復を行う場合の問題は、早期に終了しないことです。たとえば、次のコマンドは、10行だけでなくすべての行を処理します。

cat largefile | custom-program | head -n 10

ネイティブUNIXアプリケーションはどのようにして早期に終了することができますか?また、カスタムスクリプトで同じことを行うにはどうすればよいですか?

4
Kshitiz Sharma

yes | headでは、yesは、次にパイプのもう一方の端が閉じられた後にラインを書き込むときに(headが存在する場合)、SIGPIPEシグナルによって終了します。

に:

(seq 20; sleep 10; seq 10) | head

サブシェルと子は、最初の20行をパイプに書き込むことができ(パイプバッファーに収まるように)、その後、無傷で10秒間スリープします。その間、headは消滅しますが、サブシェルがパイプにさらに行を書き込んだ場合にのみ、パイプが強制終了されます。

headが返された後に初めてパイプに何かを書き込むのではなく、headbashを使用してコマンドを強制終了したい場合は、次のようにできます。

{ head; kill "$!"; } < <(exec custom-program < large-file)

bashは、たまたまプロセス置換のpidを$!に格納します)。

より移植性の高いアプローチについては、(= /// =)Grepが一致を見つけた後に終了するのが遅いですか? 、または 出力を制限して、信号13 を回避してくださいfindに適用されます。

または、逆の場合 同様のQ&A に対するこの回答(run_under_watch関数)は、そのstdinパイプが壊れます。

12