Назад | Перейти на главную страницу

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

У меня следующая проблема: у нас есть приложение 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. (Также выскочка не может остановить процесс с помощью остановить приложение.)

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

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

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

  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.

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