我有一个 python 脚本,它将检查队列并对每个项目执行操作:
# checkqueue.py
while True:
check_queue()
do_something()
我如何编写一个 bash 脚本来检查它是否正在运行,如果没有,则启动它。大致如下伪代码(或者它应该做类似
ps | grep
的事情?):# keepalivescript.sh
if processidfile exists:
if processid is running:
exit, all ok
run checkqueue.py
write processid to processidfile
我将从 crontab 调用它:
# crontab
*/5 * * * * /path/to/keepalivescript.sh
最佳答案
避免使用 PID 文件、cron 或其他任何试图评估不是其子进程的进程。
在 UNIX 中,您只能等待您的 child ,这是有充分理由的。任何试图解决该问题的方法(ps 解析、pgrep、存储 PID 等)都存在缺陷并且存在漏洞。就说否 .
相反,您需要将监控您的流程的流程作为流程的父级。这是什么意思?这意味着只有启动进程的进程才能可靠地等待它结束。在 bash 中,这绝对是微不足道的。
until myserver; do
echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2
sleep 1
done
上面这段 bash 代码运行
myserver
在 until
环形。第一行开始 myserver
并等待它结束。结束时,until
检查其退出状态。如果退出状态是 0
,这意味着它正常结束(这意味着您要求它以某种方式关闭,并且它成功地关闭了)。在这种情况下,我们不想重新启动它(我们只是要求它关闭!)。如果退出状态不是 0
, until
将运行循环体,它在 STDERR 上发出错误消息并在 1 秒后重新启动循环(回到第 1 行)。为什么我们要等一下?因为如果
myserver
的启动顺序有问题它立即崩溃,您将有一个非常密集的循环,不断重启和崩溃。 sleep 1
消除了压力。现在你需要做的就是启动这个 bash 脚本(可能是异步的),它会监控
myserver
并根据需要重新启动它。如果您想在启动时启动监视器(使服务器“存活”重新启动),您可以使用 @reboot
在用户的 cron(1) 中安排它。规则。使用 crontab
打开您的 cron 规则:crontab -e
然后添加一个规则来启动你的监控脚本:
@reboot /usr/local/bin/myservermonitor
或者;查看 inittab(5) 和/etc/inittab。您可以在其中添加一行以获得
myserver
从某个初始级别开始并自动重生。编辑。
让我添加一些关于原因的信息 不是 使用PID文件。虽然它们很受欢迎;它们也非常有缺陷,你没有理由不以正确的方式去做。
考虑一下:
/etc/init.d/foo start
:开始 foo
, 写 foo
的 PID 到 /var/run/foo.pid
foo
不知何故死了。 bar
)都接受一个随机 PID,想象它接受 foo
旧的PID。 foo
不见了:/etc/init.d/foo/restart
阅读 /var/run/foo.pid
,检查它是否还活着,找到 bar
,认为是 foo
,杀死它,开始一个新的 foo
. 1.
的攻击。 . 另见:Are PID-files still flawed when doing it 'right'?
顺便一提; 比 PID 文件更糟糕的是解析
ps
! 永远不要这样做。ps
非常不便携。虽然您几乎可以在每个 UNIX 系统上找到它;如果你想要非标准输出,它的参数会有很大差异。并且标准输出仅供人类使用,不适用于脚本解析! ps
导致很多误报。拿 ps aux | grep PID
例如,现在想象有人用某个数字作为参数启动一个进程,该数字恰好与您启动守护进程的 PID 相同!想象一下,两个人开始了一个 X session ,而你正在寻找 X 来杀死你的 session 。这只是各种各样的坏事。 如果您不想自己管理流程;有一些非常好的系统可以充当您流程的监视器。调查 runit , 例如。
关于bash - 如果进程终止,如何编写 bash 脚本以重新启动进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/696839/