Pergunta

Eu tenho uma ferramenta que tenho escrito em python e, geralmente, deve ser executado como um daemon. Quais são as melhores práticas para embalar esta ferramenta para distribuição, particularmente como deveria arquivos de configurações e o daemon executável / script ser tratado?

De modo relacionado existem ferramentas comuns para configurar o daemon para executar na inicialização, conforme apropriado para a plataforma dada (ou seja, init scripts em linux, Serviços no Windows, launchd no OS X)?

Foi útil?

Solução

Para responder a uma parte da sua pergunta, não há ferramentas que eu conheço que vai fazer daemon configuração portably mesmo em sistemas Linux e muito menos Windows ou Mac OS X.

A maioria das distribuições Linux parece estar usando start-stop-daemon dentro de scripts de inicialização agora, mas você ainda vai ter diferença menor no layout do sistema de arquivos e grandes diferenças na embalagem. Usando autotools / configurar ou distutils / easy_install se seu projeto é tudo Python, irá percorrer um longo caminho para torná-lo mais fácil de pacotes build para as diferentes distribuições Linux / BSD.

Windows é um jogo totalmente diferente e vai exigir win32 Mark Hammond extensões e talvez extensões "noreferrer" WMI de Tim Golden.

Eu não sei launchd exceto que "nenhuma das anteriores" são relevantes.

Para obter dicas sobre daemonizing scripts Python, gostaria de olhar para aplicativos Python que são realmente fazê-lo no mundo real, por exemplo, dentro torcida.

Outras dicas

A melhor ferramenta que eu encontrei para ajudar com scripts init.d é "start-stop-daemon". Ele irá correr qualquer aplicação, monitor de executar arquivos / pid, criá-los quando necessário, fornecer maneiras de parar o daemon, ids conjunto processo de usuário / grupo, e pode até mesmo fundo o seu processo.

Por exemplo, este é um script que pode iniciar / parar um servidor 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

Você também pode ver, há um exemplo de como usá-lo com um virtualenv, que eu sempre recomendo.

Há muitos trechos sobre a oferta de internet para escrever um daemon em python puro (sem scripts bash)

http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python / parece limpo ...

Se você quiser escrever seu próprio,
o princípio é o mesmo que com a função de festa daemon.

Basicamente:

No início:

  • você garfo para outro processo
  • abrir um arquivo de log para redirecionar o seu stdout e stderr
  • Salve a algum lugar pid.

Na parada:

  • Você enviar SIGTERM para o processo com pid armazenado em seu pidfile.
  • Com signal.signal (signal.SIGTERM, sigtermhandler) você pode vincular uma parada procedimento para o sinal SIGTERM.

Eu não sei qualquer pacote amplamente utilizado fazer isso embora.

Verifique módulo daemon de Ben Finney. Ele começou a escrever uma PEP alvo python 3.X:

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

Mas uma implementação já está disponível aqui:

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

Nem uma bala de prata para o que você está pedindo, mas confira supervisord . Ele lida com todos os bits de diversão de processos de gestão. Eu usá-lo fortemente em um grande ambiente de produção. Além disso, ele é escrito em Python!

Não me lembro onde eu baixei ele ... mas este é o melhor roteiro daemonizing que eu encontrei. Ele funciona muito bem (no Mac e Linux.) (Salvá-lo como 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( ))

Em seu script, você poderia simplesmente:

from daemonize import daemonize
daemonize()

E você pode também especificar lugares para redirecionar o stdio, err, etc ...

sistemas em Linux, gerenciador de pacotes do sistema (Portage para o Gentoo, aptidão para o Ubuntu / Debian, yum para o Fedora, etc.) normalmente se encarrega de instalar o programa, incluindo colocar scripts de inicialização nos lugares certos. Se você quiser distribuir o seu programa para Linux, você pode querer olhar para a agregação-lo para o formato adequado para os gestores de pacotes diferentes distribuição.

Este conselho é obviamente irrelevante em sistemas que não têm gerenciadores de pacotes (Windows e Mac eu acho).

Este blog tornou claro para mim que na verdade existem duas maneiras comuns de ter a sua execução do programa Python como um deamon (eu não tinha percebido isso tão claramente a partir das respostas existentes):

Existem duas abordagens para escrever aplicações daemon como servidores em Python.

  • O primeiro é lidar com todas as tarefas de sarting e parar daemons em código Python em si . A maneira mais fácil de fazer isso é com o pacote python-daemon que pode, eventualmente, fazer o seu caminho na distribuição do Python.

de Poeljapon é um exemplo desta primeira abordagem, apesar de não usar o pacote python-daemon, mas links para um costume, mas script python muito limpo.

  • A outra abordagem é usar as ferramentas fornecido pelo sistema operacional . No caso de Debain, isso significa escrever um script de inicialização que faz uso do start-stop-daemon programa.

A resposta de Ali Afshar é um exemplo de script shell do 2º abordagem, usando o start-stop-daemon.

A entrada do blog que eu citei tem um exemplo de script shell, e alguns detalhes adicionais sobre coisas como iniciar o seu daemon na inicialização do sistema e reiniciar o daemon automaticamente quando parado por qualquer razão.

me corrigir se errado, mas acredito que a questão é como implementar o daemon. Defina o seu aplicativo para instalar via pip e, em seguida, fazer a entry_point um cli(daemon()). Em seguida, crie um script de inicialização que simplesmente corre $app_name &

"geralmente deve ser executado como um daemon?"

não - na superfície - fazer um monte de sentido. "Geralmente" não é sensato. É tanto um um daemon ou não. Você pode querer atualizar a sua pergunta.

Para exemplos de daemons, ler sobre daemons como o Apache do httpd ou qualquer servidor de banco de dados (eles são daemons) ou o daemon de correio smtpd.

Ou, talvez, ler sobre algo mais simples, como o daemon FTP, SSH daemon, Telnet daemon.

No Linux mundo, você vai ter o seu diretório de aplicativos de instalação, alguns diretório de trabalho, além dos diretórios de arquivos de configuração.

Nós usamos /opt/ourapp para a aplicação (é Python, mas não instalar em lib/site-packages do Python)

Nós usamos /var/ourapp para arquivos de trabalho e nossos arquivos de configuração.

Nós poderíamos usar /etc/ourapp para arquivos de configuração - seria consistente -. Mas nós não

Nós não - ainda - utilizar os scripts init.d para inicialização. Mas essa é a peça final, inicialização automática. Por agora, temos administradores de sistemas iniciar os daemons.

Isto é baseado, em parte, na http://www.pathname.com/fhs/ http://tldp.org/LDP/ Linux sistema de arquivos-Hierarquia / html / Linux sistema de arquivos-Hierarchy.html .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top