我知道我应该按进程名称检查而不是进程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
答案 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跟踪脚本,而不是一个过程“保姆”。虽然机会很小,但现在的脚本有一个十秒钟的窗口,其中
脚本不仅仅是错误的,它是无效的,因为它假定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
脚本非常好,但是对于生产系统来说,有几个流程管理员可以做到这一点以及更多,例如。
此类流程主管的示例为daemontools或runit。有关更详细的讨论和示例,请参阅Init scripts considered harmful。不要被标题所扰乱:传统的init脚本会像你一样遇到完全相同的问题(它们启动一个守护进程,将它的PID保存在一个文件中然后单独保留守护进程)。
答案 3 :(得分:1)
答案 4 :(得分:0)
这就是kill -0 $ pid的用途。如果存在具有pid $ pid的进程,则返回成功。