Демон падает, но выскочка думает, что он все еще жив

У меня следующая проблема: у нас есть Java-приложение, которое запускается скриптом bash. Это приложение должно запускаться как демон, поэтому у нас есть задание для его запуска.

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, ни файла hserr, который обычно создается в случае сбоя виртуальной машины. Upstart сообщает о том, что приложение работает,

appDeamon start/running, process 1131

Но PID не указан в ps -aux. (Кроме того, программа upstart не может остановить процесс с помощью команды appDeamon.)

Я хотел бы знать: а) Почему выскочка не распознает, что приложение упало? б) Есть ли возможность принудительно перезапустить приложение, чтобы перезапустить приложение, даже если процесс с данным pid больше не присутствует? (До сих пор нам нужно перезапустить весь сервер.)

Наша система - Ubuntu Linux 10.04.1 LTS.

2 ответа

Вот что обычно происходит с программами-демонами:

  1. Upstart запускает исполняемый файл на переднем плане
  2. Программа загружает файл конфигурации, проверяет его, выполняет различные операции настройки (например, открывает порт прослушивания).
  3. Если предыдущий шаг завершается неудачно, программа завершает работу, и выскочка получает ненулевой код завершения, таким образом, зная, что это не удалось
  4. Если шаг 2 не завершился неудачей, программа теперь разветвляется, создавая две его копии.
  5. Процесс, который изначально выполнял Upstart, теперь завершается с нулевым кодом завершения, что указывает на его успешность
  6. Разветвленный процесс продолжает работать и выполняет фактическую работу приложения

Проблема в том, что Java не предоставляет механизм для разветвления, и поэтому этот проверенный и протестированный шаблон не может быть реализован должным образом. При выполнении Java-демонов вы вынуждены немедленно выполнить фоновый процесс (т.е. & символ в сценарии). Upstart, по сути, запускает процесс, а затем сразу же забывает об этом - процесс не может указать Upstart, успешно ли он запущен или нет.

Единственный способ обойти это - запустить процесс, установить его в фоновом режиме, а затем проверить, работает ли он все еще, чтобы определить, был ли он успешным или нет. Уловка, конечно, определяет, когда проверить, работает ли он по-прежнему. Простое решение примерно так:

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

Существуют более сложные схемы, позволяющие определить, когда проверять процесс, например, заставить программу закрыть stdout и stderr или создать свой PID-файл после завершения процедуры запуска, и ожидать этих событий в сценарии запуска.

Самое простое решение для вас - изменить скрипт 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 скрипт? Upstart должен знать, сколько раз ваше приложение разветвляется. Вы сказали, что он не разветвляется (поскольку вы не указали expect ' stanza), и все же вы разветвились (потому что вы указали' & 'в разделе сценария. Поэтому Upstart не может отследить PID.

Посмотри пожалуйста:

Другие вопросы по тегам