このようなコードを書きたい:
command="some command"
safeRunCommand $command
safeRunCommand() {
cmnd=$1
$($cmnd)
if [ $? != 0 ]; then
printf "Error when executing command: '$command'"
exit $ERROR_CODE
fi
}
しかし、このコードは私が望むようには機能しません。どこで間違えたの?
以下は修正されたコードです。
#!/bin/ksh
safeRunCommand() {
typeset cmnd="$*"
typeset ret_code
echo cmnd=$cmnd
eval $cmnd
ret_code=$?
if [ $ret_code != 0 ]; then
printf "Error : [%d] when executing command: '$cmnd'" $ret_code
exit $ret_code
fi
}
command="ls -l | grep p"
safeRunCommand "$command"
このコードを見てみると、私が変更したいくつかの点は次のとおりです。
typeset
の使用は必須ではありませんが、良い習慣です。 cmnd
およびret_code
をsafeRunCommand
に対してローカルにしますret_code
を使用する必要はありませんが、戻りコードを何らかの変数に格納(およびできるだけ早く格納)して、printf "Error : [%d] when executing command: '$command'" $ret_code
で行ったように後で使用できるようにすることをお勧めしますsafeRunCommand "$command"
のようなコマンドを囲む引用符でコマンドを渡します。しない場合、cmnd
はls -l
ではなく、値ls
のみを取得します。また、コマンドにパイプが含まれている場合はさらに重要です。typeset cmnd="$*"
の代わりにtypeset cmnd="$1"
を使用できます。コマンド引数の複雑さに応じて、両方を試すことができます。注:grep
のようなエラーが発生していなくても、一部のコマンドでは戻りコードとして1が指定されることを忘れないでください。 grep
が何かを見つけた場合、0または1を返します。
KSH/BASHでテストしました。そして、それはうまくいきました。あなたがこれを実行している問題に直面するならば、私に知らせてください。
試して
safeRunCommand() {
"$@"
if [ $? != 0 ]; then
printf "Error when executing command: '$1'"
exit $ERROR_CODE
fi
}
$($cmd)
ではなく$cmd
にする必要があります。私の箱のそれでうまくいきます。
編集:スクリプトは、lsなどの1ワードのコマンドに対してのみ機能します。 「ls cpp」では機能しません。これが機能するには、cmd="$1"; $cmd
を"$@"
に置き換えます。また、スクリプトをcommand="some cmd"; safeRun command
として実行するのではなく、safeRun some cmd
として実行します。
また、bashスクリプトをデバッグする必要がある場合は、「-x」フラグを使用して実行します。 [bash -x s.sh]。
スクリプトにはいくつかの問題があります。
関数(サブルーチン)は、呼び出す前に宣言する必要があります。おそらく、サブルーチンからexit()ではなくreturn()を使用して、呼び出しブロックが特定のコマンドの成功または失敗をテストできるようにする必要があります。それはさておき、「ERROR_CODE」をキャプチャしないため、常にゼロ(未定義)になります。
変数参照も中括弧で囲むことをお勧めします。コードは次のようになります。
#!/bin/sh
command="/bin/date -u" #...Example Only
safeRunCommand() {
cmnd="$@" #...insure whitespace passed and preserved
$cmnd
ERROR_CODE=$? #...so we have it for the command we want
if [ ${ERROR_CODE} != 0 ]; then
printf "Error when executing command: '${command}'\n"
exit ${ERROR_CODE} #...consider 'return()' here
fi
}
safeRunCommand $command
command="cp"
safeRunCommand $command
通常のアイデアは、コマンドを実行し、$?
を使用して終了コードを取得することです。ただし、終了コードを取得する必要がある場合が複数あります。たとえば、出力を非表示にしつつ、終了コードを返すか、終了コードと出力の両方を印刷する必要がある場合があります。
ec() { [[ "$1" == "-h" ]] && { shift && eval $* > /dev/null 2>&1; ec=$?; echo $ec; } || eval $*; ec=$?; }
これにより、終了コードが必要なコマンドの出力を抑制するオプションが提供されます。コマンドの出力が抑制されると、関数から終了コードが直接返されます。
個人的にこの関数を.bashrc
ファイルに入れたい
以下に、これを使用できるいくつかの方法を示します。
# In this example, the output for the command will be
# normally displayed, and the exit code will be stored
# in the variable $ec.
$ ec echo test
test
$ echo $ec
0
# In this example, the exit code is output
# and the output of the command passed
# to the `ec` function is suppressed.
$ echo "Exit Code: $(ec -h echo test)"
Exit Code: 0
# In this example, the output of the command
# passed to the `ec` function is suppressed
# and the exit code is stored in `$ec`
$ ec -h echo test
$ echo $ec
0
この関数を使用したコードの解決策
#!/bin/bash
if [[ "$(ec -h 'ls -l | grep p')" != "0" ]]; then
echo "Error when executing command: 'grep p' [$ec]"
exit $ec;
fi
また、表示される終了コードは、実行中の最後のコマンドであるため、実行中の
grep
コマンド用であることにも注意してください。ls
ではありません。