web-dev-qa-db-ja.com

INTとERRの両方をトラップしますが、コールバックが複数回実行されました

次のコードでINTとERRの両方をトラップしています

set -ex -o pipefail

dest=$(mktemp -d)
cd "$dest"

trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999

^Cを押すと、クリーンアップコールバックが複数回実行されます

++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo

++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516

それは予想される動作ですか?一度だけ実行することはできますか?

4
daisy

bashでは、これをtrap "my-cleanup-command" EXITに置き換えるだけです。このトラップは、スクリプトがSIGINTで送信されたかどうかを含め、スクリプトが終了したときに実行されます。私の意見では、これは通常、よりエレガントなアプローチです...

それがbash固有であるという事実を除いて。 EXITトラップはPOSIXで言及されていますが、動作は指定されていません。他の多くのシェルでは、信号が原因でシェルが終了した場合、EXITトラップは実行されません。

https://unix.stackexchange.com/a/57960/2948

時々私はシェルスクリプトが本当に嫌いです:)。


リンクされた回答を見ると、最初のトラップの後にコードが実行されないようにするためのbash固有の方法は、すぐに終了することだと思います。これを行うにはさまざまな方法があるようですが、これが私が試す最も簡単な方法です。

cleanup() {
    echo "Clean up"
    rm -rf "$dest"
}
trap cleanup EXIT
trap "exit 1" INT ERR
1
sourcejedi