私のbashコードには多くの出口点があります。出口でクリーンアップ作業を行う必要があるため、トラップを使用して、次のように出口のコールバックを追加しました。
trap "mycleanup" EXIT
問題は、さまざまな終了コードがあることです。対応するクリーンアップ作業を行う必要があります。mycleanupで終了コードを取得できますか?
受け入れられた答えは基本的に正しいです、私はただ物事を明確にしたいです。
次の例はうまく機能します。
#!/bin/bash
cleanup() {
rv=$?
rm -rf "$tmpdir"
exit $rv
}
tmpdir="$(mktemp)"
trap "cleanup" EXIT
# Do things...
ただし、関数を使用せずにインラインでクリーンアップを実行する場合は、さらに注意する必要があります。たとえば、これは機能しません。
trap "rv=$?; rm -rf $tmpdir; exit $rv" EXIT
代わりに、変数$rv
と$?
変数をエスケープする必要があります。
trap "rv=\$?; rm -rf $tmpdir; exit \$rv" EXIT
$tmpdir
トラップラインが実行されたときに評価され、tmpdir
後で値が変更された場合に期待される動作が得られない可能性があるため、エスケープすることもできます。
編集:shellcheckを使用してbashスクリプトをチェックし、このような問題に注意してください。
$?
終了コードを取得するために使用できると思います。
EXITトラップを他の信号のトラップから分離する方が良いことがわかりました
トラップテストスクリプトの例...
umask 77
tmpfile=`tmpfile.$$`
trap 'rm -f "$tmpfile"' EXIT
trap 'exit 2' HUP INT QUIT TERM
touch $tmpfile
read -r input
exit 10
一時ファイルがクリーンアップされます。10のファイル終了値が保持されます!割り込みの結果、終了値は2になります
基本的に、EXITトラップで「exit」を使用しない限り、元の終了値が保持された状態で終了します。
ASIDE:EXITトラップの引用符に注意してください。これにより、スクリプトの存続期間中にクリーンアップする必要のあるファイルを変更できます。$ tmpfileを削除する前に、その存在のテストを含めることもよくあります。そのため、スクリプトの開始時に設定する必要はなく、作成する前にのみ設定する必要があります。
次のコードはうまく機能します。終了コードを保管し、トラップ関数の各終了コードに必要なコマンドを定義できます。
#!/bin/bash
trap cleanup EXIT
cleanup() {
exit_code=$?
if [[ ${exit_code} -eq 1 ]]; then
# command 1
elif [[ ${exit_code} -eq 2 ]]; then
# command 2
elif [[ ${exit_code} -eq 2 ]]; then
# command 2
fi
}