コマンドが成功したか失敗したかを確認し、いくつかのクリーンアップ操作を無条件に実行する必要があります。
順次コマンドを実行するための一般的なオプションはここには適用されないようです。
$ mycmd.sh && rm -rf temp_files/ # correct exit status, cleanup fails if mycmd fails
$ mycmd.sh ; rm -rf temp_files/ # incorrect exit status, always cleans up
$ mycmd.sh || rm -rf temp_files/ # correct exit status, cleanup fails if mycmd succeeds
シェルスクリプトでこれを行うには、次の手順を実行します。
#!/usr/bin/env bash
mycmd.sh
RET=$?
rm -rf temp_files
exit $RET
これらのすべてのコマンドをセミコロンで連結するよりも、コマンドラインでこれを行うより慣用的な方法はありますか?
答え1
スクリプトの改行はほぼ常にセミコロンと同じです。
mycmd.sh; ret=$?; rm -rf temp_files; exit $ret
編集者への回答:
trap
または、次のようにサブシェルを使用できます。
( trap 'rm -rf temp_files' EXIT; mycmd.sh )
答え2
いくつかの言語のコピーを探している場合は、try { } finally { }
他の方法があります。trap
組み込みシェルbash
と他のPOSIXyシェルを使用することです(参考資料を参照help trap
)。
#!/bin/bash
# exit with this by default, if it is not set later
exit_code=0
# the cleanup function will be the exit point
cleanup () {
# ignore stderr from rm incase the hook is called twice
rm -rf "temp_files/" &> /dev/null
# exit(code)
exit $exit_code
}
# register the cleanup function for all these signal types (see link below)
trap cleanup EXIT ERR INT TERM
# run your other script
mycmd.sh
# set the exit_code with the real result, used when cleanup is called
exit_code=$?
cleanup
この名前は次のとおりです。
- このスクリプトをSIGINTまたはSIGTERMに送信するか、CTRL-C(SIGINT)を押す
- このスクリプトが正常に終了してゼロを返す場合
- mycmd.shがゼロ以外の状態で終了する場合(おそらく希望の状態ではない可能性があります -
ERR
無効にするには、トラップパラメータから削除します。)
答え3
存在するzsh
:
{mycmd.sh} always {rm -rf temp_files}
これいつもこのセクションは、エラー(たとえば、一致しないglobまたはランタイム構文エラー)が発生してスクリプトを終了した場合にも実行されます。
答え4
これで代わりに&&
and演算子を使用します。しかし、時には「if; then」に戻ることがより明確になることもあります。コマンドラインソリューションが必要なので、これはその1つです。||
if;then
このように書き直す...
$ if mycmd.sh; then { success; actions; } else { fail; actions; } fi; rm -rf temp_files/
- mycmd.sh を実行し、
if
その結果を使用します。 - 中括弧は、内部の複数のコマンドのリストがブロックとして扱われることを保証し、明瞭性を向上させる。各コマンド(最後のコマンドを含む)の後の中かっことセミコロンの周りのスペースは必須です。
rm
後に発生するため、fi
無条件に実行されます。