bash - 如果进程终止,如何编写 bash 脚本以重新启动进程?

标签 bash scripting cron

我有一个 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 代码运行 myserveruntil环形。第一行开始 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文件。虽然它们很受欢迎;它们也非常有缺陷,你没有理由不以正确的方式去做。

考虑一下:
  • 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 .
  • PID 文件变得陈旧。您需要过于复杂(或者我应该说,非平凡)的逻辑来检查 PID 文件是否过时,并且任何此类逻辑再次容易受到 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/

    相关文章:

    perl - 人们说 “Perl is very good at parsing” 是什么意思?

    python - 在 Docker 中运行 python cronjob 时缺少环境变量

    java - 计划的 Cron 运行超出 Spring Boot 中规定的时间

    bash - ssh 到远程文件夹并检查所有文件的脚本?

    python - 在 Pycharm 2016.3 中安装 pip

    shell - 如何将列表传递给 KornShell 脚本中的函数?

    java - 通过 bash 脚本向 Java 程序提供输入

    python - Crontab 不会在 Mac OS 上运行 python

    bash - 在 shell 编程中打印双引号

    bash - 别名命令执行不正确