守护进程崩溃,但新贵认为它还活着

我不得不面对以下问题:我们有一个由bash脚本启动的Java应用程序。 这个应用程序应该作为守护进程运行,所以我们有一个暴发户的工作来启动它。

start on runlevel [2345] stop on runlevel [!2345] #tell upstart we will fork later, so it will mangage the pids. expect fork #If the daemon stoppes unexpectedly, restart it! respawn script #The framework will only work, if we start it from this directory. cd /usr/lib/app-dir nohup ./appStartScript.sh &> /dev/null & #send an upstart event, in case we will chain this job later emit app_running end script 

有时,应用程序停止工作。 没有一个.hprof文件,如果虚拟机崩溃,也不会创build一个hserr文件。 暴发户申报为运行,

 appDeamon start/running, process 1131 

但是PID没有在ps -aux中列出。 (另外,新贵不能停止appDeamon的进程。)

我想知道:a)为什么暴发户认识到应用程序崩溃? b)是否有可能强迫新手重新启动应用程序,即使具有给定PID的进程不再存在? (到目前为止,我们需要重新启动整个服务器。)

我们的系统是Ubuntu Linux 10.04.1 LTS。

这是守护程序通常发生的事情:

  1. Upstart在前台运行可执行文件
  2. 程序加载它的configuration文件,检查它,执行各种设置操作(如打开一个监听端口)。
  3. 如果上一步失败,程序退出,新贵得到一个非零的退出代码,从而知道失败
  4. 如果第2步没有失败,程序现在分叉,基本上创build它的两个副本
  5. Upstart最初执行的过程现在退出,退出代码为零,表示成功
  6. 分叉的进程继续运行,并执行应用程序的实际工作

问题是Java不提供fork的机制,所以这个经过testing的模式不能正确实现。 在执行Java守护进程时,您不得不立即为进程提供后台服务(即脚本中的&符号)。 新贵基本上开始了这个过程,然后立即忘了 – 这个过程没有办法指示Upstart是否成功启动。

解决这个问题的唯一方法就是开始这个​​过程,将其背景化,然后检查它是否仍在运行,以确定它是否成功。 当然了,是确定何时检查它是否仍在运行。 简单的解决scheme是这样的:

 #!/bin/sh java MyClass >/dev/null 2>&1 & PID=$! sleep 3 if kill -0 $PID; then exit 0 else exit 1 fi 

有更复杂的scheme来确定何时检查进程,如使程序closuresstdout和stderr,或者在完成启动例程时创buildPID文件,并在启动脚本中等待这些事件。

最简单的解决scheme是修改你的Upstart脚本,如下所示:

 script cd /usr/lib/app-dir nohup ./appStartScript.sh &> /dev/null & PID=$! sleep 3 if kill -0 $PID; then emit app_running exit 0 else exit 1 fi end script 

为什么你的应用程序需要由bash脚本启动? 新贵需要知道你的应用分叉多less次。 你已经告诉它它没有fork(因为你没有指定' expect '节),但是你已经分叉了(因为你已经在脚本部分指定了' & ',所以Upstart无法跟踪PID 。

请参见: