Почему стандартный вывод не сбрасывается при подключении к процессу, запущенному с помощью supervisord?

Я использую Supervisor (контроллер процессов, написанный на python) для запуска и управления моим веб-сервером и связанными службами. Иногда мне нужно войти в pdb (или действительно в ipdb) для отладки, когда сервер работает. У меня возникли проблемы с выполнением этого через Supervisor.

Supervisor позволяет запускать процессы и управлять ими с помощью демона supervisord, а также предлагает доступ через клиент с именем supervisorctl. Этот клиент позволяет вам подключиться к одному из процессов переднего плана, который был запущен с помощью команды «fg». Как это:

supervisor> fg webserver

Все данные журнала отправляются на терминал. Но я не получаю никакого текста от отладчика pdb. Он принимает мой ввод, поэтому стандартный ввод, похоже, работает.

В рамках моего расследования я смог подтвердить, что ни print, ни raw_input не отправляли текстовые сообщения; но в случае raw_input стандартный ввод действительно работает.

Я также смог подтвердить, что это работает:

sys.stdout.write('message')
sys.flush()

Я думал, что когда я выдал команду fg, это было бы так, как если бы я запустил процесс на переднем плане в стандартном терминале ... но похоже, что supervisorctl делает что-то большее. Обычная печать например не смывается. Любые идеи?

Как заставить pdb, стандартную печать и т. д. работать правильно при подключении к терминалу переднего плана с помощью команды fg в supervisorctl?

(Возможная полезная ссылка: http://supervisord.org/subprocess.html#nondaemonizing-of-subprocesses)


person Rocketman    schedule 16.03.2013    source источник
comment
Вот это: fflush('stdout'); Это должно помочь.   -  person Games Brainiac    schedule 17.03.2013


Ответы (2)


Оказывается, python по умолчанию буферизует свой выходной поток. В некоторых случаях (таких как этот) - это приводит к задержанию вывода.

Существуют такие идиомы:

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

чтобы принудительно обнулить буфер.

Но лучшей альтернативой, на мой взгляд, является запуск базового процесса Python в небуферизованном состоянии с использованием флага -u. В файле supervisord.conf это выглядит просто так:

command=python -u script.py

ссылка: http://docs.python.org/2/using/cmdline.html#envvar-PYTHONUNBUFFERED

Также обратите внимание, что это загрязняет ваш файл журнала, особенно если вы используете что-то вроде ipdb с раскраской ANSI. Но поскольку это среда разработки, вряд ли это имеет значение.

Если это проблема, другое решение — остановить отлаживаемый процесс в supervisorctl, а затем временно запустить процесс в другом терминале для отладки. Это сохранит файлы журналов в чистоте, если это необходимо.

person Rocketman    schedule 17.03.2013

Возможно, ваш веб-сервер перенаправляет свой собственный стандартный вывод (внутренне) в файл журнала (т. е. игнорирует перенаправление стандартного вывода супервизора), и это не позволяет супервизору контролировать, куда направляется его стандартный вывод.

Чтобы проверить, так ли это, вы можете tail -f просмотреть журнал и посмотреть, идет ли туда вывод, который вы ожидали увидеть в своем терминале.

Если это так, посмотрите, можете ли вы найти способ настроить свой веб-сервер, чтобы этого не делать, или, если ничего не помогает, попробуйте работать с двумя терминалами... (один для ввода, один для вывода)

person shx2    schedule 16.03.2013
comment
Мой веб-сервер не отправляет свои выходные данные в файл журнала. Он отправляет его на стандартный вывод. Другая странная вещь: когда я убиваю процесс, некоторые, но не все, застрявшие выходные данные в конце сбрасываются в файл журнала. Я начинаю думать, что супервизор может быть немного глючным... - person Rocketman; 17.03.2013
comment
Нет ... мой последний комментарий на самом деле не соответствует действительности ... это не вина руководителя ... см. мое опубликованное решение. - person Rocketman; 17.03.2013