У меня следующая проблема: у нас есть приложение 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.
Вот что обычно происходит с программами-демонами:
Проблема в том, что 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.
Посмотри пожалуйста: