Как запустить долгосрочные (бесконечные) процессы Python? - PullRequest
28 голосов
/ 31 декабря 2011

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

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

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

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

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


Я использую Apache 2.2.14 на компьютере с Ubuntu.
Моя версия Python 2.7.2

Ответы [ 3 ]

26 голосов
/ 31 декабря 2011

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

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

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

Используя такую ​​систему, как supervisord, вы, в основном, пишете обычный скрипт на python, который выполняет задачу, находясь в "бесконечном" цикле.

#!/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)

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

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

  • фоновый / * 1023 режим демона *
  • Отслеживание PID (можно настроить для перезапуска процесса в случае его неожиданного завершения)
  • Обычно входите в ваш скрипт (потоковый обработчик, если вы используете модуль регистрации вместо печати), но пусть supervisor перенаправляет вас в файл.
2 голосов
/ 31 декабря 2011

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

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

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

2 голосов
/ 31 декабря 2011

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

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

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

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

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

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

...