Linux

“kill -PIPE $$”與“exit 1”有什麼區別?

  • November 23, 2018

在我的 Bash 腳本中,我使用以下語法來退出 Bash 腳本:

kill -PIPE $$

我使用它是因為有時在腳本的函式或內部 shell 中,它exit 1並沒有真正退出 Bash 腳本。

所以我使用kill而不是exit 1.

看起來

exit 1

kill -PIPE $$

幾乎相等。我的假設是真的嗎?

其次-關於kill -PIPE $$,使用該語法是否有風險?

exit 1以退出程式碼 1 退出目前子 shell 環境,例如:

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

exit 1退出執行程式碼的子shell,因此(...)2輸出,並且父shell程序恢復 echoing 3

kill -s PIPE "$$"¹ 將 SIGPIPE 信號發送到執行目前解釋腳本的 shell 解釋器的程序。預設情況下,SIGPIPE 信號會導致程序終止,並且該程序已被 SIGPIPE 殺死的事實反映在其退出狀態中。

所以在:

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

SIGPIPE 信號由子shell 程序發送到其父程序(執行的那個sh)。該父程序將死亡並且不輸出3,而子shell程序將繼續在後台執行並輸出2

如果您在bashor zshshell(以及其他一些類似 Bourne 的 shell)中執行該命令,這些 shell 會將$?參數(它們對最後一個命令的退出狀態的內部表示)設置為 141,即 128 + SIGPIPE ( 13 在大多數係統上)。

現在 SIGPIPE 是系統向嘗試寫入沒有讀取端的管道或套接字(損壞的管道/套接字)的程序發送的信號,因此在此處發送它有點誤導。保留用於管理終止程序的信號是 SIGTERM,它恰好是kill預設發送的信號。

現在,您可能想要使用 SIGPIPE 而不是 SIGTERM 的一個原因是,bash當它們的一項工作被信號終止時,有這樣的 shell 會輸出一條消息,而它們通常不會為 SIGPIPE 執行此操作(因為這對於程序被 SIGPIPE 終止,並不一定意味著存在類似 in cmd | head -n 1) 中的問題,因此使用 SIGPIPE 是避免這些消息的一種方法。

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在大多數係統上也應該可以使用)。

引用自:https://unix.stackexchange.com/questions/478281