シェルスクリプトwhileループ:パイプの周りに["]"がありません。

シェルスクリプトwhileループ:パイプの周りに["]"がありません。

使用するシェルスクリプトでこのエラーが発生し続けます。

$ ./script.sh: line 2: [: missing `]' 
grep: ]: No such file or directory

この行は、特定のプロセスがファイルをロックすることを確認するセクションの一部です。

COUNTER=0
while [ ps aux | grep "[r]elayevent.sh" ] && [ "$COUNTER" -lt 10 ]; do
    sleep 3
    let COUNTER+=1
done

明らかに、私は角括弧がすべて正しく対になっていることを確認しました。これは私にとっては大丈夫に見えます。また、条件付き質問の周りの一般的なスペースは適用されません。

私がここで何を見逃しているのでしょうか?

答え1

エラーは、[終了状態を確認した後、命令を直接使用したいので、まず削除する必要があることです。

ウィキページ住宅検査ツールこれについての説明があります(問題SC1014):

[ .. ]ifステートメントなどのシェル構文の一部ではありません。 Cに似た言語では、括弧と同じではなく、if (foo) { bar; }テストするコマンドを束ねてはいけません。

[whoamiorのような一般的なコマンドgrepですが、面白い名前があります(参照ls -l /bin/[)。の略ですtest

コマンドの終了状態を確認するには、そのコマンドを直接使用します。

コマンドの出力を確認するには、文字列比較のためにまたは/を"$(..)"使用して出力を取得します。test[[[

また、ps aux | grep -q "[r]elayevent.sh"これを使用するとstdout

pgrepまたはその出力を使用して/dev/null

最後のケースではより効率的であるため、最初の条件を最初に使用してください。

したがって、最終スクリプトは次のようになります。

#!/bin/bash
COUNTER=0

while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh"   ; do

    sleep 3

    let COUNTER+=1

done

または

#!/bin/bash
COUNTER=0

while [ "$COUNTER" -lt 10 ] && pgrep  "[r]elayevent.sh" >/dev/null  ; do

    sleep 3

    let COUNTER+=1

done

答え2

その中にチューブがありません[ ... ]pgrep次の出力を解析するよりも使用する方が良いですps

count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
    sleep 3
    count=$(( count + 1 ))
done

BSDシステムが通常と同様に廃棄するpgrep -q ...代わりに使用できる実際の出力です(終了状態にのみ興味があります)。pgrep ... >/dev/nullpgrepgrep

pgrepコマンドを入れない理由[ ... ]は、出力には興味がなく、終了状態にのみ興味があるからです。[ ... ]通常、文字列または数字を比較します。これは[ ... ]実行と同様に終了状態が0(true)または0ではない(false)になりますpgrep

ただし、これはロックメカニズムをチェックせず、特定のプロセスが実行されているかどうかを確認します。

スクリプトの単一インスタンスのみを実行する場合は、次のことをお勧めします(EXITスクリプトが順番に終了するたびにトラップが実行されると仮定します)。

lockdir=dir.lock

if mkdir "$lockdir"; then
    trap 'rmdir "$lockdir"' EXIT
else
    echo 'Only one instance of this script allowed' >&2
    exit 1
fi

何度も試してから眠りに落ちた後:

lockdir=dir.lock

count=0
while [ "$count" -lt 10 ]; then
    if mkdir "$lockdir"; then
        trap 'rmdir "$lockdir"' EXIT
        break
    else
        echo 'Locked. Sleeping...' >&2
        sleep 3
    fi

    count=$(( count + 1 ))
done

if [ "$count" -eq 10 ]; then
    echo 'Giving up.' >&2
    exit 1
fi

関連:

関連情報