我正在为启动服务脚本编写停止例程:
do_stop()
{
rm -f $PIDFILE
pkill -f $DAEMON || return 1
return 0
}
问题是 pkill(与 killall 相同)也匹配代表脚本本身的进程,并且它基本上会自行终止。如何解决?
您可以从结果中显式过滤掉当前的 PID:
kill $(pgrep -f $DAEMON | grep -v ^$$\$)
要正确使用该-f
标志,请确保提供守护程序的整个路径,而不仅仅是一个子字符串。这将阻止您终止脚本(并消除对上述内容的需要grep
),并阻止您终止所有其他碰巧共享守护进程名称的系统进程。
pkill -f
接受一个完整的正则表达式。因此,pkill -f $DAEMON
您应该使用:
pkill -f "^"$DAEMON
确保只有当进程名称以给定的守护进程名称开头时,才会杀死它。
更好的解决方案是在启动进程时将进程的 pid(进程 ID)保存在文件中。对于停止进程,只需读取文件以获取要停止/终止的进程 ID。
从你的问题来看,你并不难使用 pgrep 和 pkill,所以这里有一些常用的其他选项。
1) 使用killproc
from /etc/init.d/functions
or /lib/lsb/init-functions
(适用于您的发行版和 linux 版本)。如果您正在编写服务脚本,如果您使用其他服务之一作为示例,您可能已经包含此文件。
Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]
使用它的主要优点是它发送 SIGTERM,等待查看进程是否终止并仅在必要时发送 SIGKILL。
2)您还可以使用killproc的秘诀,即找到要杀死的进程ID,使用pidof
它可以-o
选择排除特定进程。的参数-o
可以是$$
当前进程 ID,也%PPID
可以是 pidof 解释为调用 pidof 的脚本的特殊变量。最后,如果守护进程是一个脚本,您将需要 -x 以便您尝试通过它的名称来终止脚本,而不是终止 bash 或 python。
for pid in $(pidof -o %PPID -x progd); do
kill -TERM $pid
done
你可以在文章Bash: How to check if your script is already running中看到一个例子