如何使用shell脚本来监督程序?

时间:2010-07-21 23:01:18

标签: perl bash shell

我已经四处寻找,但还没有找到我正在寻找的东西。简而言之,我创建了一个bash脚本,在无限循环中运行,睡眠并检查进程是否正在运行。唯一的问题是,即使进程正在运行,也表示它不是,并打开另一个实例。

我知道我应该按进程名称检查而不是进程ID,因为另一个进程可以跳入并获取id。但是所有perl程序在我的系统上都被命名为Perl5.10.0,我打算打开同一个perl程序的多个实例。

以下“if”总是返回false,我在这里做错了什么???

while true; do

 if [ ps -p $pid ]; then
  echo "Program running fine"
  sleep 10

 else
  echo "Program being restarted\n"
  perl program_name.pl &
  sleep 5
  read -r pid < "${filename}_pid.txt"
 fi

done

5 个答案:

答案 0 :(得分:9)

摆脱方括号。它应该是:

if ps -p $pid; then

方括号是test命令的语法糖。这是一个完全不同的野兽,根本不会调用ps

if test ps -p $pid; then

事实上,当我运行它时会产生“-bash:[: - p:binary operator expected”。

答案 1 :(得分:7)

除了已经指出的语法错误之外,这是一种确保进程保持活跃的糟糕方法。

首先,你应该找出你的程序首先死亡的原因;这个脚本没有修复bug,它试图隐藏一个。

其次,如果程序保持运行非常重要,为什么你期望你的(至少已经有一次)错误的shell脚本能够完成这项工作呢?使用专门用于重新启动服务器进程的系统工具。如果您说您正在使用的平台以及服务器进程的性质。我可以提供更具体的建议。

在回复评论时添加

当然,有工程需要,但正如OP中提到的那样,在这种尝试中仍然存在一个错误:

  

我知道我应该按流程名称查看   而不是进程id,因为另一个   进程可以跳入并获取id。

所以现在你留下了一个PID跟踪脚本,而不是一个过程“保姆”。虽然机会很小,但现在的脚本有一个十秒钟的窗口,其中

  1. “受监控”流程失败
  2. 我启动了为期一周的emacs进程,它抓取了相同的PID
  3. 保姆脚本继续幸福地意识到其依赖失败
  4. 脚本不仅仅是错误的,它是无效的,因为它假定PID是进程的稳定标识符。有一些方法可以更好地处理,即使在shell脚本级别。最简单的是永远不要从脚本中分离perl的执行,因为除了观察子进程之外,脚本什么都不做。例如:

    while true ; do
        if perl program_name.pl ; then
             echo "program_name terminated normally, restarting"
        else
             echo "oops program_name died again, restarting"
        fi
    done
    

    这不仅更短更简单,而且实际上阻止了您真正感兴趣的条件:perl程序的运行状态。原始脚本重复检查运行状态条件(PID)的错误代理指示,因此可能会出错。并且,由于这个保姆脚本的整个目的是处理故障,如果设计本身有缺陷就会很糟糕。

答案 2 :(得分:3)

我完全同意摆弄PID几乎总是一个坏主意。 while true ; do ... done脚本非常好,但是对于生产系统来说,有几个流程管理员可以做到这一点以及更多,例如。

  • 使您能够向受监督的过程发送信号(不知道它的PID)
  • 检查服务已启动或停止的时间
  • 捕获其输出并将其写入日志文件

此类流程主管的示例为daemontoolsrunit。有关更详细的讨论和示例,请参阅Init scripts considered harmful。不要被标题所扰乱:传统的init脚本会像你一样遇到完全相同的问题(它们启动一个守护进程,将它的PID保存在一个文件中然后单独保留守护进程)。

答案 3 :(得分:1)

答案 4 :(得分:0)

这就是kill -0 $ pid的用途。如果存在具有pid $ pid的进程,则返回成功。