Kill Services
如何杀死一个守护进程?
如果守护进程(一套服务)只存在一个单一的进程中,则直接对其发送信号即可。使用 kill
或 killall
命令。 killall
是根据进程名发送信号,所有相同名称的进程都会收到。
如果守护程序创建了pid文件,那么规范一些的操作应当是根据pid文件中的pid号去发信号。pid文件一般在 /var/run/*.pid
, 如/var/run/atd.pid
,/var/run/crond.pid
,/var/run/docker.pid
,/var/run/sshd.pid
等。
不过,通常情况可能更复杂,因为守护程序一般都会创建一些子进程,如cron和at作业,cgi脚本等。如果只杀死了它们的主进程, 那么它们衍生出的子进程可能会主动关闭,也可能会交给init程序管理,(这取决于程序自己的行为逻辑),如果这些子进程交给 init进程管理了,就难以追踪了。
而在systemd
中,支持对整个服务的所有进程发送信号,(得益于systemd使用的cgroups机制),使用命令 systemctl kill
即可。默认发送 SIGTERM
信号。信号名在这里可以不加SIG前缀。
1
2
3
4
5
6
# systemctl kill [PATTERN] ...
# Send a signal to one or more processes of the unit. Use --kill-who= to select which process to kill.
# Use --signal= to select the signal to send.
systemctl kill crond.service
systemctl kill -s SIGKILL crond.service
这样,整个service中所有的进程都会收到相应的信号。如果只希望发送给主进程,则可以使用
1
systemctl kill -s HUP --kill-who=main crond.service
传统方式中,守护程序的子进程的终止通常需要守护程序配合来完成。如果守护程序没能正确终止子进程,那么清理起来就非常麻烦, 而到了systemd中,可以很方便的解决这类问题,它能够对一个服务的所有进程发信号。
Stop Services
systemctl kill
和 systemctl stop
的关联,kill本身的直接释义是向service中的进程发信号,发送SIGTERM信号一般可以关闭, 如果发SIGKILL,可以强制结束。 而 stop方式则是通过官方配置的方式来关闭服务,即调用服务文件中配置了ExecStop=的stop命令。 通常stop应该就足够了。Kill是更激烈的版本,适用于不希望通过stop命令关闭服务,或者当服务以其他方式被 hosed 或挂起时。