「kill -PIPE $$」と「exit 1」の違いは何ですか?

「kill -PIPE $$」と「exit 1」の違いは何ですか?

私のBashスクリプトでは、次の構文を使用してBashスクリプトを終了します。

kill -PIPE $$

場合によっては、スクリプトの関数や内部シェル内でexit 1Bash スクリプトが実際に終了しないため、これを使用します。

だからkill私はexit 1

そうだ

exit 1

そして

kill -PIPE $$

ほぼ同じです。私の仮定は本当ですか?

第二に、kill -PIPE $$この構文を使用すると危険がありますか?

答え1

exit 1たとえば、終了コード 1 を使用して現在のサブシェル環境を終了します。

sh -c '(echo 1; exit 1; echo 2); echo 3'

これにより、exit 1サイドでコードを実行するサブシェルがシャットダウンされるため、出力はなく、(...)2シェルプロセスはエコーを再開します3

kill -s PIPE "$$"1現在スクリプトを解釈しているシェルインタプリタを実行しているプロセスにSIGPIPE信号を送信します。デフォルトでは、SIGPIPE信号はプロセスを終了し、プロセスがSIGPIPEによって終了したという事実が終了状態に反映されます。

だから:

sh -c '(echo 1; kill -s PIPE "$$"; echo 2); echo 3'

SIGPIPE信号は、サブシェルプロセスから親プロセス(実行プロセスsh)に送信されます。親プロセスは終了し、出力は生成されませんが、3サブシェルプロセスはバックグラウンドで実行され続け、出力を生成します2

bashzshまたは、シェル(およびBourneなどの他のシェル)でコマンドを実行すると、そのシェルは引数$?(最後のコマンドの終了状態の内部表現)を128 + SIGPIPE(ほとんどのシステム)である141と同じに設定します。上は13)である。

今、SIGPIPEは、読み込み終了(壊れたパイプ/ソケット)のないパイプやソケットに書き込もうとするプロセスにシステムが送る信号なので、ここに送るのは少し誤解を招くことがあります。プロセスの管理終了のために予約された信号はSIGTERMであり、デフォルトで送信されるkill信号です。

SIGTERMの代わりにSIGPIPEを使用したい理由の1つは、ジョブの1つがシグナルbashによって終了したときにメッセージを印刷する同様のシェルがあり、通常はSIGPIPEではそうしないことです。 SIGPIPE によって終了されるプロセスに有用であっても必ずしも のcmd | head -n 1ような問題があるという意味ではないため、SIGPIPE を使用することがこれらのメッセージを防止する 1 つの方法です。

bash-4.4$ /bin/kill 0
Terminated
bash-4.4$ /bin/kill -s PIPE 0
bash-4.4$

非対話型の場合でも:

$ bash -c 'sh -c "kill \$\$"; exit'
bash: line 1:  6665 Terminated              sh -c "kill \$\$"
$ bash -c 'sh -c "kill -s PIPE \$\$"; exit'
$

1ここに追加周囲に引用符がありません。$$信頼性と使用のため標準(POSIXではオプションではありません) kill -s PIPE移植性構文(kill -PIPEほとんどのシステムでも機能しますが)

関連情報