Рекомендации По Упаковке Демона Python

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

относительно существуют ли какие-либо общие инструменты для настройки демона для запуска при загрузке в соответствии с данной платформой (т. е. init скрипты на linux, сервисы на windows,launchd на ОС x)?

10 ответов


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

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

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

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

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


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

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

#! /bin/bash

case "" 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, который я всегда рекомендую.


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

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

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

по сути:

начало:

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

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

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

Я не знаю, какой широко используемый пакет делает это.


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

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

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

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


Я не могу вспомнить, где я его скачал... но это лучший сценарий daemonizing, что я нашел. Это прекрасно работает (на 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 и т. д...


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


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

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


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

существует два подхода к написанию приложений daemon, таких как серверы в Python.

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

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

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

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

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


исправьте меня, если неправильно, но я считаю, что вопрос в том, как развернуть демона. Установите приложение для установки через pip, а затем сделайте entry_point cli(daemon()). Затем создайте скрипт init, который просто запускает $app_name &


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

не -- на поверхности -- имеет большой смысл. "Вообще" - это неразумно. Это либо демон, либо нет. Возможно, вы захотите обновить свой вопрос.

для примеров демонов читайте на демонах, таких как 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.