“kill -PIPE $$”與“exit 1”有什麼區別?
在我的 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程序恢復 echoing3
。
kill -s PIPE "$$"
¹ 將 SIGPIPE 信號發送到執行目前解釋腳本的 shell 解釋器的程序。預設情況下,SIGPIPE 信號會導致程序終止,並且該程序已被 SIGPIPE 殺死的事實反映在其退出狀態中。所以在:
sh -c '(echo 1; kill -s PIPE "$$"; echo 2); echo 3'
SIGPIPE 信號由子shell 程序發送到其父程序(執行的那個
sh
)。該父程序將死亡並且不輸出3
,而子shell程序將繼續在後台執行並輸出2
。如果您在
bash
orzsh
shell(以及其他一些類似 Bourne 的 shell)中執行該命令,這些 shell 會將$?
參數(它們對最後一個命令的退出狀態的內部表示)設置為 141,即 128 + SIGPIPE ( 13 在大多數係統上)。現在 SIGPIPE 是系統向嘗試寫入沒有讀取端的管道或套接字(損壞的管道/套接字)的程序發送的信號,因此在此處發送它有點誤導。保留用於管理終止程序的信號是 SIGTERM,它恰好是
kill
預設發送的信號。現在,您可能想要使用 SIGPIPE 而不是 SIGTERM 的一個原因是,
bash
當它們的一項工作被信號終止時,有這樣的 shell 會輸出一條消息,而它們通常不會為 SIGPIPE 執行此操作(因為這對於程序被 SIGPIPE 終止,並不一定意味著存在類似 incmd | 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
在大多數係統上也應該可以使用)。