我用 LinuxLinux学习|Gentoo/Arch/FreeBSDLinux运维进阶-Python,Docker,Shell

systemd的oneshot 与 forking servic

2020-04-05  本文已影响0人  My熊猫眼

oneshot 类型的service:

A. 服务启动结果判断:
会等待”ExecStart=“ 指定的命令执行完成,然后根据返回值来判定是否执行成功;如果返回值为0, 那么认为执行成功,否则会有类似“failed to start service because control process exited with error code "这样的报错信息. 如果有多个“ExecStart=” 参数,那么会依次执行,只要有返回值是“error code”的,那么都会导致该service 启动失败.
B. 服务状态查看:
无论执行成功或者失败,通过 "systemctl status" 来查看服务状态的时候,一般都会有 “Main PID: xxxx (code=exited, status=xx/...)” 之类的提示,只有 status=0 才表示服务启动成功,和上面A的描述是一致的,但是我们有时候可能会看到 "systemctl status” 显示该服务的状态是 : inactive(dead) 之类的提示,这是因为: control process 退出之后,oneshot类型的服务自动进入 inactive(dead) 状态, 但是如果设置了: RemainAfterExit=yes 的话,那么oneshot 类型的service 在成功启动之后会进入actived 状态. 所以,对于oneshot类型的服务,要查看其当前的状态,应该查看“exit ” code.
C. 从子进程的角度看oneshot:
对于oneshot类型的service, 其在启动过程中并不关注有没有子进程,也不关注子进程的状态变化, 只要control process 退出的code 是0, 那么就表示启动成功. 所以很多服务的启动脚本可以修改为oneshot 类型的service unit.

forking 类型的service unit:

A.
这种类型和oneshot类型很像 . 如果control process的退出code不是0, 那么服务启动就被判定为fail. 同时,该类型并不支持多个 "ExecStart=" 参数。
B.
对于服务状态的显示,如果启动成功,那么 Active 状态始终是: running. 否则就是 inactive(dead) 的状态;
C.
和oneshot不同的是: forking 类型的service, 其control process (ExecStart= )退出之后,其forking的子进程一定存在(如果不存在,那么该服务就不能是forking类型),并且应该是持续存在的, 除非手动去停止这个service.
如果forking的所有子进程中的main process 停止了,那么service 的状态就从running 变成了inactive(dead),同时其他的子进程也会被强制kill, 因为查寻service status的时候其实判断的是main process子进程的状态,基于这个原因,对于forking类型的service, 通常需要配合 "PIDFile=" 这个参数一起使用来指定main process 子进程,一旦main process 子进程退出,那么其他的子进程将也会被强制结束.而如果没有指定main process, 那么就算其中一个forking的子进程结束了,但是其他的子进程依然存在,这样的话,service的状态就依然是 running 的. 这就导致了"systemctl status" 查看的服务状态不够准确的问题. 所以建议 forking类型的service 总是加上 ”PIDFile=“ 这个参数

以下的代码验证了主进程退出就会导致 service unit的其他进程被系统kill的这种情况,主进程为 "sleep 30" ,当时间到30s后,主进程自动退出.从而导致 "sleep 3600" 进程被强制kill了.

[root@www ~]# cat /etc/systemd/system/my.service 
[Unit]
Description="Testing Service for forking"
After=syslog.service
[Service]
Type=forking
PIDFile=/var/run/my.pid
ExecStart=/root/s.sh start
ExecStop=/root/s.sh stop
[Install]
WantedBy=basic.target
[root@www ~]# cat s.sh 
#!/bin/bash
if [[ $1 = "start" ]];then
    nohup sleep 30 &
    nohup sleep 3600 & 
    echo `ps -ef | grep "sleep 30" | grep -Evi grep | awk '{print $2}'` >/var/run/my.pid
    exit 0
else:
    exit 0
fi
[root@www ~]# 

本文原创,转载请注明出处

上一篇 下一篇

猜你喜欢

热点阅读