Bash

dash vs ksh和bash中的退出陷阱

  • May 12, 2021

這是一個簡單的腳本,它在目前目錄中設置一個臨時目錄,並在退出時設置一個陷阱來刪除它。

#filename: script   
set -x  
trap 'rm -rf "$d"' exit
d=`TMPDIR=$PWD mktemp -d`
"$@"

如果我這樣做ksh script sleep 100orbash script sleep 100並用, 中斷它C-C,則陷阱將被執行並刪除目錄。它不適用於dash. 為什麼?這是錯誤還是預期行為?

zsh, pdksh(雖然不是mksh從那個派生的最新版本), yash, Bourne shell 的行為類似於dash.

只有bash,ksh88ksh93否則mksh行為。

POSIX 規範不清楚什麼應該是正確的行為,但其中沒有任何內容表明允許 shell 覆蓋SIGINT(或其他)信號的預設處理程序。

它說EXIT陷阱動作應該在exit被呼叫時進行評估,但是AFAICT,它甚至沒有說例如當shell由於語法錯誤或失敗的特殊內置函式等錯誤條件而退出時是否應該評估set -eset -u

為了能夠EXIT在接收到信號時執行陷阱,shell 需要在該信號上安裝一個處理程序。

就是這樣做的ksh,但是它們處理的信號列表在所有三種實現中都不同。三者之間唯一共同的信號似乎是、、和。mksh``bash``INT``QUIT``TERM``ALRM``HUP

如果您希望EXIT陷阱在某些信號上執行,可移植的方法是自己處理這些信號:

trap 'exit 1' INT HUP QUIT TERM ALRM USR1
trap 'cleanup' EXIT

但是,該方法不適用於,如果從陷阱處理程序呼叫zsh,則不會執行陷阱。EXIT``exit

它也無法向您的父母報告您的死亡信號。

因此,您可以這樣做:

for sig in INT QUIT HUP TERM ALRM USR1; do
 trap "
   cleanup
   trap - $sig EXIT
   kill -s $sig "'"$$"' "$sig"
done
trap cleanup EXIT

現在,請注意,如果在您執行時有更多信號到達cleanupcleanup可能會再次執行。cleanup如果多次呼叫和/或在執行期間忽略信號,您可能希望確保您的工作正常。

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