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

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

我的问题:

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

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

但是(特别是自从转向 systemd 以来)打印出一大堆文本,解析起来有点混乱。我假设有一个针对具有简单输出或我可以检查的返回值的脚本的命令。

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

或者我应该闭嘴并用一点 pgrep 弄脏我的手?

答案1

systemctl有一个is-active为此的子命令:

systemctl is-active --quiet service

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

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

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

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

一次性单位没有“RemainAfterExit”永远不会进入活动单元状态,因此is-active永远不会成功;要处理此类单位,is-active可以分析 的文本输出:

systemctl is-active service

这将为当前正在运行的一次性单元输出“activating”,为当前未运行但上次运行成功(如果有)的一次性单元输出“inactive”,为当前未运行的一次性单元输出“failed”并且上次运行时失败了。is-active这些单位总是返回非零状态,因此运行

systemctl is-active service ||:

如果你需要忽略它。

答案2

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 "=".

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

systemctl show -a polkit

LoadState不幸的是, 、ActiveState和的可能值SubState在联机帮助页中没有记录;相反,它们记录在 D-Bus 接口描述中org.freedesktop.systemd1https://www.freedesktop.org/software/systemd/man/org.freedesktop.systemd1.html

LoadState包含一个状态值,反映该单元的配置文件是否已加载。当前定义了以下状态:“ loaded”、“ error”和“ masked”。 “ loaded”表示配置加载成功。 “ error”表示配置加载失败。该LoadError字段(见下文)包含有关此故障原因的信息。 “ masked”表示该单元当前被屏蔽(即符号链接到/dev/null或为空)。请注意,LoadState与 完全正交ActiveState(见下文),因为没有有效加载配置的单元可能处于活动状态(因为配置可能已在单元已处于活动状态时重新加载)。

ActiveState包含反映单元当前是否处于活动状态的状态值。当前定义了以下状态:“ active”、“ reloading”、“ inactive”、“ failed”、“ activating”和“ deactivating”。 “ active”表示该单元处于活动状态(显然......)。 “ reloading”表示该单元处于活动状态并且当前正在重新加载其配置。 “ inactive”表示它处于非活动状态,并且先前的运行已成功或尚未发生先前的运行。 “ failed”表示它处于非活动状态,并且之前的运行未成功(有关其原因的更多信息可在单元类型特定接口上找到,例如“结果”属性中的服务,请参见下文)。 “ activating”表示该单元之前处于非活动状态,但当前正在进入活动状态。相反,“ deactivating”表示该单元当前处于停用过程中。

SubStateActiveState对覆盖但了解特定于单元类型的更细粒度状态的同一状态机的状态进行编码。其中ActiveState仅覆盖六个高级状态,SubState可能覆盖映射到六个高级状态的更多低级单元类型特定状态。请注意,多个低级状态可能映射到相同的高级状态,但反之则不然。并非所有高级别状态在所有单位类型上都有低级别对应项。此时,低级状态未在此处记录,并且比上面解释的常见高级状态更有可能在以后扩展。

有很多房产,所以如果您知道自己在寻找什么......

$ systemctl show - polkit | grep Active
ActiveState=active
ActiveEnterTimestamp=Thu 2020-07-02 07:24:40 IST
ActiveEnterTimestampMonotonic=6682102
ActiveExitTimestamp=
ActiveExitTimestampMonotonic=0

答案3

作为对 Zanna 答案的补充,引入了--value选项systemctl showsystemd 版本 230。因此,它可能在某些发行版(例如 debian jessie)上不可用。

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

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running

答案4

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

复制自@StephenKitt

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

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

那里||检查 systemctl 的返回值是否非零,意思是如果它没有按照作者的解释激活。

相关内容