web-dev-qa-db-ja.com

シェルコマンド(スクリプトではない)で「確実に」/「最終的に」機能を取得していますか?

コマンドが成功したか失敗したかを知り、無条件で後でクリーンアップを実行する必要があります。

順次コマンドを実行するための通常のオプションはどちらもここでは適用できないようです。

$ 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

コマンドラインでこれを実現するための慣用的な方法はありますか?

6
Ian

スクリプトの改行は、ほとんど常にセミコロンと同等です。

mycmd.sh; ret=$?; rm -rf temp_files; exit $ret

編集に応じて:

あるいは、trapとサブシェルを使用することもできます。

( trap 'rm -rf temp_files' EXIT; mycmd.sh )
11
PSkocik

一部の言語のコピーをお探しの場合は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=$?

trapコマンドの引数についてお読みください。

cleanupが呼び出されることに注意してください:

  • このスクリプトがSIGINTまたはSIGTERMに送信された場合、またはCTRL-Cが押された場合(SIGINT)
  • このスクリプトが0で正常に終了する場合
  • mycmd.shがゼロ以外のステータスで終了する場合(おそらく、期待どおりではありません-remove ERR from trap's arguments from disable
7
cat

zsh内:

{mycmd.sh} always {rm -rf temp_files}

alwaysの部分は、一致のないグロブのようなエラーやスクリプトを終了するランタイム構文エラーの場合でも実行されます。

3
mycmd.sh && { rm -r temp_files;  true; } || { rm -r temp_files; false; }
1
user218374

現在、&&演算子の代わりに||演算子とif;then演算子のみを使用しています。しかし、「if; then」に戻る方がはるかに明確な場合もあります。コマンドラインソリューションが必要なため、これはその1つです。

このように書き直します...

$ if mycmd.sh; then { success; actions; } else { fail; actions; } fi;  rm -rf temp_files/
  • mycmd.shが実行され、ifがその結果を使用します
  • 中括弧は、内部の複数のコマンドのリストが1つのブロックとして処理されることを保証し、それらが明瞭さを高めます。中括弧とセミコロンの周りのスペースは、最後のコマンドを含め、中の各コマンドの後に必須です。
  • rmfiの後に発生するため、無条件に実行されます。
0
DocSalvager