Shell 脚本 while 循环:[ 管道周围缺少“]”

Shell 脚本 while 循环:[ 管道周围缺少“]”

我尝试使用的 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; },并且不应将要测试的命令括起来。

[只是常规命令,例如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/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

有关的:

相关内容