为什么我得到不同的 ps 退出状态 | 脚本中的grep?

pra*_*ado 11 process ps shell-script exit-status

我在脚本下面运行:

#!/bin/bash

ps ax  | grep -q [v]arnish
if [ $? -eq 0 ];then
        echo varnish is running...
        exit 0
else
        echo "Critical : varnish is not running "
        exit 2
fi
Run Code Online (Sandbox Code Playgroud)

输出就像 ::

[root@server ~]# sh -x check_varnish_pro.sh
+ ps ax
+ grep -q '[v]arnish'
+ '[' 0 -eq 0 ']'
+ echo varnish is running...
varnish is running...
+ exit 0
Run Code Online (Sandbox Code Playgroud)

当我在命令行中运行相同时,我的退出状态为 1:

[root@server ~]# ps ax  | grep -q [v]arnish; echo $?
1
Run Code Online (Sandbox Code Playgroud)

这种情况就像服务器中没有安装清漆。此脚本在安装了 varnish 的服务器中运行良好。

为什么使用脚本和命令行运行时退出状态不同?如何改进这个脚本?

Kus*_*nda 15

一般来说,尝试简单的方法psgrep尝试确定给定的进程是否正在运行是一个坏主意。

您最好pgrep为此使用:

if pgrep "varnish" >/dev/null; then
  echo "Varnish in running"
else
  echo "Varnish is not running"
fi
Run Code Online (Sandbox Code Playgroud)

参见手册pgrep。在某些系统上(可能不是在 Linux 上),您会得到一个-q标志,该标志对应于grep无需重定向到/dev/null. 还有一个-f标志可以在完整的命令行上而不是仅在进程名称上执行匹配。还可以将匹配限制为属于特定用户的进程,使用-u.

安装pgrep还允许您访问pkill哪些允许您根据名称向进程发送信号。

此外,如果这是一个服务守护进程,并且如果您的 Unix 系统有一种查询它的信息的方法(例如,它是否已启动并正在运行),那么这就是检查它的正确方法。

在 Linux 上,你有systemctlsystemctl is-active --quiet varnish如果它正在运行,将返回 0,否则返回 3),在 OpenBSD 上你有rcctl,等等。


现在到你的脚本:

在您的脚本中,您解析来自ps ax. 此输出将包含脚本本身的名称check_varnish_pro.sh,其中显然包含字符串varnish。这会给你一个误报。如果您在测试时在没有-q标志的情况下运行它,您就会发现这一点grep

#!/bin/bash
ps ax | grep '[v]arnish'
Run Code Online (Sandbox Code Playgroud)

运行它:

$ ./check_varnish_pro.sh
31004 p1  SN+     0:00.04 /bin/bash ./check_varnish_pro.sh
Run Code Online (Sandbox Code Playgroud)

另一个问题是,尽管您尝试通过在模式中使用来“隐藏”grep进程,使其不被grep自身检测到[v]。如果您碰巧在包含指定文件或目录的目录中运行脚本或命令行,则该方法将失败varnish(在这种情况下,您将再次得到误报)。这是因为该模式未加引号,并且 shell 将使用它执行文件名通配。

看:

bash-4.4$ set -x
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep '[v]arnish'
bash-4.4$ touch varnish
+ touch varnish
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep varnish
91829 p2  SN+p    0:00.02 grep varnish
Run Code Online (Sandbox Code Playgroud)

该文件的存在varnish将导致 shell 替换[v]arnish为文件名,varnish并且您会在进程表(grep进程)中找到模式。

  • 因为一切都是“在 linux 领域”的文件。 (4认同)
  • 不仅是grep进程;脚本被命名为 `check_varnish_pro.sh` 也是一个因素。 (4认同)

Ale*_*exP 10

当您运行名为check_varnish_pro.shtest的脚本时

ps ax  | grep -q [v]arnish
Run Code Online (Sandbox Code Playgroud)

成功是因为有一个名为check_varnish的脚本_pro正在运行。