我试图检测进程(goland.sh
)是否正在运行。我用这个:
#!/bin/bash
if pgrep "goland.sh" >/dev/null 2>&1 ; then
echo "running"
exit 1
fi
echo "not running"
这是可行的,但我不明白两件事:
if [[ pgrep "goland.sh" >/dev/null 2>&1 ]] ; then
,它不工作(它总是打印‘运行’,即使进程没有运行)if [ pgrep "goland.sh" >/dev/null 2>&1 ] ; then
,它不工作(它总是打印‘运行’,即使进程没有运行)我怀疑1与如何解析>
有关,但我对2完全一无所知。
发布于 2021-10-18 14:32:29
在shell的测试如何构造[ ... ]
(或Bash情况下的[[ ... ]]
)的工作方式方面,似乎存在误解。
if
语句检查它后面的命令是否返回0
的退出状态,这意味着“没有错误”,并被解释为"true“。如果是这样,则执行切换到脚本的then
分支(参见巴什手册 )。pgrep
命令将返回0
(即"true")。这就是为什么只有在running
的一个实例是活动的情况下才会得到goland.sh
。[
是一个特殊的命令(通常是shell内置的命令),它允许对文件、字符串和数字执行测试,如果开头括号和结尾括号之间的条件为真,则返回" true“。但是,它的设计是根据特定的语法检查一个或多个操作数上的操作是否为真,例如,如果一个数字(操作数1)大于(运算符)另一个操作数(操作数2)。例如,假设shell变量n
的值为5
,则测试将返回true,并且当用作if
语句的测试命令时,执行将切换到then
分支。[ ... ]
之间代码的正确语法,以确保得到预期的结果。现在,您已经在测试构造括号中包含了一个“原始”shell命令。那么会发生什么在一定程度上取决于情况,但在任何情况下它都会构成语法错误,因为在方括号之间没有一个有效的运算符,因此有几个(常量)字符串标记。
[[ ... ]]
时,您将立即得到一个语法错误,因为它是一个Bash语法元素,并且Bash识别错误的语法。[ ... ]
,您的命令就会悄悄地失败,因为[
实际上是一个命令(尽管通常是内置的),它只希望它的参数对预定义的操作符有意义,并且期望它的最后一个参数是关闭的]
--但是既然您已经将它的错误输出重定向到/dev/null
,错误消息就会丢失。running
复制为输出。总之,您不需要使用[ ... ]
(或[[ ... ]]
)构造,因为如果找到正在运行的进程,用于测试的程序已经返回"true“。如果希望将测试建立在pgrep
输出的基础上,就需要使用“命令替换”( $(pgrep ...)
中的命令替换)(当然还需要将输出重定向移到/dev/null
)。
我建议使用shellcheck
(也可作为许多Linux发行版上的独立程序)检查您的shell脚本,以防止语法(和一些逻辑上的)错误。
https://unix.stackexchange.com/questions/673712
复制相似问题