运维排查 | Systemd 之服务停止后状态为 failed-问题出现

我们的 zookeeper 是通过源码编译来安装,为了方便管理,决定改成通过 systemd 来管理。

下面是 zookeeper 的 service 文件

# zookeeper
[Unit]
Description=Zookeeper
After=network.target

[Service]
Type=forking
ExecStart=/opt/zookeeper/bin/zkServer.sh start
ExecStop=/opt/zookeeper/bin/zkServer.sh stop
PIDFile=/var/lib/zookeeper/zookeeper_server.pid

[Install]
WantedBy=multi-user.target

可以看到,配置文件分成几个区块,每个区块包含若干条键值对。

[Unit]

Unit 部分的 Description 字段给出当前服务的简单描述接下来的设置是启动顺序:

  1. After 字段:表示 zookeeper.service 应该在哪些服务之后启动。
  2. Before字段,表示 zookeeper.service 应该在哪些服务之前启动。

注意,AfterBefore字段只涉及启动顺序,不涉及依赖关系。

[Service]

Service 部分定义如何启动当前服务。

  • ExecStart:启动进程时执行的命令。

  • ExecStop:停止服务时执行的命令。

  • Type:定义启动类型

    1. simple(默认值):ExecStart字段启动的进程为主进程
    2. forking:ExecStart字段将以fork()方式启动,此时父进程将会退出,子进程将成为主进程
    3. oneshot:类似于simple,但只执行一次,Systemd 会等它执行完,才启动其他服务
    4. dbus:类似于simple,但会等待 D-Bus 信号后启动
    5. notify:类似于simple,启动结束后会发出通知信号,然后 Systemd 再启动其他服务
    6. idle:类似于simple,但是要等到其他任务都执行完,才会启动该服务。一种使用场合是为让该服务的输出,不与其他服务的输出相混合

[Install]

Install 部分定义如何安装这个配置文件,即怎样做到开机启动

  • WantedBy:表示该服务所在的 Target。

Target 的含义是服务组,表示一组服务。WantedBy=multi-user.target指的是,kafka 和 zookeeper 所在的 Target 是 multi-user.target

这个设置非常重要,因为执行systemctl enable 命令时,zookeeper .service 的一个符号链接,就会放在/etc/systemd/system目录下面的multi-user.target.wants子目录之中。

Systemd 有默认的启动 Target。

[root@localhost ~]# systemctl get-default
multi-user.target

上面的结果表示,默认的启动 Target 是 multi-user.target。在这个组里的所有服务,都将开机启动。这就是为什么 systemctl enable 命令能设置开机启动的原因。

编写好 service 文件之后,我们执行下面的命令来启动 zookeeper:

[root@localhost ~]# systemctl start zookeeper.service

接着看下 zookeeper 的运行状态

[root@localhost ~]# systemctl status zookeeper.service       
● zookeeper.service - Zookeeper
   Loaded: loaded (/usr/lib/systemd/system/zookeeper.service; enabled; vendor preset: disabled)
   Active: active (running) since 一 2024-04-01 09:10:23 CST; 2s ago
  Process: 60955 ExecStop=/opt/zookeeper/bin/zkServer.sh stop (code=exited, status=0/SUCCESS)
  Process: 61116 ExecStart=/opt/zookeeper/bin/zkServer.sh start (code=exited, status=0/SUCCESS)
 Main PID: 61132 (java)
   CGroup: /system.slice/zookeeper.service
           └─61132 java -Dzookeeper.log.dir=/opt/zookeeper/bin/../logs -Dzookeeper.log.file=zookeeper--server-localhost.localdomain.log -Dzookeepe...

4月 01 09:10:22 localhost.localdomain systemd[1]: Starting Zookeeper...
4月 01 09:10:22 localhost.localdomain zkServer.sh[61116]: /usr/sbin/java
4月 01 09:10:22 localhost.localdomain zkServer.sh[61116]: ZooKeeper JMX enabled by default
4月 01 09:10:22 localhost.localdomain zkServer.sh[61116]: Using config: /opt/zookeeper/bin/../conf/zoo.cfg
4月 01 09:10:23 localhost.localdomain zkServer.sh[61116]: Starting zookeeper ... STARTED
4月 01 09:10:23 localhost.localdomain systemd[1]: Started Zookeeper.

active (running) 表示运行正常

当我们执行 systemctl stop zookeeper.service 命令停止 zookeeper 的时候,问题出现了

[root@localhost ~]# systemctl status zookeeper.service 
● zookeeper.service - Zookeeper
   Loaded: loaded (/usr/lib/systemd/system/zookeeper.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since 一 2024-04-01 09:10:30 CST; 906ms ago
  Process: 61183 ExecStop=/opt/zookeeper/bin/zkServer.sh stop (code=exited, status=0/SUCCESS)
  Process: 61116 ExecStart=/opt/zookeeper/bin/zkServer.sh start (code=exited, status=0/SUCCESS)
 Main PID: 61132 (code=exited, status=143)

4月 01 09:10:23 localhost.localdomain systemd[1]: Started Zookeeper.
4月 01 09:10:29 localhost.localdomain systemd[1]: Stopping Zookeeper...
4月 01 09:10:29 localhost.localdomain zkServer.sh[61183]: /usr/sbin/java
4月 01 09:10:29 localhost.localdomain zkServer.sh[61183]: ZooKeeper JMX enabled by default
4月 01 09:10:29 localhost.localdomain zkServer.sh[61183]: Using config: /opt/zookeeper/bin/../conf/zoo.cfg
4月 01 09:10:29 localhost.localdomain systemd[1]: zookeeper.service: main process exited, code=exited, status=143/n/a
4月 01 09:10:30 localhost.localdomain zkServer.sh[61183]: Stopping zookeeper ... STOPPED
4月 01 09:10:30 localhost.localdomain systemd[1]: Stopped Zookeeper.
4月 01 09:10:30 localhost.localdomain systemd[1]: Unit zookeeper.service entered failed state.
4月 01 09:10:30 localhost.localdomain systemd[1]: zookeeper.service failed.

可以看到,zookeeper 服务在停止后并不是 inactive ,而是 failed 状态,最后两行输出里有 Unit zookeeper.service entered failed state./zookeeper.service failed 字段

上一篇:安阳旅游地图


下一篇:Spring IOC控制反转、DI注入以及配置-ref属性表示参照哪个bean对象