Я получил несколько отчетов об этом в IRC, а также комментарий к № 350, а теперь и ветку списка рассылки .
Пока нет ясной причины, и хотя об этом сообщалось несколько раз, я не ожидаю, что это постоянная проблема, иначе мы услышим о ней гораздо больше. В некоторых очень ограниченных тестах с моей стороны я могу воссоздать проблему, может быть, в 30-50% случаев, но это воспроизводимо.
Симптом заключается в том, что сценарии в стиле инициализации, отвечающие за запуск демонов и затем немедленно возвращающие их, возвращают OK, код возврата 0 и сообщение о статусе успеха, выводимое на стандартный вывод, но фактически не запускают рассматриваемый демон.
Мой личный тест был проведен с помощью последнего мастера, нацеленного на виртуальную машину Ubuntu 10.04 (Lucid) и сценарий инициализации стандартного пакета Apache2.
Первоначально представленный Джефф Forcier ( bitprophet ) на 2011-07-23 в 07:25 вечера EDT
Джефф Форсьер (
Инструментировал сценарий инициализации, который я тестирую, и все, похоже, работает одинаково в любом случае (т.е. реальный успех или сценарии ложного успеха), подразумевая, что проблема заключается в вызове apachectl
который делает сам сценарий.
Начинаем задумываться о том, в чем причина может быть с нашей стороны:
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 за уловку со сном
необходимо для работы в системах с requiretty
sudo ('start service; sleep .5') и все хорошо!
Если вы используете sudo () и в удаленной системе включен RequireTty для доступа sudo, вы можете использовать set -m; услуга
См. 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 , с некоторыми предположениями, не полностью подтвержденными, но тесты того, как это работает, похоже, подтверждают.
Запущенная оболочка bash подключается к stdout / stderr / stdin запущенного процесса и продолжает работать до тех пор, пока к сокетам ничего не прикреплено и дочерние элементы не выйдут. Хороший процесс deamon гарантирует, что он не будет ждать выхода дочернего процесса, разветвляет дочерний процесс и затем завершает работу. В этом режиме SSH не отправляет SIGHUP дочернему процессу. Я считаю, что это будет работать правильно для большинства скриптов, выполняющих процесс, который обрабатывает саму деамонизацию и не требует поддержки. Если сценарии инициализации используют '&' для фонового выполнения процесса, то, вероятно, основная проблема будет заключаться в том, пытается ли фоновый процесс когда-либо читать из stdin, поскольку это вызовет SIGHUP, если сеанс был завершен.
Если сценарий инициализации запускает процесс, родительская оболочка BASH вернет код выхода в соединение SSH, которое, в свою очередь, будет немедленно завершать работу, поскольку не ожидает завершения дочернего процесса и не блокируется на stdout. / stderr / stdin. Это вызовет отправку SIGHUP родительской группе процессов оболочки bash, которая, поскольку управление заданиями отключено в неинтерактивном режиме в bash, будет включать только что запущенные дочерние процессы. Если процесс-демон явно запускает новый сеанс процесса при разветвлении или в разветвленном процессе, тогда он или его дочерние элементы не получат SIGHUP от выхода родительского процесса BASH. Обратите внимание, что это отличается от приостановленных заданий, для которых отображается сообщение SIGTERM.
Я подозреваю, что проблемы, связанные с этой работой, иногда связаны только с небольшим состоянием гонки. Если вы посмотрите на стандартный подход к деамонизации - http://www.itp.uzh.ch/~dpotter/howto/daemonize , вы увидите, что в коде новый сеанс создается разветвленным процессом, который может не быть запускается до выхода из родительского, что приводит к случайному успешному / неудачному поведению, упомянутому выше. Оператор сна дает разветвленному процессу достаточно времени для создания нового сеанса, поэтому в некоторых случаях он работает.
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, отлично работает).
Самый полезный комментарий
Только что столкнулся с этой проблемой.
У меня была ситуация, когда я не могу использовать tty = False, потому что я запускаю команду с помощью sudo.
Добавление
>& /dev/null < /dev/null &
выполняется хорошо, но процесс не был запущен.Решил проблему с добавлением сна после строки выполнения команды:
nohup java -jar text.jar & sleep 5; exit 0