Лучшие практики упаковки Python Daemon

У меня есть инструмент, который я написал на Python и обычно должен запускаться как демон. Каковы наилучшие методы упаковки этого инструмента для распространения, в частности, как следует обрабатывать файлы настроек и исполняемый файл / скрипт демона?

Соответственно, существуют ли какие-либо общие инструменты для настройки демона для запуска при загрузке в соответствии с данной платформой (например, сценарии инициализации в Linux, службы в Windows, запуск в OS X)?

Ответов (10)

Решение

Чтобы ответить на одну часть вашего вопроса, я не знаю никаких инструментов, которые могли бы переносить установку демона даже в системах Linux, не говоря уже о Windows или Mac OS X.

Кажется, что большинство дистрибутивов Linux сейчас используются start-stop-daemon в сценариях инициализации, но вы все равно будете иметь небольшие различия в макете файловой системы и большие различия в упаковке. Использование autotools / configure или distutils / easy_install, если ваш проект полностью основан на Python, значительно упростит сборку пакетов для различных дистрибутивов Linux / BSD.

Windows - это совершенно другая игра, и для нее потребуются расширения Win32 Марка Хаммонда и, возможно , расширения WMI Тима Голдена .

Я не знаю Launchd, за исключением того, что «ничего из вышеперечисленного» не имеет значения.

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

Не серебряная пуля за то, о чем вы просите, но проверьте супервайзера . Он обрабатывает все забавные моменты управления процессами. Я активно использую его в большой производственной среде. Кроме того, он написан на Python!

поправьте меня, если ошибаюсь, но я считаю, что вопрос в том, как РАЗВЕРТАТЬ демон. Настройте приложение для установки через pip, а затем сделайте entry_point a cli(daemon()) . Затем создайте сценарий инициализации, который просто запускает $app_name &

Эта запись в блоге прояснила для меня, что на самом деле есть два распространенных способа запустить вашу программу Python в качестве демона (я не понял этого так ясно из существующих ответов):

Есть два подхода к написанию приложений-демонов, таких как серверы, на Python.

  • Первый - выполнять все задачи по запуску и остановке демонов в самом коде Python . Самый простой способ сделать это - использовать python-daemonпакет, который в конечном итоге может попасть в дистрибутив Python.

Ответ Poeljapon является примером этого 1-го подхода, хотя он не использует python-daemon пакет, а ссылается на собственный, но очень чистый скрипт python.

  • Другой подход - использовать инструменты, предоставляемые операционной системой . В случае Debain это означает написание сценария инициализации, использующего start-stop-daemon программу.

Ответ Али Афшара - это пример сценария оболочки второго подхода с использованием start-stop-daemon .

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

"вообще должен запускаться как демон?"

Не имеет - на первый взгляд - большого смысла. «Вообще» не имеет смысла. Либо демон, либо нет. Возможно, вы захотите обновить свой вопрос.

Примеры демонов можно найти в таких демонах, как httpd Apache, или о любом сервере базы данных (они же демоны), или о почтовом демоне SMTPD.

Или, возможно, почитайте что-нибудь попроще, например, демон FTP, демон SSH, демон Telnet.

В мире Linux у вас будет каталог установки вашего приложения, некоторый рабочий каталог, а также каталоги файлов конфигурации.

Мы используем /opt/ourapp для приложения (это Python, но мы не устанавливаем в Python lib/site-packages )

Мы используем /var/ourapp для работы файлы и наши файлы конфигурации.

Мы могли бы использовать /etc/ourapp файлы конфигурации - это было бы согласованно - но мы этого не делаем.

Мы пока не используем init.d скрипты для запуска. Но это последняя часть, автоматический запуск. На данный момент у нас есть системные администраторы, запускающие демонов.

Частично это основано на http://www.pathname.com/fhs/ и http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/Linux-Filesystem-Hierarchy.html .

Лучший инструмент, который я нашел для помощи со сценариями init.d, - это "start-stop-daemon". Он будет запускать любое приложение, отслеживать файлы run / pid, создавать их при необходимости, обеспечивать способы остановки демона, устанавливать идентификаторы пользователей / групп процессов и даже может фонить ваш процесс.

Например, это скрипт, который может запускать / останавливать сервер wsgi:

#! /bin/bash

case "$1" in
  start)
    echo "Starting server"

    # Activate the virtual environment
    . /home/ali/wer-gcms/g-env/bin/activate

    # Run start-stop-daemon, the $DAEMON variable contains the path to the
    # application to run
    start-stop-daemon --start --pidfile $WSGI_PIDFILE \
        --user www-data --group www-data \
        --chuid www-data \
        --exec "$DAEMON"
    ;;
  stop)
    echo "Stopping WSGI Application"

    # Start-stop daemon can also stop the application by sending sig 15
    # (configurable) to the process id contained in the run/pid file
    start-stop-daemon --stop --pidfile $WSGI_PIDFILE --verbose
    ;;
  *)
    # Refuse to do other stuff
    echo "Usage: /etc/init.d/wsgi-application.sh {start|stop}"
    exit 1
    ;;
esac

exit 0

Вы также можете увидеть там пример того, как использовать его с virtualenv, который я всегда рекомендую.

В системах Linux системный менеджер пакетов (Portage для Gentoo, Aptitude для Ubuntu / Debian, yum для Fedora и т. Д.) Обычно заботится об установке программы, включая размещение сценариев инициализации в нужных местах. Если вы хотите распространять свою программу для Linux, вы можете подумать о том, чтобы связать ее в надлежащем формате для менеджеров пакетов различных дистрибутивов.

Этот совет, очевидно, не имеет отношения к системам, в которых нет менеджеров пакетов (я думаю, Windows и Mac).

В Интернете есть множество фрагментов, предлагающих написать демона на чистом питоне (без сценариев bash)

http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/ выглядит чистым ...

Если вы хотите написать свой собственный,
принцип тот же, что и с функцией демона bash.

По сути:

В начале:

  • вы переходите к другому процессу
  • откройте файл журнала, чтобы перенаправить ваш stdout и stderr
  • Сохраните pid где-нибудь.

На остановке:

  • Вы отправляете SIGTERM процессу с pid, хранящимся в вашем pidfile.
  • С помощью signal.signal (signal.SIGTERM, sigtermhandler) вы можете привязать процедуру остановки к сигналу SIGTERM.

Однако я не знаю ни одного широко используемого пакета, делающего это.

Я не помню, где я его скачал ... но это лучший демонизирующий скрипт, который я нашел. Он прекрасно работает (на Mac и Linux) (сохраните его как daemonize.py)

import sys, os
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
    # Perform first fork.
    try:
        pid = os.fork( )
        if pid > 0:
            sys.exit(0) # Exit first parent.
    except OSError, e:
        sys.stderr.write("fork #1 failed: (%d) %sn" % (e.errno, e.strerror))
        sys.exit(1)
    # Decouple from parent environment.
    os.chdir("/")
    os.umask(0)
    os.setsid( )
    # Perform second fork.
    try:
        pid = os.fork( )
        if pid > 0:
            sys.exit(0) # Exit second parent.
    except OSError, e:
        sys.stderr.write("fork #2 failed: (%d) %sn" % (e.errno, e.strerror))
        sys.exit(1)
    # The process is now daemonized, redirect standard file descriptors.
    for f in sys.stdout, sys.stderr: f.flush( )
    si = file(stdin, 'r')
    so = file(stdout, 'a+')
    se = file(stderr, 'a+', 0)
    os.dup2(si.fileno( ), sys.stdin.fileno( ))
    os.dup2(so.fileno( ), sys.stdout.fileno( ))
    os.dup2(se.fileno( ), sys.stderr.fileno( ))

В своем сценарии вы просто:

from daemonize import daemonize
daemonize()

И вы также можете указать места для перенаправления stdio, err и т. Д.

Проверьте модуль демона Бена Финни. Он начал писать PEP, ориентированный на python 3.X:

http://www.python.org/dev/peps/pep-3143/

Но реализация уже доступна здесь:

http://pypi.python.org/pypi/python-daemon/