16

我正在为启动服务脚本编写停止例程:

do_stop()
{
  rm -f $PIDFILE
  pkill -f $DAEMON || return 1
  return 0
}

问题是 pkill(与 killall 相同)也匹配代表脚本本身的进程,并且它基本上会自行终止。如何解决?

4

3 回答 3

16

您可以从结果中显式过滤掉当前的 PID:

kill $(pgrep -f $DAEMON | grep -v ^$$\$)

要正确使用该-f标志,请确保提供守护程序的整个路径,而不仅仅是一个子字符串。这将阻止您终止脚本(并消除对上述内容的需要grep),并阻止您终止所有其他碰巧共享守护进程名称的系统进程。

于 2013-04-01T09:06:14.823 回答
11

pkill -f接受一个完整的正则表达式。因此,pkill -f $DAEMON您应该使用:

pkill -f "^"$DAEMON

确保只有当进程名称以给定的守护进程名称开头时,才会杀死它。

更好的解决方案是在启动进程时将进程的 pid(进程 ID)保存在文件中。对于停止进程,只需读取文件以获取要停止/终止的进程 ID。

于 2013-04-01T09:07:51.260 回答
1

从你的问题来看,你并不难使用 pgrep 和 pkill,所以这里有一些常用的其他选项。

1) 使用killprocfrom /etc/init.d/functionsor /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中看到一个例子

于 2016-09-22T21:15:53.403 回答