Первоначально я задавал этот вопрос в StackOverflow. Затем понял, что это, вероятно, лучшее место.
У меня есть настройка bluepill для мониторинга моих процессов delayed_job. (Приложение Ruby On Rails)
Использование Ubuntu 12.10.
Я запускаю и отслеживаю сам сервис bluepill, используя Ubuntu upstart
. Моя конфигурация выскочки ниже (/etc/init/bluepill.conf
).
description "Start up the bluepill service"
start on runlevel [2]
stop on runlevel [016]
expect daemon
exec sudo /home/deploy/.rvm/wrappers/<app_name>/bluepill load /home/deploy/websites/<app_name>/current/config/server/staging/delayed_job.bluepill
# Restart the process if it dies with a signal
# or exit code not given by the 'normal exit' stanza.
respawn
Я также пытался с expect fork
вместо expect daemon
. Я также попытался полностью удалить линию expect...
.
Когда машина загружается, bluepill запускается нормально.
$ ps aux | grep blue
root 1154 0.6 0.8 206416 17372 ? Sl 21:19 0:00 bluepilld: <app_name>
PID процесса bluepill здесь 1154. Но upstart
, похоже, отслеживает неправильный PID. Он отслеживает PID, который не существует.
$ initctl status bluepill
bluepill start/running, process 990
Я думаю, что это отслеживает PID процесса sudo
, который запустил процесс bluepill.
Это предотвращает возрождение процесса bluepill, если я принудительно убью bluepill с помощью kill -9
.
Более того, я думаю, что из-за неверного PID, который отслеживается, перезагрузка / завершение работы просто зависает, и мне приходится каждый раз выполнять полную перезагрузку машины.
В чем здесь может быть проблема?
ОБНОВЛЕНИЕ :
Проблема остается на сегодня (3 мая 2015 г.) в Ubuntu 14.04.2.
Проблема не в использовании sudo. Я больше не использую sudo. Моя обновленная конфигурация upstart:
description "Start up the bluepill service"
start on runlevel [2]
stop on runlevel [016]
# Restart the process if it dies with a signal
# or exit code not given by the 'normal exit' stanza.
respawn
# Give up if restart occurs 10 times in 90 seconds.
respawn limit 10 90
expect daemon
script
shared_path=/home/deploy/websites/some_app/shared
bluepill load $shared_path/config/delayed_job.bluepill
end script
Когда машина загружается, программа загружается нормально. Но выскочка все еще отслеживает неправильный PID, как описано выше.
Обходной путь, упомянутый в комментариях, может решить проблему зависания. Впрочем, я не пробовал.
Довольно поздно, но, надеюсь, это может помочь другим пользователям.
В upstart есть задокументированная ошибка, которая может привести к тому, что initctl отследит неправильный PID, если указать неверный раздел fork
в конфигурации upstart: https://bugs.launchpad.net/upstart/+bug / 406397
Что происходит, так это то, что upstart проверяет раздел fork
и определяет, сколько разветвленных процессов он должен проверить перед выбором «истинного» PID контролируемой программы. Если вы укажете expect fork
или expect daemon
, но ваша программа не разветвляется достаточное количество раз, start
зависнет. С другой стороны, если ваш процесс разветвляется слишком много раз, initctl
отследит неправильный PID. Теоретически, это должно быть задокументировано в этом разделе поваренной книги выскочки , но, как вы можете видеть в этой ситуации, есть PID, связанный с завершенным процессом, когда его не должно быть.
Последствия этого объясняются в комментариях к багтрекеру, но я здесь подведу итог: помимо initctl
неспособности остановить процесс демона и зависания в недокументированном / недопустимом состоянии <service> start/killed, process <pid>
, если процесс принадлежит этот PID останавливается (и обычно будет), а затем PID освобождается для повторного использования системой.
Если вы введете initctl stop <service>
или service <service> stop
, initctl
уничтожит этот PID в следующий раз, когда он появится. Это означает, что где-то в будущем, если вы не перезагрузите компьютер после совершения этой ошибки, следующий процесс, использующий этот PID, будет немедленно уничтожен initctl
, даже если это не будет демон. Это может быть что-то такое же простое, как cat
или такое же сложное, как ffmpeg
, и вам будет трудно понять, почему ваш программный пакет завис в середине какой-то рутинной операции.
Итак, проблема в том, что вы указали неправильную опцию expect
для количества вилок, которые фактически делает ваш демон-процесс. Они говорят, что есть переписывание выскочки, которое решает эту проблему, но по состоянию на выскочке 1.8 (последняя версия Ubuntu 13.04 / январь 2014) проблема все еще присутствует.
Поскольку вы использовали expect daemon
и столкнулись с этой проблемой, я рекомендую попробовать expect fork
.
Редактировать: вот Ubuntu BASH-совместимый скрипт (оригинал Уэйда Фитцпатрика , модифицированный для использования Ubuntu sleep
), который порождает процессы до тех пор, пока не будет исчерпано доступное адресное пространство идентификатора процесса, после чего он запускается обратно в 0 и работает до «застрял» PID. Затем процесс запускается в режиме PID initctl
, а затем initctl
его убивает и сбрасывает.
#!/bin/bash
# usage: sh /tmp/upstart_fix.sh <pid>
sleep 0.001 &
firstPID=$!
#first lets exhaust the space
while (( $! >= $firstPID ))
do
sleep 0.001 &
done
# [ will use testPID itself, we want to use the next pid
declare -i testPID
testPID=$(($1 - 1))
while (( $! < $testPID ))
do
sleep 0.001 &
done
# fork a background process then die so init reaps its pid
sleep 3 &
echo "Init will reap PID=$!"
kill -9 $
# EOF
Для приведенного примера:
$ initctl status bluepill
bluepill start/running, process 990
быстрое решение для меня:
# If upstart gets stuck for some job in stop/killed state
export PID=990
cd /usr/local/bin
wget https://raw.github.com/ion1/workaround-upstart-snafu/master/workaround-upstart-snafu
chmod +x workaround-upstart-snafu
./workaround-upstart-snafu $PID
источник: https://bugs.debian.org/cgi- bin / bugreport.cgi? bug = 582745 # 37
Надеюсь, это будет полезно. То, что происходит, объясняется в других ответах.
Если вы не выполняете задание Upstart на уровне пользователя или , используя раздел setuid - тогда ваша работа выполняется от имени пользователя root.
Поскольку Upstart уже запущен от имени пользователя root, зачем вам вообще использовать sudo в exec
строфе?
Используя sudo
или su
в строфе exec
вызвали те же проблемы для меня, как вы описываете здесь.
Обычно я испытываю пункт 1 ИЛИ 1 И 2:
Конечно, дополнительно необходимо, чтобы раздел expect
отражал правильное количество вилок.
YMMV, но для меня:
exec
с указанием правильного числа вилок обычно приводит к ситуации 1 выше. exec
) приводит к ситуации 1 И 2 выше.