私が使用しようとしているシェルスクリプトが次のエラーを出し続けます。
$ ./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
明らかに、角かっこがすべて正しくペアになっていることを確認しました-私には問題ありません。また、条件の問題の周りにある一般的な空白は適用されません。
ここで何が欠けていますか?
エラーは、終了ステータスを確認してから直接コマンドを使用するため、最初に_[
_を削除する必要があることです。
Shellcheckツール のWikiページには、これに関する説明があります( issue SC1014 ):
_
[ .. ]
_は、if
ステートメントのようなシェル構文の一部ではありません。 Cライクな言語の括弧if (foo) { bar; }
と同等ではないため、テストするコマンドを囲む必要はありません。_
[
_は、whoami
またはgrep
のような通常のコマンドですが、おかしな名前が付いています(_ls -l /bin/[
_を参照)。これは、test
の省略形です。特定のコマンドの終了ステータスを確認する場合は、そのコマンドを直接使用します。
コマンドの出力を確認する場合は、
"$(..)"
を使用して出力を取得し、次にtest
または_[
_/_[[
_を使用して文字列を比較します。
また、_ps aux | grep -q "[r]elayevent.sh"
_を使用して、stdout
に何かを出力する代わりに、サイレントモードで終了ステータスを取得します。
または、pgrep
を使用して、その出力を_/dev/null
_に送信することもできます。
最後のケースの方が効率的であるため、最初に2番目の条件を使用します。
したがって、最終的なスクリプトは次のようになります。
_#!/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
_
[ ... ]
内にパイプを置くことはできません。また、pgrep
の出力を解析するよりも、ps
を使用する方が適切です。
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
BSDシステムは、通常のpgrep
と同様に、grep
の実際の出力を破棄するためにpgrep -q ...
ではなくpgrep ... >/dev/null
を使用できます(終了ステータスのみに関心があります) 。
pgrep
コマンドを[ ... ]
内に配置しないことに注意してください。これは、出力には関心がなく、終了ステータスのみに関心があるためです。 [ ... ]
を使用すると、通常、文字列または数値を比較します。 [ ... ]
は、pgrep
の実行と同様に、終了ステータスがゼロ(true)または非ゼロ(false)になります。
ただし、これは、特定のプロセスが実行されているかどうかだけをチェックして、ロックメカニズムをチェックしません。
スクリプトのインスタンスを1つだけ実行する場合は、次のようにすることをお勧めします(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
関連: