2011-12-31 2 views
25

Я недавно начал экспериментировать с использованием Python для веб-разработки. До сих пор я имел успех с помощью Apache с mod_wsgi и веб-картой Django для Python 2.7. Однако я столкнулся с некоторыми проблемами с постоянно работающими процессами, обновлением информации и т. Д.Как запустить длительные (бесконечные) процессы Python?

Я написал сценарий, который я называю «daemonManager.py», который может запускать и останавливать все или отдельные петли обновления python (Должен ли я назвать их демонами?). Он делает это путем разметки, затем загружает модуль для выполнения определенных функций и запускает бесконечный цикл. Он сохраняет файл PID в /var/run, чтобы отслеживать процесс. Все идет нормально. Проблемы, с которыми я столкнулся, это:

  • Время от времени один из процессов просто прекратится. Я проверяю ps утром, и процесс просто исчез. Ошибок не было зарегистрировано (я использую модуль logging), и я рассказываю обо всех исключениях, о которых я могу думать и регистрировать их. Также я не думаю, что эти процессы выхода имеют какое-то отношение к моему коду, потому что все мои процессы запускают совершенно другой код и выходят с довольно похожими интервалами. Конечно, я ошибаюсь. Нормально ли, что процессы Python просто умирают после того, как они работают в течение нескольких дней/недель? Как мне решить эту проблему? Должен ли я написать еще один демон, который периодически проверяет, продолжают ли другие демоны? Что делать, если этот демон останавливается? Я не понимаю, как справиться с этим.

  • Как я могу программно узнать, работает ли процесс еще или нет? Я сохраняю файлы PID в /var/run и проверяю, существует ли файл PID для определения того, выполняется ли процесс. Но если процесс просто умирает из-за неожиданных причин, PID-файл останется. Поэтому я должен удалять эти файлы каждый раз, когда процесс выходит из строя (пару раз в неделю), какой вид поражения цели. Наверное, я могу проверить, работает ли процесс в PID в файле, но что, если начался другой процесс и был назначен PID мертвого процесса? Мой демон подумал бы, что процесс работает нормально, даже если он давно мертв. Опять же я в недоумении, как с этим бороться.

Любой полезный ответ о том, как лучших процессов бесконечен Python Беги, мы надеемся, также пролить некоторый свет на вышеуказанные проблемы, я буду принимать


Я использую Apache 2.2.14 на машина Ubuntu.
My Python version is 2.7.2

+0

Если вы добавите некоторые примеры кода, показывающие код для демонов, которые терпят крах, мы сможем решить специфику. Прежде всего, сначала я удалю весь код из ваших сценариев, которые касаются форкирования, мониторинга, перенаправления и т. Д. –

+0

Можете ли вы прояснить, разыскиваете ли вы эти процессы демона из приложения WSGI, запущенного в mod_wsgi или отдельно. Вы не должны делать такое создание процесса из приложения, работающего под mod_wsgi. –

+0

Похоже, здесь много рекламы. Я имею в виду, это хорошо поставленный вопрос, на который дается ответ на конкретную технологию, на которую дается другой ответ, в котором он снова отвечает: «Я также использовал« еще одну (конкурентоспособную?) Технологию ... – citn

ответ

24

Я расскажу, что это one способ управления долговременным процессом (LRP) - не де-факто на любом участке.

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

Мой любимый решение http://supervisord.org/

Используя систему как supervisord, вы в основном написать обычный питон скрипт, который выполняет задачу, пока застрял в «бесконечном» цикле.

#!/usr/bin/python 

import sys 
import time 

def main_loop(): 
    while 1: 
     # do your stuff... 
     time.sleep(0.1) 

if __name__ == '__main__': 
    try: 
     main_loop() 
    except KeyboardInterrupt: 
     print >> sys.stderr, '\nExiting by user request.\n' 
     sys.exit(0) 

Написание сценария таким образом делает его простым и удобным для разработки и отладки (вы можете легко запустить/остановить его в терминале, наблюдая выход журнала, как разворачиваются события). Когда придет время для запуска в производство, вы просто определяете конфигурацию супервизора, которая вызывает ваш скрипт (вот полный пример для определения «программы», большая часть которого не является обязательной: http://supervisord.org/configuration.html#program-x-section-example).

Supervisor имеет кучу опций конфигурации, поэтому я не буду их перечислять, но я скажу, что это специально решает проблемы, вы описываете:

  • фоновый/
  • режим демона
  • PID отслеживания (может быть настроен на перезапуск процесса, если он неожиданно завершится)
  • Обычно регистрируйте свой сценарий (обработчик потока, если используете модуль протоколирования, а не печать), но пусть диспетчер перенаправляет на файл для вас.
+0

Я закончил тем, что сбросил свое собственное решение daemonize, так как оказалось, что у меня недостаточно опыта на эту тему. Я также закончил использование [forever by nodejitsu] (https://github.com/nodejitsu/forever), которое представляет собой приложение, не требующее дополнительных настроек (но тонны конфигурации), где вам просто нужно указать исполняемый файл и аргументы, и скрипт будет работать как демон навсегда, перезагружая при сбое. Я также решил некоторые длительные ошибки, проверив автоматические журналы вывода. Я принимаю ваш ответ как ближайший к моему решению. – Hubro

+0

Будет ли Supervisor перезапускать ваш скрипт после того, как вы выйдете из своего сценария вручную? –

+1

@Jakobud, когда супервизор управляет процессом, который выходит (через 'sys.exit()', неперехваченное исключение или если сценарий в противном случае достигает своего конца - может быть, не было цикла?), Он попытается перезапустить его. Существуют настройки для управления количеством попыток перезапуска и сколько времени ждать между попытками. Как только все попытки будут потрачены, он сдастся. Если вы хотите остановить выполняемую работу, вы должны использовать supervisorctl для ее закрытия. –

2

Предполагаете, вы используете Unix/Linux, но на самом деле не говорите. У меня нет прямых советов по вашей проблеме. Поэтому я не ожидаю, что буду «правильным» ответом на этот вопрос. Но здесь есть что изучать.

Во-первых, если ваши демоны рушится, вы должны это исправить. Только программы с ошибками должны быть повреждены. Возможно, вы должны запустить их под отладчиком и посмотреть, что произойдет, когда они сбой (если это возможно). У вас есть отслеживание трассировки в этих процессах? Если нет, добавьте их. Это может помочь диагностировать ваш крах.

Во-вторых, ваши демоны, предоставляющие услуги (открытие труб и ожидание запросов), или они выполняют периодическую очистку? Если они являются периодическими процессами очистки, вы должны использовать cron, чтобы запускать их периодически, а затем запускать их в бесконечном цикле. Процессы Cron должны быть предпочтительнее процессов демона. Точно так же, если они являются службами, открывающими порты и запросы на обслуживание, считаете ли вы, что они работают с INETD? Опять же, единственный демон (inetd) должен быть предпочтительнее пучка процессов демона.

В-третьих, сохранение PID в файле не очень эффективно, как вы обнаружили. Возможно, общий IPC, как семафор, будет работать лучше. Однако у меня нет никаких подробностей.

В-четвертых, иногда мне нужны вещи для запуска в контексте веб-сайта. Я использую процесс cron, который вызывает wget с URL-адресом обслуживания. Вы устанавливаете специальный файл cookie и включаете информацию о файлах cookie в командной строке wget. Если специальный файл cookie не существует, верните 403, а не выполните процесс обслуживания. Другим преимуществом здесь является логин в базе данных и другие экологические проблемы, которые можно избежать, поскольку код, обслуживающий обычные веб-страницы, служит для обслуживания.

Надеюсь, что дает вам идеи. Я думаю, что избегать демонов, если вы можете, это лучшее место для начала. Если вы можете запустить свой python в mod_wsgi, который сохранит вам поддержку нескольких «сред». Отладка процесса, который терпит неудачу после запуска в течение нескольких дней, является просто жестокой.

+1

Спасибо за хороший совет. Я указываю, что я запускаю Ubuntu кстати :) – Hubro

+0

О, в конце. Не видел. – jmucchiello

2

Вы должны учитывать процессы Python как способные запускать «навсегда» при условии, что у вас нет утечек памяти в вашей программе, интерпретаторе Python или любых используемых вами библиотеках/модулях Python. (Даже если вы сталкиваетесь с утечками памяти, вы можете работать вечно, если у вас есть достаточное пространство подкачки на 64-битной машине. Десятилетия, если не столетия, должны быть выполнимыми. У меня были процессы Python, два года на ограниченном оборудовании - до того, как аппаратное обеспечение необходимо было переместить.)

Обеспечение программ перезагрузки, когда они умирают раньше очень просто назад, когда дистрибутивы Linux используется SysV-style init - вы просто добавить новую строку в /etc/inittab и init(8) породит свою программу при загрузке и повторной икре его, если он умрет. (Я не знаю механизма для повторения этой функции с новым upstart - заменой, которую используют многие дистрибутивы в наши дни. Я не говорю, что это невозможно, я просто не знаю, как это сделать.)

Но даже механизм прошедших лет был не таким гибким, как хотелось бы некоторым. Пакет daemontools от DJB является одним из примеров средств контроля и контроля процесса, призванных удерживать демонов навсегда. В комплект поставки Linux-HA входит другой аналогичный инструмент, хотя он может обеспечить слишком много «лишних» функциональных возможностей, которые могут быть оправданы для этой задачи. monit - еще один вариант.

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