检测java进程是否正在运行的万无一失的方法

检测java进程是否正在运行的万无一失的方法

我有一个连续运行的java进程,有时由于我尚未完全调试的原因,它会崩溃。因此,我还有一个 cron 作业,每 5 分钟查找一次进程,如果发现进程没有运行,它会调用一个脚本来重新启动它。

问题是,有时,检查脚本每隔一段时间就会得到一个误报——它认为进程没有运行,而实际上它正在运行。我还没有看到它何时执行此操作有任何一致性。但我确实需要一种完全万无一失的方法来检查进程是否正在运行。

我目前正在做的是这样的:

if ! pgrep -f '/path/to/XML2DB.jar -n' > /dev/null
then
    nice -n 19 java -Xmx2024M -jar /path/to/XML2DB.jar -n > /dev/null 2>/dev/null &
    echo "" | mail -s "$HOST: xml2db was found not running, is being started" [email protected]
fi

在 pgrep 之前,我们使用过,! ps ax | grep -v grep | grep "XML2DB.jar -n" > /dev/null但这也会产生误报。

Linux 版本Scientific Linux SL release 3.0.9 (SL)现在LSB Version是 1.3。

提前致谢!

答案1

ps ax | grep -v grep | grep "XML2DB.jar -n"技术存在竞争条件:grep实例可能会或可能不会及时启动以ps查看它们,因此您会得到不准确的计数:请参阅这里这里。您不是第一个在使用它时遇到麻烦的人。

strace pgrep somepattern在 RHEL 盒子上做了一个测试来了解pgrep正在做什么。它统计 中的每个进程目录/proc,并打开/proc/<PID>/cmdline一些 PID,并读取内容,大概是为了与pgrep命令行上给出的模式匹配。我在这里挥手,但我敢打赌那里也存在竞争条件。

对此唯一万无一失的解决方案是让 Java 进程尝试创建一个“锁定目录”。目录创建对于用户进程来说是原子的。如果锁定目录已经存在,则退出并显示错误消息,否则启动。创建后锁定目录,它应该将其 PID 写入锁定目录中的文件中。

您可以使用文件中的PID来检查Java程序是否正在运行kill -0 $(cat /whatever/lockdir/PIDfile)- 如果进程不存在,kill将以非零状态退出。

诀窍是在命令行上将 PID 传递给 Java 程序:

exec java blah blah -mypid $$

您仍然必须非常小心围绕锁定目录创建、解释kill -0、 以及删除 PID 文件和锁定目录时出现的错误或异常,但使用任何其他方法都会遇到问题。

答案2

没有办法可靠且有效地检查不相关的进程是否正在运行:竞争条件始终是可能的。即使您找到一种方法来检测您感兴趣的进程是否正在运行,它也可能在您看到它后立即被杀死,或者相反,它可能在您错过它后立即启动。

如果您控制程序或其运行方式,则可以使其保留独特的资源,例如文件锁。但是,如果您控制程序的调用方式,则可以使用一种更简单的方法来跟踪它:从其父级监视它。当一个进程的子进程死亡时,它就会被通知。

确保进程始终运行的最简单方法是循环重新启动它。

# sleep 1 avoids a tight loop if the process systematically fails to start
while sleep 1; do
  nice …
  ret=$?
  if [ $ret -le 127 ]; then
    msg="… exited with status $ret"
  else
    msg="… exited on signal $((ret-128))"
  esac
  mail -s "$msg" "$USER"
done

有更强大、更强大的监控软件。看如何以自动化的方式对我的服务进行适当的监控?那么,如果发生崩溃,它会自动重新启动吗?

相关内容