次の2つのスクリプトを考えてみましょう。
run.sh:
#!/bin/bash
set -euo pipefail
. "$(dirname $(realpath $BASH_SOURCE))"/init-sudo-script.sh
init-sudo-script.sh
[ ${#BASH_SOURCE[@]} -eq 1 ]\
&& echo "must be sourced by another script."\
&& exit 10
[ $EUID -ne 0 ]\
&& echo "must be executed as root."\
&& exit 20
これは正確で、これが私が期待するものです。
$ ./run.sh
must be executed as root.
$ echo $?
20
しかし、理解できません。
$ sudo ./run.sh
$ echo $?
1
問題は、[ $EUID -ne 0 ]
スクリプトを削除すると機能するためであることがわかります。
また、set -e
エラーが発生するとスクリプトが終了することも理解しています。
私が理解していないのは、なぜ最初のガード条件([ ${#BASH_SOURCE[@]} -eq 1 ]
)が失敗したときに1で終了しないのか、そして2番目のガード条件が終了する理由です。
ここで何が起こっているのか理解する人はいますか?
===更新===
期待どおりに機能させる方法を見つけました。
if [ $EUID -ne 0 ]; then
echo "must be executed as root."\
&& exit 20
fi
私はそれを残してBashをより良くするために投資しています。したがって、誰かが何が起こっているのかを明確にすることができれば、喜んで聞きたいのです。
答え1
また、
set -e
エラーが発生するとスクリプトが終了することも理解しています。
「何も間違っていませんでした」ではありません。例外があり、そのうちの1つは次のとおりです。
失敗したコマンドがまたは
&&
リストで実行されたコマンドの[...]の一部である場合、||
シェルは次の最後または[...]コマンドを除いて終了しません。&&
||
(源泉)
失敗すると、[ ${#BASH_SOURCE[@]} -eq 1 ]
シェルは終了しませんset -e
。
同様[ $EUID -ne 0 ]
に失敗すると、シェルは終了しませんがset -e
。台本が終わったからつまり、実行することはもう残っていないからです。これにより、スクリプトの終了状態は、最後に実行されたコマンドの終了状態になります[
。それがあなたが得る理由です1
。
:
テストが完了したら(常に成功した無修正コマンド)を入れてinit-sudo-script.sh
テストを再実行してください。最後のコマンドがあるためsudo ./run.sh
返されます。0
:
if
終了ステータスは次のとおりであるため、更新されたコードは異なりますif
。
[...] 条件が true でテストされていない場合は 0 です。
(源泉)