条件文でスクリプトを終了するにはどうすればよいですか?


50

ユーザーがrootでない場合に終了するbashスクリプトを書いています。条件は正常に機能しますが、スクリプトは終了しません。

[[ `id -u` == 0 ]] || (echo "Must be root to run script"; exit)

私は&&代わりに使用しましたが;、どちらも動作しませんでした。

回答:


50

これは次の方法で行うことができます。

[[ $(id -u) -eq 0 ]] || { echo >&2 "Must be root to run script"; exit 1; }

(最初のステートメントに算術二項演算子を使用した「通常の」条件式)、または:

(( $(id -u) == 0 )) || { echo >&2 "Must be root to run script"; exit 1; }

(最初のテストの算術評価)。

変更に注意してください()-> {}-中括弧はサブシェルを生成しません。(man bash「サブシェル」を検索します。)


1
ゼロ以外のコードで終了してください。例:exit 1問題が発生した親プロセスを理解するため。
SamK

1
[[数値比較には使用しないでください((
クリスダウン

1
@ChrisDown [[は、の-eq代わりに使用する限り問題ありません==
Let_Me_Be

条件を修正し、算術バージョン@ChrisDownを追加しました。
マット

2
@Matところで、短縮することができます(( EUID )) && ...
クリスダウン

21

これらのコマンドを囲む括弧はサブシェルを作成します。サブシェルは「スクリプトを実行するためにルートである必要があります」とエコーし、サブシェルに終了するように指示します(ただし、コマンドはもうないので、既に終了しています)。それを修正する最も簡単な方法は、おそらく単に使用することifです:

if [[ `id -u` != 0 ]]; then
    echo "Must be root to run script"
    exit
fi

ワンライナーでこれを行う方法はありませんか?
ギャレットホール

1
あなたのロジックは逆向きです。あなたの例では、if id -u == 0、これはあなた root であることを意味します。あなたが欲しい[[ $(id -u) != 0 ]]; then
ティムケネディ

4
/ must /に1ライナーが必要な場合は、サイズを試してみてください:プロセスの生成を節約[ "$UID" != 0 ] && echo 'You have to be root.' && exit 1;する$UIDにも注意してください。あなたも好むかもしれません$EUID
ジャンモエセン

1
@janmoesen、良い点。そして、おしっこながら数値を持つ変数を持っています((UID)) && echo 'You have to be root.' && exit 1
マナトワーク

3
@janmoesen:このような逆論理を使用すると、スクリプトがset -e中断することに注意してください。その問題の解決策の1つです[ "$UID" != 0 ] && echo 'You have to be root.' && exit 1 || true
サムホセバー


1

周りのブラケット||及び&&これらとして必要とされていないが右結合されています。次の2つの式は同等です。

expr1 || expr2 && expr3
expr1 || { expr2 && expr3 }

そのため、trueを返すように、&&代わりに;うまく動作しechoます。

[[ $(id -u) == 0 ]] || echo "Must be root to run script" && exit 1

1
あなたが言ったことはすべて正しいが、expr2の戻り値に依存しているので、これは学ぶのが悪いパターンです。echoは常に0の終了ステータスを返すと確信していますか?ステートメントを中括弧とセミコロンでグループ化することをお勧めします。これはよくある落とし穴で、BashPitfallsに独自のエントリがあります:mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3
Flimm

1
@Flimm:悪いパターンだとは思わない。明らかに、使用方法は大文字と小文字が異なり、また、返される戻り値に関する知識にも依存します。この場合、 echoは99.999%の時間で0を返すと確信しており、書き込みエラーが発生すると(0を返さない唯一のケース)、このexprよりも大きな問題があります。また、YOUが戻り値を生成している場合もあります。そのため、それは私にとって「悪いパターン」ではありません。
ata

Wikiで述べているように、Cの評価を理解していることを確認したら使用することも追加します。とにかく、少しのテストであいまいさを解消する必要があります。
ata

0

これはあなたを助けるかもしれません、bashで

[oracle@rac1 ~]$ which bash
/bin/bash
[oracle@rac1 ~]$ cat test1.sh
if [ `id -u` != 0 ]
then
echo "Must be root to run the script
 "
exit
fi

3
これはすでに回答され、受け入れられています。また、あなたの答えはすでに投稿されたものとほぼ同じです。
maulinglawns

@maulinglawns、その答えは、他のものに反して、すべてのBourneのようなシェルに移植可能であるというメリットがあります(エラーがstderrに出力され、終了ステータスがゼロではなく、コマンド置換が引用された方が良いでしょう) )
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.