2011-03-15 6 views
31

bashコードには多くの終了点があります。私はいくつかの終了時に仕事をクリーンアップ実行する必要があるので、私はこのように、出口のコールバックを追加するためにトラップを使用:Bashスクリプトで終了コードをトラップする方法

trap "mycleanup" EXIT 

問題は別の終了コードがそこにいるですが、私はクリーンアップの作品を対応する実行する必要があります。 mycleanupで終了コードを取得できますか?

+0

トラップ 'foo' EXITまたはトラップ 'foo' CHLD? –

答えて

31

私は$?を使用して終了コードを取得できると思います。

+1

はい、正しいです。ありがとう! – Dagang

+2

@Todd: '$ BASH_COMMAND'と' $ BASH_LINENO'変数は時には便利です。 –

+4

@Todd、@bmk:実行された*コマンドが$?の値を変更することを忘れないでください。たとえば、myCmdIWantToTest;エコー$? ; myRC = $? ; ... myRCはエコー$の '真実'ですか? cmdが呼び出されます。 myCmdIWantToTestが「偽」を終了すると、その値は失われます。 $を保存するのが最善でしょうか?一意の別名varに変換します。 exitCode = $を使用していますか?普遍的に、他のcmdのexitCodeを継承することもできます(または、おそらくサブシェル(スクリプト)から継承することもできます)。また、ifの一部としてOKテスト終了コードであることを忘れないでください。その後、 ... fi。同様にmyCmdIWantToTest;エコーが働いた。そうでなければエコーは失敗したfi – shellter

25

受け入れられた答えは基本的に正しいです、私は物事を明確にしたいです。

#!/bin/bash 

cleanup() { 
    rv=$? 
    rm -rf "$tmpdir" 
    exit $rv 
} 

tmpdir="$(mktemp)" 
trap "cleanup" INT TERM EXIT 
# Do things... 

しかし、あなたはクリーンアップをインラインで行う場合は機能せず、より注意する必要があります:

次の例ではうまく動作します。たとえば、これは動作しません。

trap "rv=\$?; rm -rf $tmpdir; exit \$rv" INT TERM EXIT 
あなたはまた、それが評価されますよう、 $tmpdirを脱出したい場合があります

トラップライン:

trap "rv=$?; rm -rf $tmpdir; exit $rv" INT TERM EXIT 

は、代わりにあなたが$rv$?変数をエスケープする必要があります実行され、後でtmpdirの値が変更された場合、期待される動作が得られません。

編集:shellcheckを使用してbashスクリプトを確認し、このような問題に注意してください。

2

は私が...それは他の信号

例トラップテストスクリプトのためのトラップとは別の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 varablesの存在に関するテストも含むので、スクリプトの最初に設定する必要はありません。

関連する問題