我一直在研究使用shell脚本进行过程管理,我开始意识到确保它做得正确是多么困难。
例如,您可以将程序的PID记录到文件中,并在其上进行wait,并在程序退出后清除PID文件。
例如,如果您尝试并从init脚本中kill这个守护进程,您可能会想到这样做:
do_stop() {
kill $(</var/run/program.pid)
}这显然行不通。在获得PID和发送杀死信号之间,另一个进程可能已经死亡并取代了它。
正确的方法似乎需要在程序的父程序中使用IPC向其子程序发送杀死信号。这将确保进程的PID不会被另一个进程重用。
我一直在尝试编写自己的init脚本,这些脚本尽可能的正确。在这种情况下,我一直在为NRPE编写一个。不幸的是,NRPE将自己去初始化并与init不承认,这意味着我不能在上面使用wait。相反,我想出了以下解决方案:
do_stop() {
echo "Stopping (sending SIGTERM to) nrpe"
pkill -u nrpe || { echo >&2 "nrpe isn't running"; exit 1; }
}nrpe用户运行的唯一进程是NRPE本身,考虑到系统在我的控制下,我认为这是一个相对合理的解决方案。
我好奇的是pkill的原子性(如果这是正确的话)。我假设pkill遵循以下步骤:
SIGTERM (默认情况下)发送到所获得的PID假设pkill -u nrpe在第一步给出了42的PID值,那么在第二步发生之前,nrpe的S过程是否可能死亡,而另一个过程可能会在第二步发生之前发生呢?
发布于 2014-07-03 19:34:06
你是正确的怀疑有一个(小!)原子性问题
无论您使用什么方法,也不管它是一个系统标准实用程序,比如start-stop-daemon,一个滚动自己的PID文件,使用pkill通过用户ID、二进制文件或其他方式查询和杀死,总是有一个间隔,可以找到要杀死的进程,也可以将进程ID提供给kill系统调用,以便向其发送信号。
基本上,你不应该担心它。为了遇到麻烦,以下两种情况都必须发生:
这真的不太可能。
请注意,在您正在学习的特定案例中,您确实有一种保护自己不受此影响的方法。nrpe用户运行的唯一进程是NRPE本身,因此如果在发出kill命令之前切换到nrpe用户(可能是从root ),那么在非常不可能的情况下,您可能会试图杀死属于其他东西的可怜的无辜进程,但是您将没有权限这样做,也不会产生任何效果。
https://unix.stackexchange.com/questions/140552
复制相似问题