個々のコマンドでset -eを無効にする方法は?


36

set -eコマンドは、いずれかのコマンドがゼロ以外の終了コードを返すと、bashスクリプトをすぐに失敗させます。

  1. スクリプト内の個々のコマンドに対してこの動作を無効にする簡単でエレガントな方法はありますか?

  2. この機能はBashリファレンスマニュアル(http://www.gnu.org/software/bash/manual/bashref.html)に記載されていますか?

回答:


29
  1. このようなもの:

    #!/usr/bin/env bash
    
    set -e
    echo hi
    
    # disable exitting on error temporarily
    set +e
    aoeuidhtn
    echo next line
    
    # bring it back
    set -e
    ao
    
    echo next line

    実行:

    $ ./test.sh
    hi
    ./test.sh: line 7: aoeuidhtn: command not found
    next line
    ./test.sh: line 11: ao: command not found
  2. set組み込みヘルプで説明されています:

    $ type set
    set is a shell builtin
    $ help set
    (...)
    Using + rather than - causes these flags to be turned off.

同じことがhttps://www.gnu.org/software/bash/manual/bashref.html#The-Set-Builtinに記載されています


ありがとう!別の可能性を見つけました:#!/ bin / bash set -e#次の行のコメントを外してset -eの効果を確認します:#blubb if blubb; 次に、「Command blubbは成功しました。」とエコーします。else echo "コマンドblubbが失敗しました。終了コード:$?" fiエコー通常のスクリプトの終了
ギュスターヴ

22

エラー時に保釈を解除する別の方法は、何であれ成功を強制することです。次のようなことができます:

cmd_to_run || true

これは0(true)を返すため、セット-eはトリガーされません。


3
faulty_cmd || :これのもう一つの人気のイディオムです。(:は、と同義のコマンドtrueです)。
ulidtko

3
@ulidtko-興味深い。これを見つけるためにウサギの穴の下に私を導いたstackoverflow.com/questions/3224878/...を真の対の履歴を取得するには:
アーニー

12

リターン/エラーコード(関数またはフォーク)をキャッチしようとしている場合、これは機能します。

function xyz {
    return 2
}

xyz && RC=$? || RC=$?

8

「すぐにシェルを終了する」オプションが適用されるか無視されるかは、実行されたコマンドのコンテキストによって異なります(ビルトインセットのBashリファレンスマニュアルのセクションを参照してください-Arkadiusz Drabczykに感謝します)。

特に、コマンドがifステートメントのテストの一部である場合、オプションは無視されます。したがって、次のようなifステートメントを使用して、コマンドを実行し、「すぐに終了するコンテキスト」内でコマンドの成功または失敗を確認することができます。

#!/bin/bash

set -e

# Uncomment next line to see set -e effect:
#blubb

if blubb; then
  echo "Command blubb was succesful."
else 
  echo "Command blubb failed. Exit code: $?"
fi
echo "Script exited normally."

「then」ステートメントを省略して、使用する行を減らすことができます。

if blubb; then :;
else echo "Command blubb failed. Exit code: $?"; fi

2

私がかなり簡単だと思う別のアプローチ(およびsetに加えて他のオプションにも適用されます-e):

を使用し$-て設定を復元します。

例えば:

oldopt=$-
set +e
# now '-e' is definitely disabled.
# do some stuff...

# Restore things back to how they were
set -$oldopt

以下のためものの-e具体的には、オプションの他の人が(mentinedている|| trueか「内に置くif」)より慣用的かもしれません。


0

私は実際に最近似たような質問をしました(投稿しなかったが、私はそれに回りました)、そして私が見ることができることから、それはコマンドの前にset + eを使用し、その後で最もエレガントにset -eを使用しているようです。以下に例を示します。コマンドの応答を取得し、エラーがそれを捨てないようにします。

#!/bin/sh

args=""
for argcol in $*
do
    args="${args} ${argcol}"
done
fortunevar=""
fortfail=""
{
    set +e
    fortunevar=`fortune $args`
    fortfail=$?
    set -e
} &> /dev/null
if [ $fortfail == 0 ]
then
    echo ${fortunevar}
    say ${fortunevar}
else
    echo misfortune: an illegal option was detected!
    echo misfortune: usage: misfortune [-afilosw] [-m pattern][ [#%] file/directory/all]
fi

これは 'fortune'の出力を取得し、その終了ステータスを確認し、それをエコーし​​て言います。これはあなたが求めていたもの、または少なくとも似たようなものだと思いますか?とにかく、これが役立つことを願っています。


明確にするために、/ dev / nullにリダイレクトされる中括弧のビットは、あなたが望んでいることだと思います。コマンドに出力がないようにし、プログラムを終了せずにエラーステータスをチェックします。
アディソンクランプ

0

一時的に何かを変更したい場合、サブシェルを起動するのが好きです。以下のコマンドは、最初のbad_commandが無視され、2番目のコマンドが実行を中止することを示しています。

bash -c 'set -e ;\
( set +e; bad_command ; echo still here ) ;\
echo even here ; \
bad_command ; \
echo but not here;'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.