我有一个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中,您只能照顾您的子元素.任何方法(ps解析、pgrep、存储PID等)它试图解决有缺陷且存在巨大漏洞的问题.就说no吧.

相反,您需要监视流程的流程成为流程的父级.这是什么意思?这意味着只有starts个进程可以可靠地等待进程结束.在bash中,这绝对是微不足道的.

until myserver; do
    echo "Server 'myserver' crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

上面的bash代码在until循环中运行myserver次.第一行从myserver开始,等待它结束.当它结束时,until判断其退出状态.如果退出状态为0,则意味着它优雅地结束了(这意味着你要求它以某种方式关闭,它成功地关闭了).在这种情况下,我们不想重新启动它(我们只是要求它关闭!).如果退出状态为not 0until将运行循环体,它在STDERR上发出错误消息并重新启动循环(返回到第1行)after 1 second.

我们为什么要等一会儿?因为如果myserver的启动顺序出了问题,它会立即崩溃,你会有一个非常密集的不断重启和崩溃循环.sleep 1消除了压力.

现在,您需要做的就是启动这个bash脚本(可能是异步的),它将监视myserver,并根据需要重新启动它.如果您想在 bootstrap 时启动监视器(使服务器"存活"重新 bootstrap ),可以使用@reboot规则在用户的cron(1)中安排它.用crontab打开你的cron规则:

crontab -e

然后添加一条规则来启动监视器脚本:

@reboot /usr/local/bin/myservermonitor

或者;看看inittab(5)和/etc/inittab.您可以在其中添加一行,使其在某个初始级别有myserver个开始,并自动重新启动.


编辑

让我添加一些关于为什么要使用PID文件的信息.虽然他们很受欢迎;它们也有很大的缺陷,你没有理由不按正确的方式go 做.

考虑一下:

  1. 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.
  2. PID文件会过时.您需要过于复杂(或者我应该说,非常复杂)的逻辑来判断PID文件是否过时,任何这样的逻辑都会再次受到1.的攻击.

  3. 如果您甚至没有写访问权限,或者处于只读环境中,该怎么办?

  4. 这是毫无意义的过度复杂;看看我上面的例子有多简单.根本没必要让这件事复杂化.

See also: Are PID-files still flawed when doing it 'right'?

顺便说一句永远不要这样做.

  1. ps是很不合适的.而在几乎所有的UNIX系统上都可以找到它;如果您想要非标准输出,它的参数会有很大差异.标准输出仅用于人类消费,不用于脚本解析!
  2. 解析ps会导致很多误报.以ps aux | grep PID为例,现在想象有人在某个地方启动一个进程,并以一个数字作为参数,该参数恰好与启动守护进程时使用的PID相同!想象一下,两个人开始了一个X会话,而你却大喊X来杀死你的X会话.只是各种各样的不好.

如果你不想自己管理这个过程;有一些非常好的系统可以作为流程的监视器.例如,看看runit.

Linux相关问答推荐

Linux x86_64上PIE ELF可执行文件的.Text段的基本虚拟地址

shell中两个日期的天数差异

如何比较 2 个文件并将第二个文件的所有行打印到输出文件 awk

更改 awk 中的上一个重复行

什么命令用于在linux中创建或修改具有指定文件大小的多个文件

在 puppet 中管理 linux 的用户密码

为什么 fork() 在 setsid() 之前

argv的编码是什么?

如何使目录下的所有文件在linux上可读?

为什么 Linux 不通过 TSS 使用硬件上下文切换?

使用 linux 命令行 (bash) 从网络摄像头拍照

用于 Linux 的 Less 编译器

将 bash 脚本添加到路径

'&&' 与 '&' 与 Bash 中的 'test' 命令

docker compose:加载共享库时出错:libz.so.1:无法从共享对象映射段:不允许操作

linux根据文件名模式搜索文件

如何获取 GNU Makefile 中使用的 shell 命令的退出状态?

Hierarchical分层 ldd(1)

在linux中将制表符分隔的文件转换为csv的最快方法

未找到版本CXXABI_1.3.8(...要求)