我的问题:

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

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

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

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

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

评论

initd->重新生成| systemd->重新启动=始终。手册页中的详细信息。

#1 楼

systemctl对此具有一个is-active子命令:

systemctl is-active --quiet service


如果service处于活动状态,则退出状态为零,否则为非零,这使其非常适合脚本:

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


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

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

评论


小心oneshot服务。它们仅处于非活动状态或处于激活状态,并且systemctl状态和systemctl均为活动退出状态(从3开始)。(从systemd-241开始) grep -qx ActiveStatus =正在激活

–阿洛瓦·马哈德(Alois Mahdal)
19年7月16日在19:51



@Alois我想知道您想在哪种情况下考虑使oneshot服务处于活动状态;你有例子吗?

–斯蒂芬·基特(Stephen Kitt)
19年7月20日在22:09

当然,@ StephenKitt。工具foo对系统进行一些涉及重新引导的操作,并在下次引导时使用一次性服务(例如foo_cleanup)进行清理。我正在对此进行测试(我的脚本也被安排为服务),并希望事后收集错误,但是事后几点(vsauce音乐)?好一个标准是foo_cleanup已经完成(“停止活动”)。

–阿洛瓦·马哈德(Alois Mahdal)
19年8月4日在16:18

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

– Phill Healey
19年9月6日在16:10

注意:对于webmin,唯一有效的命令是:service webmin status。 systemctl无法正常工作

–哈多曼
20年8月18日在15:48



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

要查看服务的可用属性,请运行(例如,对于polkit
systemctl show -a polkit

有很多属性,因此,如果您知道要查找的内容...
$ systemctl show - polkit | grep Active
ActiveState=active
ActiveEnterTimestamp=Thu 2020-07-02 07:24:40 IST
ActiveEnterTimestampMonotonic=6682102
ActiveExitTimestamp=
ActiveExitTimestampMonotonic=0


评论


+1为复杂的答案。请指定将接受systemctl的--version选项的发行版。

– S.K.文卡特
18-4-26在11:31



在Raspbian上,我使用了有时会中断的服务。代替“活动(运行)”,其状态将为“活动(退出)”。 “ systemctl是活动的”不会区分。这个答案给了我我所需要的区别:运行/退出/死亡

–皮拉
20-05-31在18:25

在哪里可以获得可用属性的列表?

–列宁·拉杰·拉塞卡斯卡兰(Lenin Raj Rajasekaran)
20年7月2日在4:59

我编辑了@LeninRajRajasekaran,在答案的末尾添加了如何查看此内容的信息-这对您有帮助吗?

–赞娜
20年7月2日,9:25

@Zanna谢谢,我刚刚做了“ service $ serviceName status | grep Active”来获取完整的状态信息。很高兴认识我家乡的人🙏

–列宁·拉杰·拉塞卡斯卡兰(Lenin Raj Rajasekaran)
20年7月2日在22:21

#3 楼

作为对Zanna的回答的补充,已在systemd的230版中引入了--valuesystemctl show选项。因此,在某些发行版(如debian jessie)上可能不可用。

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

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


评论


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

– S.K.文卡特
18年4月26日在11:29

#4 楼

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

从@StephenKitt复制

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

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


那里的||检查systemctl的返回值是否为非零,这意味着它是否不如作者所解释的那样有效。

评论


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

– Phill Healey
19年9月6日在16:14

是的,但是对我来说。我想练习自己,并假设一切都在运转,如果不是。这样我就可以使用它来验证其他内容。只是如果您只是想检查它是否未运行,那么“失败”是正确的选择。 :)

–星号
19年9月8日在2:02

我认为Phil的观点是,使用is-active意味着即使脚本已手动停止,该脚本也将重新启动该服务,这可能会引起一些混乱。

– SteenSchütt
20年1月21日在10:35



我将其放入cron作业中,并添加了日志记录:systemctl is-active --quiet <服务名称> || (回显“ ...” >> log.txt && systemctl restart <服务名称>)。

– Manngo
20-11-27在1:46

#5 楼


我参加聚会太晚了,但是在脚本中始终不主动使用systemctl以及&&||。下面是我用于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 "
 


评论


与systemctl是否处于活动状态--quiet tomcat.service相比,这比简单的方法好吗?另外,[[不是标准外壳。

– Toby Speight
19年6月13日在17:55



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

– SAGAR Nair
19年6月19日在9:34

#6 楼

使用systemctl有很多答案。

您还有其他选择($?派上用场了):


使用pidof命令:假设我正在尝试查找如果redis-server正在运行。首先发出pidof redis-server,然后检查
$?的值。如果它正在运行,您将发现0;否则,将发现0。否则为非零。
特定于服务的解决方案:如果该服务提供了一种检查服务是否正在运行的方法,则可以使用该方法。对于redis-service示例,如果服务正在运行,我们将获得redis-cli ping命令的PONG响应。发出redis-cli ping之后,我将检查$?,如果它为0,则服务正在运行。


评论


总的来说,systemctl似乎更好,但是在Linux的Windows子系统(v1)中,它将无法正常工作。 +1,对于WSL我来说已经足够了。如果您不想使用$ ?,您也可以将例如pidof cron直接放入测试中,或者执行cron_pid = $(pidof cron)在以后使用。如果服务未运行,则输出为空字符串,因此可以像[-z $ cron_pid];一样对其进行测试。然后做某事;科幻

–内森(Nathan)
20 Jan 25 '15:00



#7 楼

无需像在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
19年9月6日在16:12

#8 楼

也适用于非系统操作系统。

ps -C service-name怎么样?
检查$?以获得答案。如果0正在运行,如果1未运行。

示例:

ps -C privoxy && echo running


ps -C privoxy 1>/dev/null && echo running

注意事项:

我注意到长度超过14个字符的服务名称可能会误判。

另外,请参阅“ Nick S”的评论。

示例:

正确显示正在运行:

$ ps -C notification-daemon
  PID TTY          TIME CMD
 7418 ?        00:00:04 notification-da


不正确显示正在运行:

$ ps -C notification-daemon-fake
  PID TTY          TIME CMD
 7418 ?        00:00:04 notification-da


正确显示由于少于14个字符而无法运行:

$ ps -C notification
  PID TTY          TIME CMD


我从这里得到了这个答案。

评论


很高兴了解ps的-C选项。但是,如果正在运行该命令的另一个实例,而不是作为服务运行,则这将为假肯定,正如我在问题中提到的那样。

–尼克S
20-2-13在14:27

我不知道我刚刚对其进行了测试以验证,您是正确的。因此,这不是一个好的解决方案。

–́ajnabi
20-2-21在19:19

#9 楼

这用于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 &

程序退出时,它还会返回错误ID(带符号的字节)。
退出时没问题,该值通常为0。
由于错误而退出时,该值通常为错误ID或经常为-1。
此值通常用于命令集成,例如打印的数字状态ID程序输出。
通过命令链接使用它有两个选项&&和||
||。检查出口返回值是否不为零,然后运行链接的命令
而不是||无法编写&&
&&检查退出返回值是否为零,然后运行链接的命令
,类似于此页面上的@asterisk答案(对于systemd)
https:/ /unix.stackexchange.com/a/500336/156304

#10 楼

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

#!/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
19年6月13日在17:54

如果服务消失,您似乎想让它重新启动。在初始化时,关键字在/ etc / inittab中重新生成。现在,使用systemd,您必须在/etc/systemd/system/multi-user.target.wants/mydaemon.service中配置服务,只需添加以下行即可:Restart = always。

–schweik
20-2-21在19:56

#11 楼

在脚本下面,我直接从“外壳脚本”中获取了“检查服务状态”一文,并做了一个小小的改动以确定给定服务是否已安装在系统上。
将服务作为Docker并将下面的脚本另存为check_service.sh
 #!/bin/bash

if [ "$#" = 0 ]; then
  echo "Usage wasdkiller@kushan:~$ sudo service docker status
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2020-09-22 14:30:59 +0530; 6min ago
     Docs: https://docs.docker.com
 Main PID: 25220 (dockerd)
    Tasks: 17
   CGroup: /system.slice/docker.service
           └─25220 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.033698487+05:30" level=warning msg="Your kernel does not support cgroup rt runtime"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.033703758+05:30" level=warning msg="Your kernel does not support cgroup blkio weight"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.033707702+05:30" level=warning msg="Your kernel does not support cgroup blkio weight_device"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.033812954+05:30" level=info msg="Loading containers: start."
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.101347726+05:30" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to 
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.130162694+05:30" level=info msg="Loading containers: done."
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.172380859+05:30" level=info msg="Docker daemon" commit=48a66213fe graphdriver(s)=overlay2 version=19.03.12
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.172860484+05:30" level=info msg="Daemon has completed initialization"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.228633124+05:30" level=info msg="API listen on /var/run/docker.sock"
සැප් 22 14:30:59 kushan systemd[1]: Started Docker Application Container Engine.
lines 1-19/19 (END)
wasdkiller@kushan:~$
wasdkiller@kushan:~$
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ source check_service.sh docker
Service docker is running
wasdkiller@kushan:~$
 "
  exit 0
fi

service=
is_running=$(ps aux | grep -v grep | grep -v "wasdkiller@kushan:~$ sudo service docker stop
wasdkiller@kushan:~$ sudo service docker status
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Tue 2020-09-22 14:41:00 +0530; 3s ago
     Docs: https://docs.docker.com
  Process: 25220 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=0/SUCCESS)
 Main PID: 25220 (code=exited, status=0/SUCCESS)

සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.130162694+05:30" level=info msg="Loading containers: done."
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.172380859+05:30" level=info msg="Docker daemon" commit=48a66213fe graphdriver(s)=overlay2 version=19.03.12
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.172860484+05:30" level=info msg="Daemon has completed initialization"
සැප් 22 14:30:59 kushan dockerd[25220]: time="2020-09-22T14:30:59.228633124+05:30" level=info msg="API listen on /var/run/docker.sock"
සැප් 22 14:30:59 kushan systemd[1]: Started Docker Application Container Engine.
සැප් 22 14:41:00 kushan systemd[1]: Stopping Docker Application Container Engine...
සැප් 22 14:41:00 kushan dockerd[25220]: time="2020-09-22T14:41:00.691599535+05:30" level=info msg="Processing signal 'terminated'"
සැප් 22 14:41:00 kushan dockerd[25220]: time="2020-09-22T14:41:00.692925147+05:30" level=info msg="stopping event stream following graceful shutdown" error="<nil>" module=libcontainerd namespace=moby
සැප් 22 14:41:00 kushan dockerd[25220]: time="2020-09-22T14:41:00.693778800+05:30" level=info msg="Daemon shutdown complete"
සැප් 22 14:41:00 kushan systemd[1]: Stopped Docker Application Container Engine.
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ source check_service.sh docker
Found startap script /etc/init.d/docker. Start it? Y/n ? y
Starting service...
[ ok ] Starting docker (via systemctl): docker.service.
wasdkiller@kushan:~$ 
" | grep $service | wc -l | awk '{print }')

if [ $is_running != "0" ]; then
  echo "Service $service is running"
else
  initd=$(ls /etc/init.d/ | grep $service | wc -l | awk '{ print  }')

  if [ $initd = "1" ]; then
    startup=$(ls /etc/init.d/ | grep $service)
    echo -n "Found startap script /etc/init.d/${startup}. Start it? Y/n ? "
    read answer

    if [ $answer = "y" -o $answer = "Y" ]; then
      echo "Starting service..."
      /etc/init.d/${startup} start
    fi
  else
    echo "Service $service not yet installed"
  fi
fi
 


在服务启动时运行脚本。

 wasdkiller@kushan:~$ sudo service docker123 status
Unit docker123.service could not be found.
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ 
wasdkiller@kushan:~$ source check_service.sh docker123
Service docker123 not yet installed
wasdkiller@kushan:~$
 


在服务关闭时运行脚本。

 q4312079q 


在尚未在系统中安装服务时运行脚本。

 q4312079q 


评论


我能知道为什么我对此答案投反对票吗?

– Kushan Gunasekera
20-09-22在10:37

这看起来像是一个有用的脚本,但是它检查服务是否正在运行的方式是ps aux |。我在问题中提到的grep -v grep方法。从其他答案来看,似乎有更简单,更好的方法来执行此操作(systemctl是活动的,systemctl显示)。感谢您的脚本,但是如果您想知道为什么要投票,那可能就是这样。在回答之前,请务必仔细阅读问题和其他答案。

–尼克S
20-09-22在19:34

非常感谢@NickS,实际上我必须捕获该服务是否已安装。所以systemctl is-active docker和systemctl is-active docker123都给出与inactive相同的答案。就我而言,如果服务处于停止状态或尚未安装,则必须运行该服务,然后必须安装并运行该服务。无论如何,再次感谢@NickS。谢谢您,从这个答案中学到了很多知识。当然,我下次会检查问题和答案。

– Kushan Gunasekera
20-09-22在23:47