Демон падает, но выскочка думает, что он все еще жив
У меня следующая проблема: у нас есть 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 ответа
Вот что обычно происходит с программами-демонами:
- Upstart запускает исполняемый файл на переднем плане
- Программа загружает файл конфигурации, проверяет его, выполняет различные операции настройки (например, открывает порт прослушивания).
- Если предыдущий шаг завершается неудачно, программа завершает работу, и выскочка получает ненулевой код завершения, таким образом, зная, что это не удалось
- Если шаг 2 не завершился неудачей, программа теперь разветвляется, создавая две его копии.
- Процесс, который изначально выполнял Upstart, теперь завершается с нулевым кодом завершения, что указывает на его успешность
- Разветвленный процесс продолжает работать и выполняет фактическую работу приложения
Проблема в том, что 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.
Посмотри пожалуйста:
- http://upstart.ubuntu.com/cookbook/ (внимательно прочитайте этот раздел)
- http://upstart.ubuntu.com/cookbook/