测试服务是否在脚本中运行的“正确”方法

Nic*_*k S 195 shell-script systemd

我的问题:

我正在编写一个 bash 脚本,我想在其中检查给定的服务是否正在运行。

我知道如何手动执行此操作,使用$ service [service_name] status.

但是(尤其是在转向 systemd 之后)会打印一大堆文本,解析起来有点麻烦。我假设有一个为脚本制作的命令,带有简单的输出或我可以检查的返回值。

但是谷歌搜索只会产生大量“哦,只是ps aux | grep -v grep | grep [service_name]”的结果。这不可能是最佳做法,是吗?如果该命令的另一个实例正在运行,但不是由 SysV init 脚本启动的呢?

还是我应该闭嘴,用一点 pgrep 弄脏我的手?

Ste*_*itt 306

systemctl有一个is-active子命令:

systemctl is-active --quiet service
Run Code Online (Sandbox Code Playgroud)

如果service处于活动状态,将以状态零退出,否则为非零状态,使其成为脚本的理想选择:

systemctl is-active --quiet service && echo Service is running
Run Code Online (Sandbox Code Playgroud)

如果省略,--quiet它也会将当前状态输出到其标准输出。

正如don_crissti所指出的那样,即使没有任何设备在运行以提供服务,某些单元也可以处于活动状态:如果成功退出,标记为“RemainAfterExit”的单元将被视为处于活动状态,其想法是它们提供不需要守护程序的服务(例如,他们配置系统的某些方面)。然而,只有当守护程序仍在运行时,涉及守护程序的单元才会处于活动状态。

  • 小心 oneshot 服务。它们只是`inactive` 或`activation`,并且`systemctl status` 和`systemctl is-active` 都以3 退出。(截至*systemd-241*) 解决方法:`systemctl show service | grep -qx ActiveStatus=activation` (3认同)
  • 可能值得指出的是,“is-failed”也是一个选项,如果您需要基于未启动的服务执行操作,则该选项很有用。 (2认同)

Zan*_*nna 65

systemctl确实有适合脚本编写的模式;使用show而不是status,并添加-p/--properties--value选项以仅获取您想要的输出。

这是一个示例(来自 Ubuntu 17.04 系统):

$ systemctl show -p SubState --value NetworkManager
running
Run Code Online (Sandbox Code Playgroud)

运行(或以其他方式)是一个SubState. 如果您想知道服务是否处于活动状态,请使用该属性ActiveState

$ systemctl show -p ActiveState --value x11-common
inactive
$ systemctl show -p SubState --value x11-common
dead
Run Code Online (Sandbox Code Playgroud)

注释来自man

show [PATTERN...|JOB...]
           Show properties of one or more units, jobs, or the manager
           itself. If no argument is specified, properties of the
           manager will be shown. If a unit name is specified, properties
           of the unit are shown, and if a job ID is specified,
           properties of the job are shown. By default, empty properties
           are suppressed. Use --all to show those too. To select specific
           properties to show, use --property=. This command is intended
           to be used whenever computer-parsable output is required. Use
           status if you are looking for formatted human-readable output.

-p, --property=
           When showing unit/job/manager properties with the show command,
           limit display to properties specified in the argument. The
           argument should be a comma-separated list of property names,
           such as "MainPID". Unless specified, all known properties are
           shown. If specified more than once, all properties with the
           specified names are shown. Shell completion is implemented for
           property names.

--value
           When printing properties with show, only print the value, and
           skip the property name and "=".
Run Code Online (Sandbox Code Playgroud)

要查看服务的可用属性,请运行(例如,for polkit

systemctl show -a polkit
Run Code Online (Sandbox Code Playgroud)

有很多属性,所以如果你知道你在找什么......

$ systemctl show - polkit | grep Active
ActiveState=active
ActiveEnterTimestamp=Thu 2020-07-02 07:24:40 IST
ActiveEnterTimestampMonotonic=6682102
ActiveExitTimestamp=
ActiveExitTimestampMonotonic=0
Run Code Online (Sandbox Code Playgroud)

  • +1 为复杂的答案。请使用 systemctl 指定将接受 `--version` 选项的发行版。 (3认同)
  • 在 Raspbian 上,我使用了有时会中断的服务。它的状态不是“活动(运行)”,而是“活动(退出)”。“systemctl is-active”不会区分。这个答案给了我我需要的区别:运行/退出/死 (2认同)
  • 非常令人沮丧的是,您网站上的文档_没有列出所有状态_。对于与“服务”单元类型相关的状态,它引用另一个文档页面,该页面根本不讨论可能的子状态值或其语义:( (2认同)

小智 22

作为 Zanna 答案的补充, systemd 的 230 版引入了--value选项。所以它可能不适用于某些发行版,例如 debian jessie。systemctl show

在这种情况下,可以使用 sed 模拟该选项:

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running
Run Code Online (Sandbox Code Playgroud)

  • +1 指出 --value 介绍版本和发行版不起作用。 (2认同)

小智 11

我发现这对于命令行执行或如果您正在制作脚本很有用。

复制自@StephenKitt

这将检查服务是否关闭并执行服务重启

systemctl is-active --quiet <service name> || <service name> restart
Run Code Online (Sandbox Code Playgroud)

||如果 systemctl 没有按照作者的解释处于活动状态,则那里会检查它的返回值是否为非零值。


小智 9


我参加聚会为时已晚,但是在脚本中使用 systemctl is-active&&||不会一直如此。下面是我用于 tomcat 的一个,但可以在接受参数的方法中使用它并将服务名称作为参数传递,如果你必须检查多个服务但它超出了这里的范围。

STATUS="$(systemctl is-active tomcat.service)"
if [ "${STATUS}" = "active" ]; then
    echo "Execute your tasks ....."
else 
    echo " Service not running.... so exiting "  
    exit 1  
fi
Run Code Online (Sandbox Code Playgroud)

这就是我如何利用....只是分享我的。

为了简单和容易的东西,请按照此处的其他说明进行操作:

systemctl -q is-active tomcat.service  && \
echo "Tomcat Runnung" || \
echo "Service is not running at all "
Run Code Online (Sandbox Code Playgroud)

  • 这比简单的“if systemctl is-active --quiet tomcat.service”更好吗?另外,“[[”不是标准 shell。 (4认同)

小智 5

这是针对 init.d 系统的

如果服务未运行则启动服务:

service mysql status > /dev/null ||     service mysql start &
service ssh status > /dev/null ||     service ssh start &
service php7.4-fpm status > /dev/null ||     service php7.4-fpm start &
service redis-server status > /dev/null ||     service redis-server start &
service nginx status > /dev/null ||     service nginx start  &
service cron status > /dev/null ||     service cron start &
Run Code Online (Sandbox Code Playgroud)

当程序退出时,它还会返回一个错误 ID,即一个有符号字节。如果没有问题退出,该值通常为 0。如果因错误退出,该值通常为错误 id 或经常为 -1。

该值经常用于命令集成,例如打印程序输出的数字状态 ID。

要将其与命令链一起使用,有两个选项 && 和 ||

|| 的 检查退出返回值是否不为零,然后运行链接命令

而不是 || 不可能写&&

&& 检查退出返回值是否为零,然后运行链接命令

类似于本页上的@asterisk答案(对于systemd) https://unix.stackexchange.com/a/500336/156304