Початкове відстеження неправильного PID процесу - не повторне породження


11

Я спочатку задав це питання на StackOverflow. Тоді зрозумів, що це, мабуть, краще місце.

У мене є програма проконтролювання моніторингу моїх процесів відстроченої роботи. (Додаток Ruby On Rails)

Використання Ubuntu 12.10.

Я запускаю та контролюю саму службу креслення за допомогою 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...лінію.

Коли машина завантажується, креслення починається чудово.

$ ps aux | grep blue
root      1154  0.6  0.8 206416 17372 ?        Sl   21:19   0:00 bluepilld: <app_name>

PID процесу креслення тут 1154. Але, upstartсхоже, слідкує за неправильним PID. Він відстежує PID, який не існує.

$ initctl status bluepill
bluepill start/running, process 990

Я думаю, це відстеження PID sudoпроцесу, який розпочав процес креслення.

Це запобігає відновленню процесу креслення, якщо я насильно вбиваю програму за допомогою kill -9.

Більше того, я думаю, через те, що відслідковується неправильний PID, перезавантаження / відключення просто зависає, і мені доводиться щоразу ретельно скидати машину.

Що тут може бути проблемою?

ОНОВЛЕННЯ :

Проблема залишається на сьогодні (3 травня 2015 року) на Ubuntu 14.04.2.

Проблема полягає не у використанні судо. Я вже не користуюся судо. Моя оновлена ​​конфігурація на початку:

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, як описано вище.

Вирішення проблеми, згадане в коментарях, може виправити неполадки. Я ще не пробував цього.


Ви спробували подивитися, що таке процес 990? ps aux | grep 990слід зробити це, але pstree 990може бути більш інформативним.
Олі

Жодного процесу з PID 990 не існує.
Анян

2
що стосується необхідності перезавантажуватися, щоб повернутися до хорошого стану - дивіться цей чудовий інструмент: github.com/ion1/workaround-upstart-snafu
andersonbd1

і ви можете прискорити цей інструмент за допомогою цієї команди: $ echo 3000 | sudo tee / proc / sys / kernel / pid_max
andersonbd1

Відповіді:


8

Досить пізно, але, сподіваємось, це може допомогти іншим користувачам.

Існує задокументована помилка в запуску, яка може призвести до того, що initctl відстежує неправильний PID, якщо вказати неправильну forkстрофу в конфігурації на початку: https://bugs.launchpad.net/upstart/+bug/406397

Що відбувається, це те, що на початку перевіряється 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 ( оригінал Wade Fitzpatrick, модифікований для використання Ubuntu sleep), який породжує процеси, поки не буде вичерпано наявний адресний простір ідентифікатора процесу, і в цей момент він починається з 0 і працює на шляху до "застряглого" ПІД. Потім процес, породжений на 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

Ця відповідь містить корисну та цікаву інформацію, проте мені незрозуміло, як ця відповідь відповідає на початкове запитання, як згадував @Anjan: "Я також спробував вилкою очікувати замість демона очікування. Я також спробував повністю видалити рядок очікування ... "
користувач12345

5

Для наведеного прикладу:

$ 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

Я сподіваюся, що це буде корисно. Що відбувається, пояснено в інших відповідях.


Гарний сценарій. Це може зайняти хвилину-дві. rebootІноді може бути кращим , а також фіксує це.
Пітер Ільфріх

0

Якщо ви не виконуєте завдання на рівні користувача Upstart або не використовуєте встановлену строфу - ваше завдання працює як root.

Оскільки Upstart вже працює як root, навіщо взагалі використовувати судо у вашій execстрофі?

Використання sudoабо suв execстрофі викликало ті самі проблеми, що ви описали тут.

Як правило, я зазнаю пункт 1 АБО 1 та 2:

  1. upstart слід за неправильним PID
  2. на початку висить, коли я намагаюся зупинити процес

Звичайно, додатково у вас повинна бути expectстрофа, яка відображає правильну кількість виделок.

YMMV, але для мене:

  • використання судо або су в execстрофі з вказаною правильною кількістю вилок, як правило, призводить до ситуації 1 вище.
  • неправильна кількість вилок, вказаних (у нас без sudo / su in exec), призводить до ситуації 1 І 2 вище.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.