$?使用のベストプラクティス バッシュから?

$?使用のベストプラクティス バッシュから?

私がこの記事を読むとき答え$?別の質問がありました。

$の使用方法に関するベストプラクティスはありますか?バッシュから?


たとえば、見てみましょう。

私たちは線形スクリプトを持っており、すべてのコマンドが正しく実行されているかどうかを知りたいです。エラーコードを確認し、そうでなければ中断する小さな関数(「did_it_work」と呼ばれる)を呼び出すことができると思います。

#!/bin/bash 

function did_it_work {
    code=$1
    if [ "$code" -ne "0" ]
    then
        echo "Error failure: code $code "
        exit 1
    fi
}

dir=some/path

mkdir -p $dir
did_it_work $? 

cd $dir
did_it_work $? 

run_some_command
did_it_work $? 

もちろん、このアプローチは、問題がある場合は手動で修正してスクリプトを再実行する必要があることを意味します。

これは良い考えだと思いますか?それともこれを行うための他のベストプラクティスはありますか?

/ありがとう

答え1

一般的な方法は次のとおりです。

die() {
    IFS=' ' # make sure "$*" is joined with spaces

    # output the arguments if any on stderr:
    [ "$#" -eq 0 ] || printf '%s\n' "$*" 1>&2
    exit 1
}

次に、次のように使用します。

mkdir -p some/path || die "mkdir failed with status $?"

または、終了ステータスを含めるには、次のように変更できます。

die() {
    last_exit_status=$?
    IFS=' '
    printf '%s\n' "FATAL ERROR: $* (status $last_exit_status)" 1>&2
    exit 1
}

これにより、次のものを使用する方が簡単になります。

mkdir -p some/path || die "mkdir failed"

失敗するとmkdirエラーメッセージが表示される可能性があるため、2番目のメッセージは重複していると見なすことができます。次のことができます。

mkdir -p some/path || exit   # with the same (failing) exit status as mkdir's
mkdir -p some/path || exit 1 # with exit status 1 always

die(または引数なしで上記の最初のバリアントを使用します)

以前見たことがない場合に備えて動作しcommand1 || command2、失敗してcommand1も動作します。command1command2

だから「ディレクトリを作らないと死ぬ」と読むことができます。

あなたの例は次のとおりです

mkdir -p some/path || die "mkdir failed"
cd some/path || die "cd failed"
some_command || die "some_command failed"

あるいは、diesメインコードがよりよく見えるように右に揃えることもできます。

mkdir -p some/path         || die "mkdir failed"
cd some/path               || die "cd failed"
some_command               || die "some_command failed"

または、コマンドラインが非常に長い場合は、次の行を使用してください。

mkdir -p some/path ||
  die "mkdir failed"

cd some/path ||
  die "cd failed"

some_command ||
  die "some_command failed"

また、名前を複数回使用したい場合は、some/path名前を変数に保存して入力を続ける必要がなく、必要に応じて簡単に変更できます。変数引数をコマンドに渡すときに引数がで始まる場合は、オプションと見なされないように--オプション区切り文字を使用する必要があります-

dir=some/path
mkdir -p -- "$dir"         || die "Cannot make $dir"
cd -P -- "$dir"            || die "Cannot cd to $dir"
some_command               || die "Cannot run some_command"

答え2

次のようにコードを書き換えることができます。

#!/bin/bash
function try {
    "$@"
    code=$?
    if [ $code -ne 0 ]
    then
        echo "$1 did not work: exit status $code"
        exit 1
    fi
}

try mkdir -p some/path
try cd some/path
try run_some_command

実際にエラーコードを記録する必要はありませんが、コマンドが成功したかどうかを記録するだけで、次のようにtry()コードをさらに短縮できます。

function try {
    if ! "$@"
    then
        echo "$1 did not work"
        exit 1
    fi
}

答え3

本当にexitエラーを解決してBashを使用している場合は、Fromも考慮する必要がありますset -ehelp set

-e コマンドが 0 以外の状態で終了したら直ちに終了します。

これは間違いなくdid_it_work()関数の柔軟性を提供しませんが、新しい関数に多くの呼び出しを追加することなくエラーが発生したときにbashスクリプトを停止させる簡単な方法です。

関連情報