$を使用するためのベストプラクティスは?バッシュで?


10

$についてこの答えを読んだとき別の質問が思い浮かびます。

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


例を挙げましょう:

線形スクリプトがあり、すべてのコマンドが正常に実行されたことを知りたいのですが。小さな関数( "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 $? 

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

これは良いアイデアだと思いますか、これを行うための他のベストプラクティスはありますか?

/ありがとう

回答:


15

一般的な方法の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て実行されcommand1command1失敗した場合は実行されcommand2ます。

だから、「ディレクトリを作るか死ぬか」のようにそれを読むことができます。

あなたの例は次のようになります:

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"

9

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

#!/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
}

この形式のコードを使用することもできます。<pre> function try {
BillThor

この機能をインラインで使用し、本来の側面から戻りたくない場合はreturn $?:組み込みに置き換えることができます。
BillThor 2011年

8

exitエラーが本当に発生し、Bashを使用している場合は、も検討する必要がありますset -e。からhelp set

-eコマンドがゼロ以外のステータスで終了した場合、直ちに終了します。

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


set -e便利です。通常の状況下で非ゼロを返すコマンドがいくつかあります(たとえば、diff)。ゼロ以外の戻り値を期待しているスクリプトでset -eを使用している場合は、そうしますcommand || true
Shawn J. Goff

2
さらに、を使用する場合でもset -e、「例外ハンドラ」を設定して、ですべてのエラーをキャッチできtrap did_it_work EXITます。
Gilles「SO-邪悪なことをやめよう」

1
これはPOSIXの一部であり、bash固有の機能ではありません。それを使用しますが、いくつかの落とし穴に注意してくださいmywiki.wooledge.org/BashFAQ/105
kmkaplan

@ ShawnJ.Goff私がやりたいcommand && true。同様に、戻り値は変更されません
kmkaplan 2014

@kmkaplan最後のコメントは私には意味がありません。の目的は、ゼロ以外の終了コードが返された場合にスクリプトが終了command || trueしないようにすることです。必要に応じて終了コードを変更します。`コマンドが成功した場合(ゼロの終了コードを返した場合)は、実行(ゼロの終了コードを返した場合)のみが行われます-これは完全なノーオペレーションです。set -ecommandcommand && truetrue
tripleee
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.