これは、現在のディレクトリに一時ディレクトリを設定し、終了時に削除するようにトラップを設定する簡単なスクリプトです。
#filename: script
set -x
trap 'rm -rf "$d"' exit
d=`TMPDIR=$PWD mktemp -d`
"$@"
ksh script sleep 100
orを実行しbash script sleep 100
て中断すると、C-C
トラップが実行され、ディレクトリが削除されます。動作しませんdash
。なぜですか?これはバグですか、それとも意図的な動作ですか?
答え1
zsh
、(pdksh
最新バージョンではありませんが)Bourneシェルは。mksh
yash
dash
bash
、ksh88
その他の操作のみ可能ですksh93
。mksh
SIGINT
POSIX仕様では正しい動作が何であるかは不明ですが、シェルがシグナルのデフォルトハンドラをオーバーライドすることを許可するものはありません。
EXIT
トラップ操作は呼び出されたときに評価する必要があると言いますが、私が知っている限り、たとえば構文エラーや特殊な組み込みなどのエラー条件のためにシェルが終了したexit
ときに評価する必要はありません。機能障害時)。set -e
set -u
シグナルを受信した後にトラップを実行できるようにするには、シェルがシグナルEXIT
にハンドラーをインストールする必要があります。
それがまさにksh
、mksh
そしてすることですが、bash
彼らが処理する信号のリストは3つの実装間で異なります。 3 つの実装間の唯一の共通信号は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
これで、実行中により多くの信号が到着すると、再度cleanup
実行cleanup
される可能性があります。cleanup
ジョブが複数回呼び出された場合、または実行中にシグナルが無視される場合は、ジョブが正しく実行されていることを確認できます。
答え2
警告:exit
動作は保証されません。EXIT
POSIX標準は、EXIT
信号があるときにトラップを実行するかどうかを定義せず、Bourne Shellが緊急の状況EXIT
でトラップを呼び出さないことを考慮すると、次のように入力することは明らかです。指定されていないアクション。