80

java trycatchのようなLinuxbashコマンドはありますか?それとも、Linuxシェルは常に継続しますか?

try {
   `executeCommandWhichCanFail`
   mv output
} catch {
    mv log
} finally {
    rm tmp
}
4

6 に答える 6

129

あなたの例に基づくと、スクリプトがどのように終了するかに関係なく、常に一時ファイルを削除するのと同じようなことをしようとしているように見えます。Bashでこれを行うには、trap組み込みコマンドを試してEXIT信号をトラップします。

#!/bin/bash

trap 'rm tmp' EXIT

if executeCommandWhichCanFail; then
    mv output
else
    mv log
    exit 1 #Exit with failure
fi

exit 0 #Exit with success

rm tmpステートメントはtrap、スクリプトの終了時に常に実行されるため、ファイル「tmp」は常に削除されます。

インストールされているトラップもリセットできます。シグナル名のみでトラップを呼び出すと、シグナルハンドラーがリセットされます。

trap EXIT

詳細については、bashのマニュアルページを参照してください。man bash

于 2013-11-20T01:32:15.713 に答える
110

まあ、ある種:

{ # your 'try' block
    executeCommandWhichCanFail &&
    mv output
} || { # your 'catch' block
    mv log
}

 rm tmp # finally: this will always happen
于 2013-03-27T10:29:10.127 に答える
2

次の構文を使用して、スクリプトで成功を収めました。

# Try, catch, finally
(echo "try this") && (echo "and this") || echo "this is the catch statement!"

# this is the 'finally' statement
echo "finally this"

tryステートメントがエラーをスローするか、で終わるexit 1場合、インタープリターはcatchステートメントに移動し、次にfinallyステートメントに移動します。

両方のtryステートメントが成功した場合(および/またはで終了した場合exit)、インタープリターはcatchステートメントをスキップしてからfinallyステートメントを実行します。

Example_1:

goodFunction1(){
  # this function works great
  echo "success1"
}

goodFunction2(){
  # this function works great
  echo "success2"
  exit
}

(goodFunction1) && (goodFunction2) || echo "Oops, that didn't work!"

echo "Now this happens!"

Output_1

success1
success2
Now this happens!

例_2

functionThrowsErr(){
  # this function returns an error
  ech "halp meh"
}

goodFunction2(){
  # this function works great
  echo "success2"
  exit
}

(functionThrowsErr) && (goodFunction2) || echo "Oops, that didn't work!"

echo "Now this happens!"

Output_2

main.sh: line 3: ech: command not found
Oops, that didn't work!
Now this happens!

Example_3

functionThrowsErr(){
  # this function returns an error
  echo "halp meh"
  exit 1
}

goodFunction2(){
  # this function works great
  echo "success2"
}

(functionThrowsErr) && (goodFunction2) || echo "Oops, that didn't work!"

echo "Now this happens!"

Output_3

halp meh
Oops, that didn't work!
Now this happens!

関数の順序が出力に影響することに注意してください。両方のステートメントを別々に試行およびキャッチする必要がある場合は、2つのtrycatchステートメントを使用してください。

(functionThrowsErr) || echo "Oops, functionThrowsErr didn't work!"
(goodFunction2) || echo "Oops, good function is bad"

echo "Now this happens!"

出力

halp meh
Oops, functionThrowsErr didn't work!
success2
Now this happens!
于 2020-02-29T18:31:24.480 に答える
1

mv2つのパラメーターを受け取るので、出力ファイルの内容を実際に確認したい場合があります。

echo `{ execCommand && cat output ; } || cat log`
rm -f tmp
于 2013-03-27T10:30:43.233 に答える
0

それを行う別の方法は次のとおりです。

set -e;  # stop on errors

mkdir -p "$HOME/tmp/whatevs"

exit_code=0

(
  set +e;
  (
    set -e;
    echo 'foo'
    echo 'bar'
    echo 'biz'
  )
  exit_code="$?"
)

rm -rf "$HOME/tmp/whatevs"

if [[ "exit_code" != '0' ]]; then
   echo 'failed';
fi 

上記は実際には何のメリットもありませんが、

set -e;  # stop on errors

mkdir -p "$HOME/tmp/whatevs"

exit_code=0

(
    set -e;
    echo 'foo'
    echo 'bar'
    echo 'biz'
    exit 44;
    exit 43;

) || {
   exit_code="$?"  # exit code of last command which is 44
}

rm -rf "$HOME/tmp/whatevs"

if [[ "exit_code" != '0' ]]; then
   echo 'failed';
fi 
于 2020-01-23T22:12:02.783 に答える
0

警告:出口トラップは常に実行されるとは限りません。この回答を書いた後、出口トラップが実行されず、ファイルが失われる状況に遭遇しました。その理由はまだわかりません。

この問題は、Pythonスクリプトをで停止したときに発生しました。PythonスクリプトはCtrl+C、出口トラップを使用してbashスクリプトを実行しました。これにより、出口トラップがbashで実行されるため、実際には出口トラップが実行されSIGINTます。

したがって、trap .. exitクリーンアップには役立ちますが、実行されないシナリオがいくつかあります。最も明白なシナリオは、停電と受信SIGKILLです。


オプションを追加したり、オプションを変更したりすると、bashスクリプトが非常に大きくなることがよくあります。bashスクリプトに多くの関数が含まれている場合、「trapEXIT」の使用は簡単ではなくなる可能性があります。

たとえば、次のように呼び出されたスクリプトについて考えてみます。

dotask TASK [ARG ...]

それぞれTASKがサブステップで構成されている場合があり、その間にクリーンアップを実行することが望ましい場合。

この場合、サブシェルを操作してスコープ付き出口トラップを生成すると便利です。

function subTask (
    local tempFile=$(mktemp)
    trap "rm '${tempFile}'" exit
    ...
)

ただし、サブシェルは親シェルのグローバル変数を設定できないため、サブシェルの操作には注意が必要です。

さらに、単一の出口トラップを作成することはしばしば不便です。たとえば、クリーンアップ手順は、エラーが発生する前に関数がどこまで到達したかによって異なる場合があります。RAIIスタイルのクリーンアップ宣言を作成できると便利です。

function subTask (
    ...
    onExit 'rm tmp.1'
    ...
    onExit 'rm tmp.2'
    ...
)

次のようなものを使用するのは明らかだと思われます

handlers=""
function onExit { handlers+="$1;"; trap "$handlers" exit; }

トラップを更新します。ただし、これはネストされたサブシェルでは失敗します。これは、親シェルのハンドラーの実行が早まるためです。クライアントコードはhandlers、サブシェルの先頭で変数を明示的にリセットする必要があります。

[同じ信号に対して複数のbashトラップ]で説明されているソリューションは、からの出力を使用してトラップにパッチを適用しますが、同様に失敗します。サブシェルはトラップをtrap -p EXIT継承しませんが、親シェルのハンドラーを表示するため、手動でリセットする必要があります。 。EXITtrap -p exit

于 2020-02-18T22:28:01.410 に答える