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


96

我的问题:

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

我知道如何使用手动进行操作$ service [service_name] status

但是(尤其是自从移至systemd以来),它会打印出一堆很难理解的混乱文本。我假设有一个针对脚本的命令,该脚本具有简单的输出或可以检查的返回值。

但是,谷歌搜索只会产生大量的“哦,就是ps aux | grep -v grep | grep [service_name]”结果。那不是最佳实践,是吗?如果该命令的另一个实例正在运行,但不是由SysV初始化脚本启动的,该怎么办?

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

Answers:


139

systemctlis-active为此有一个子命令:

systemctl is-active --quiet service

如果service处于活动状态,将以零状态退出,否则将返回非零状态,非常适合脚本:

systemctl is-active --quiet service && echo Service is running

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

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


小心oneshot服务。它们只是inactiveactivating两者兼而有之,systemctl statussystemctl is-active以3退出。(从systemd-241开始)解决方法:systemctl show service | grep -qx ActiveStatus=activating
Alois Mahdal

@Alois我想知道您遇到了哪种情况,您想让oneshot服务处于活动状态?你有例子吗?
Stephen Kitt

当然,@ StephenKitt。工具foo会对涉及重新启动的系统执行某些操作,foo_cleanup并在下次启动时使用一次性服务来清理问题。我测试这个(我的剧本还计划作为服务),并希望以后收集的错误,但是当事后(Vsauce频道的音乐)?好一个标准是foo_cleanup已经完成(“停止活动”)。
Alois Mahdal

可能值得指出的是,“失败”也是一个选项,如果您需要基于未启动的服务执行操作,则很有用。
Phill Healey

33

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

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

$ systemctl show -p SubState --value NetworkManager
running

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

$ systemctl show -p ActiveState --value x11-common
inactive
$ systemctl show -p SubState --value x11-common
dead

来自的注释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 "=".

2
+1为复杂的答案。请指定将接受--versionsystemctl选项的发行版。
SK Venkat

11

作为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

1
+1表示--value简介版本和发行版不起作用。
SK Venkat

3

我发现这对于命令行执行或正在编写脚本很有用。

从@StephenKitt复制

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

systemctl is-active --quiet <service name> || <service name> restart

||那里检查,如果从systemctl返回值是,如果由作者解释说这不是积极的非零意义。


您也可以使用“ is-failed”来测试是否需要重启。重新启动失败的服务似乎更加直观。
Phill Healey

是的,但是对我来说。我想练习自己,并假设一切都在正常进行。所以我可以用它来验证其他东西。只是如果您只是想检查它是否未运行,那么“失败”是一个正确的选择。:)
星号

3


我参加聚会太晚了,但是在脚本中始终不使用systemctl -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

这就是我的利用方式。

为了简单易用,请按照以下说明进行操作:

systemctl -q is-active tomcat.service  && echo "Tomcat Runnung" || echo "Service is not running at all "

有什么比简单更好的if systemctl is-active --quiet tomcat.service呢?另外,[[不是标准外壳。
Toby Speight

@TobySpeight您需要阅读我的文章,就像我在文章中提到的那样:“这就是我的使用方式。...分享我的。” 我从来没有说过,它是标准的shell用法,如果您将它放在单括号中,它将变成然后,但这超出了本文的范围。此外,我在下面提到了使用&&和轻松实现单行用法||
SAGAR Nair

2

不必像在Oxmel的答案中那样使用sed命令,它足以cut -d'=' -f 2用于所查询的所有类型的属性:

例如:

$ systemctl show -p ActiveState sshd | cut -d'=' -f2
active
$ systemctl show -p SubState sshd | cut -d'=' -f2
running

很好,但是您确实需要对这些命令的功能进行一些解释。
Phill Healey

-1

刚刚找到了这个很棒的小脚本:

#!/bin/bash
service=replace_me_with_a_valid_service

if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 ))
then
  echo "$service is running!!!"
else
  /etc/init.d/$service start
fi

资源


并非所有服务都具有相同名称的可执行文件,并且任何用户都可能正在运行意外匹配的命令-这是灾难的根源。
Toby Speight
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.