Fabric: Скрипты инициализации часто не запускают своих демонов

Созданный на 19 авг. 2011  ·  19Комментарии  ·  Источник: fabric/fabric

Описание

Я получил несколько отчетов об этом в IRC, а также комментарий к № 350, а теперь и ветку списка рассылки .

Пока нет ясной причины, и хотя об этом сообщалось несколько раз, я не ожидаю, что это постоянная проблема, иначе мы услышим о ней гораздо больше. В некоторых очень ограниченных тестах с моей стороны я могу воссоздать проблему, может быть, в 30-50% случаев, но это воспроизводимо.

Симптом заключается в том, что сценарии в стиле инициализации, отвечающие за запуск демонов и затем немедленно возвращающие их, возвращают OK, код возврата 0 и сообщение о статусе успеха, выводимое на стандартный вывод, но фактически не запускают рассматриваемый демон.

Мой личный тест был проведен с помощью последнего мастера, нацеленного на виртуальную машину Ubuntu 10.04 (Lucid) и сценарий инициализации стандартного пакета Apache2.


Первоначально представленный Джефф Forcier ( bitprophet ) на 2011-07-23 в 07:25 вечера EDT

связи

  • Относится к # 350: фабрика вешает некоторую удаленную команду (для программы-демона)
Bug Docs Wart

Самый полезный комментарий

Только что столкнулся с этой проблемой.
У меня была ситуация, когда я не могу использовать tty = False, потому что я запускаю команду с помощью sudo.
Добавление >& /dev/null < /dev/null & выполняется хорошо, но процесс не был запущен.

Решил проблему с добавлением сна после строки выполнения команды: nohup java -jar text.jar & sleep 5; exit 0

Все 19 Комментарий

Джефф Форсьер (


Инструментировал сценарий инициализации, который я тестирую, и все, похоже, работает одинаково в любом случае (т.е. реальный успех или сценарии ложного успеха), подразумевая, что проблема заключается в вызове apachectl который делает сам сценарий.

Начинаем задумываться о том, в чем причина может быть с нашей стороны:

  • Поскольку это полуслучайно, это заставляет меня думать о прошлых проблемах с подсистемой ввода-вывода, страдающей от состояния гонки. Однако я не могу серьезно подумать о том, как это могло повлиять на что-то на удаленном конце таким образом, и все условия гонки в любом случае были локальными.

    • Один из способов проверить это может заключаться в том, чтобы увидеть, возникает ли эта проблема с Fab 0.9.x и pty = True (чтобы соответствовать текущему значению по умолчанию в 1.x).

  • Это также могло быть связано с pty - я не помню, чтобы это была проблема до 1.0, и установка pty на True была одним из основных изменений в поведении по умолчанию. Хотя, опять же, я не понимаю, почему использование SSH-подсистемы request-a-pty может привести к такому поведению сценариев инициализации.

    • Тестом здесь было бы использовать ssh -t <hostname> <command> и посмотреть, воспроизводит ли это также проблему.


23.07.2011 в 19:45 EDT

Джефф Форсьер (


apache2ctl сам по себе также является просто сценарием оболочки Bash, вызывающим /usr/sbin/apache2 , который является символической ссылкой на фактический двоичный исполняемый файл в месте установки Apache mpm-worker. В частности, при обычном использовании start он вызывает /usr/sbin/apache2 -k start . Как и раньше, apache2ctl , похоже, не ведет себя по-разному в двух разных сценариях: re: return value или какие разделы выполняются.

Документы /usr/sbin/apache2 относительно ограничены (даже на сайте Apache), в них указано только, что вы должны использовать apachectl для настройки env vars (что является точным - запуск apache2 сам по себе довольно неплохо очевидно, с ошибками о том, что эти вары не установлены.)

Изучение вывода env непосредственно перед вызовом apache2ctl apache2 дает только несколько элементов: пользователь, группа, расположение pid-файла и язык. Они не меняются между успешными и неудачными ситуациями. Я как бы надеялся, что в различных источниках и настройках env var в оболочках будет что-то, что иногда будет меняться, но нет.


Пока это никуда не годится. Пришло время проверить приведенные выше идеи (pty, ssh) и посмотреть, что там изменится.


23.07.2011 в 20:46 EDT

Джефф Форсьер (


С pty=False , похоже, он работает намного лучше (как следует из комментария Макса в # 350). При настройке по умолчанию True я наблюдал сбои примерно 5/10 раз, иногда больше или меньше. С False я только что запускал его около 15 раз подряд без сбоев. Не статистик, но мне это кажется неплохим.

Запуск ssh вручную дает аналогичные результаты: ssh -t <host> sudo /etc/init.d/apache2 start не запускает Apache примерно в 50% случаев. То же самое с -T (принудительно не использовать pty), и он запускается в 100% случаев.

Так что это не вина Fabric; это что-то более глубокое, где эти сценарии инициализации ведут себя неправильно, когда задействован псевдотерминал в стиле SSH.


Ради любопытства собираюсь копнуть немного глубже, но похоже, что «решение» - это новый FAQ, в котором говорится, что при обнаружении этой проблемы следует использовать pty=False .


23.07.2011 в 20:59 EDT

Джефф Форсьер (


Да, к сожалению, не удалось найти ничего, что объясняло бы такое поведение. Учитывая вышеизложенные выводы, я думаю, что ответы на часто задаваемые вопросы - это определенно лучший способ.


23.07.2011 в 22:35 EDT

Уго Гарза (hiro2k) написал:


Ухх, я только вчера столкнулся с этим, хотел бы я увидеть эту ошибку, к счастью, я попытался установить pty = False, и это тоже сработало. Спасибо за объяснение, по крайней мере, дело не в ткани. Теперь вы действительно заставили меня задуматься, почему это не удается.


2011-08-02 в 13:27 EDT

Вы уверены, что это проблема не только сценария bash? Я имею в виду с моей веткой списка рассылки. Это были просто сценарии bash, которые запускали java и weblogic.

FWIW, я получаю это ужасное поведение практически на каждой машине Ubuntu, которую я запускаю на EC2.

Это также воспроизводимо с задачами, запущенными через отдельный экран screen -d -m someBackgroundTask .

Я должен упомянуть, что обычно pty=False решает проблему, но я видел случаи, когда это было не так.

@yuvadm - в тех случаях, когда pty = False не решает проблему, можно ли воссоздать проблему с помощью обычной команды ssh (как указано выше)? Насколько я видел, это проблема SSH, а не проблема Fabric, но было бы хорошо знать, есть ли какие-либо ситуации, когда она не совпадает.

Это интересный ракурс для проверки, я вернусь к вам по этому поводу ...

Я воспроизвел эту проблему. Клиент - Ubuntu 10.04.3 LTS, сервер - «Ubuntu 8.04.4 LTS (сервер)».
Клиент SSH - «OpenSSH_5.3p1 Debian-3ubuntu7, OpenSSL 0.9.8k 25 марта 2009 г.», сервер ssh - «OpenSSH_4.7p1 Debian-8ubuntu1, OpenSSL 0.9.8g 19 октября 2007 г.». Ткань "1.3.3 финал".

Проблема в 100% при pty = True и исчезает при pty = False.

При подключении к другим серверам проблема не всегда возникает, когда pty = True.

В моем случае для тестирования я запускаю очень простую команду: «nohup sleep 100> / tmp / xxx 2> & 1

Меня это укусило, только на EC2, как кажется (на своем Linode не видел, но не уверен на 100%). Установка pty = False, кажется, исправляет это.

Только что столкнулся с этой проблемой.
У меня была ситуация, когда я не могу использовать tty = False, потому что я запускаю команду с помощью sudo.
Добавление >& /dev/null < /dev/null & выполняется хорошо, но процесс не был запущен.

Решил проблему с добавлением сна после строки выполнения команды: nohup java -jar text.jar & sleep 5; exit 0

Спасибо spodgruskiy,

Ваши советы мне подходят.
Я попытался написать fab tp start a strom cluster с помощью следующих команд.

  1. run ('nohup ./bin/storm nimbus> & / dev / null </ dev / null &', pty = False)
  2. run ('nohup ./bin/storm nimbus> & / dev / null </ dev / null &')
  3. run ("screen -d -m './bin/storm nimbus'", pty = False)
  4. запустить ("|| экран -d -m './bin/storm nimbus'")

Но ни один из них не работает, нимб вообще не запускался. Я не понимаю, что случилось.
В любом случае, спасибо.

+1 за уловку со сном

необходимо для работы в системах с requiretty

sudo ('start service; sleep .5') и все хорошо!

Если вы используете sudo () и в удаленной системе включен RequireTty для доступа sudo, вы можете использовать set -m; услугаstart ', чтобы предотвратить отправку SIGHUP процессу, запущенному сценарием инициализации.

См. Http://stackoverflow.com/a/14866774 для более подробного объяснения интерактивного и неинтерактивного bash и того, как это влияет на управление заданиями.

Мне любопытно, в чем проблема с ssh?

pty = false работает для меня

На самом деле это не проблема SSH, это скорее тонкое поведение в неинтерактивных / интерактивных режимах BASH и распространение сигнала на группы процессов.

Следующее основано на http://stackoverflow.com/questions/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t/14866774#14866774 и http: //www.itp.uzh.ch/~dpotter/howto/daemonize , с некоторыми предположениями, не полностью подтвержденными, но тесты того, как это работает, похоже, подтверждают.

pty / tty = ложь

Запущенная оболочка bash подключается к stdout / stderr / stdin запущенного процесса и продолжает работать до тех пор, пока к сокетам ничего не прикреплено и дочерние элементы не выйдут. Хороший процесс deamon гарантирует, что он не будет ждать выхода дочернего процесса, разветвляет дочерний процесс и затем завершает работу. В этом режиме SSH не отправляет SIGHUP дочернему процессу. Я считаю, что это будет работать правильно для большинства скриптов, выполняющих процесс, который обрабатывает саму деамонизацию и не требует поддержки. Если сценарии инициализации используют '&' для фонового выполнения процесса, то, вероятно, основная проблема будет заключаться в том, пытается ли фоновый процесс когда-либо читать из stdin, поскольку это вызовет SIGHUP, если сеанс был завершен.

pty / tty = истина *

Если сценарий инициализации запускает процесс, родительская оболочка BASH вернет код выхода в соединение SSH, которое, в свою очередь, будет немедленно завершать работу, поскольку не ожидает завершения дочернего процесса и не блокируется на stdout. / stderr / stdin. Это вызовет отправку SIGHUP родительской группе процессов оболочки bash, которая, поскольку управление заданиями отключено в неинтерактивном режиме в bash, будет включать только что запущенные дочерние процессы. Если процесс-демон явно запускает новый сеанс процесса при разветвлении или в разветвленном процессе, тогда он или его дочерние элементы не получат SIGHUP от выхода родительского процесса BASH. Обратите внимание, что это отличается от приостановленных заданий, для которых отображается сообщение SIGTERM.

Я подозреваю, что проблемы, связанные с этой работой, иногда связаны только с небольшим состоянием гонки. Если вы посмотрите на стандартный подход к деамонизации - http://www.itp.uzh.ch/~dpotter/howto/daemonize , вы увидите, что в коде новый сеанс создается разветвленным процессом, который может не быть запускается до выхода из родительского, что приводит к случайному успешному / неудачному поведению, упомянутому выше. Оператор сна дает разветвленному процессу достаточно времени для создания нового сеанса, поэтому в некоторых случаях он работает.

pty / tty = true и управление заданиями явно включено в bash

SSH не будет подключаться к stdout / stderr / stdin оболочки bash или любым запущенным дочерним процессам, что будет означать, что он завершится, как только родительская оболочка bash начнет выполнение запрошенных команд. В этом случае при явном включении управления заданиями любые процессы, запущенные оболочкой bash с '&' для фонового изображения, будут немедленно помещены в отдельный сеанс и не получат сигнал SIGHUP, когда родительский процесс для сеанса BASH завершится ( SSH-соединение в этом случае).

Что нужно исправить

Я думаю, что решения просто нужно явно упомянуть в документации по операциям run / sudo как особый случай при работе с фоновыми процессами / службами. В основном либо используйте pty = false, либо, если это невозможно, явно включите управление заданиями в качестве первой команды, и поведение будет правильным.

обновление ссылки: http://www.ics.uzh.ch/~dpotter/howto/daemonize

Как я уже упоминал здесь, fabrickit (оболочка библиотек ткани) https://github.com/HyukjinKwon/fabrickit/commit/cceb8bfb8f960a3ac41b24c64b8358bd6e7a0366

Вы можете абсолютно легко запустить программу как демон без особых настроек или настроек.
В любом случае это разновидность исполнения Shell, и поэтому должен быть способ сделать то, что умеет Shell.

Попробуй это:

run("sh -c '((nohup %s > /dev/null 2> /dev/null) & )'" % cmd, pty=False)

Я пробовал это, и он отлично работает, даже если он не реализует дополнительное программирование для запуска в качестве демона (даже просто программа, пишущая 'Hello' в цикле while, отлично работает).

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

peteruhnak picture peteruhnak  ·  4Комментарии

jmcgrath207 picture jmcgrath207  ·  5Комментарии

neemxyang picture neemxyang  ·  6Комментарии

acdha picture acdha  ·  4Комментарии

SamuelMarks picture SamuelMarks  ·  3Комментарии