我尝试使用的 shell 脚本不断出现此错误:
$ ./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
错误是您应该先删除,[
因为您想检查退出状态然后直接使用命令。
的 Wiki 页面外壳检查工具对此有一个解释(问题 SC1014):
[ .. ]
不是像if
语句这样的 shell 语法的一部分。它不等同于类 C 语言中的括号 ,if (foo) { bar; }
,并且不应将要测试的命令括起来。
[
只是常规命令,例如whoami
orgrep
,但有一个有趣的名称(请参阅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/null
丢弃 的实际输出pgrep
,就像普通的一样grep
(我们只对退出状态感兴趣)。
请注意我们如何不将pgrep
命令放在[ ... ]
.那是因为我们对它的输出不感兴趣,只对它的退出状态感兴趣。您[ ... ]
通常会比较字符串或数字。这[ ... ]
将导致退出状态为零(真)或非零(假),就像执行一样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
有关的: