UFO ET IT

Linux 서비스 / 데몬으로서의 Python 스크립트

ufoet 2020. 11. 11. 21:00
반응형

Linux 서비스 / 데몬으로서의 Python 스크립트


어이,

(ubuntu) 리눅스에서 파이썬 스크립트를 서비스 (데몬)로 실행하려고합니다.

웹에는 다음과 같은 몇 가지 솔루션이 있습니다.

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

잘 작동하는 Unix 데몬 프로세스는 제대로 작동하기가 까다 롭지 만 필요한 단계는 모든 데몬 프로그램에서 거의 동일합니다. DaemonContext 인스턴스는 프로그램의 동작과 구성된 프로세스 환경을 보유합니다. 인스턴스를 컨텍스트 관리자로 사용하여 데몬 상태로 들어갑니다.

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

그러나 내 파이썬 스크립트를 우분투 리눅스와 특별히 통합하고 싶기 때문에 내 솔루션은 init.d 스크립트와의 조합입니다.

#!/bin/bash

WORK_DIR="/var/lib/foo"
DAEMON="/usr/bin/python"
ARGS="/opt/foo/linux_service.py"
PIDFILE="/var/run/foo.pid"
USER="foo"

case "$1" in
  start)
    echo "Starting server"
    mkdir -p "$WORK_DIR"
    /sbin/start-stop-daemon --start --pidfile $PIDFILE \
        --user $USER --group $USER \
        -b --make-pidfile \
        --chuid $USER \
        --exec $DAEMON $ARGS
    ;;
  stop)
    echo "Stopping server"
    /sbin/start-stop-daemon --stop --pidfile $PIDFILE --verbose
    ;;
  *)
    echo "Usage: /etc/init.d/$USER {start|stop}"
    exit 1
    ;;
esac

exit 0

그리고 파이썬에서 :

import signal
import time
import multiprocessing

stop_event = multiprocessing.Event()

def stop(signum, frame):
    stop_event.set()

signal.signal(signal.SIGTERM, stop)

if __name__ == '__main__':
    while not stop_event.is_set():
        time.sleep(3)

My question now is if this approach is correct. Do I have to handle any additional signals? Will it be a "well-behaved Unix daemon process"?


Assuming your daemon has some way of continually running (some event loop, twisted, whatever), you can try to use upstart.

Here's an example upstart config for a hypothetical Python service:

description "My service"
author  "Some Dude <blah@foo.com>"

start on runlevel [234]
stop on runlevel [0156]

chdir /some/dir
exec /some/dir/script.py
respawn

If you save this as script.conf to /etc/init you simple do a one-time

$ sudo initctl reload-configuration
$ sudo start script

You can stop it with stop script. What the above upstart conf says is to start this service on reboots and also restart it if it dies.

As for signal handling - your process should naturally respond to SIGTERM. By default this should be handled unless you've specifically installed your own signal handler.


Rloton's answer is good. Here is a light refinement, just because I spent a ton of time debugging. And I need to do a new answer so I can format properly.

A couple other points that took me forever to debug:

  1. When it fails, first check /var/log/upstart/.log
  2. If your script implements a daemon with python-daemon, you do NOT use the 'expect daemon' stanza. Having no 'expect' works. I don't know why. (If anyone knows why - please post!)
  3. Also, keep checking "initctl status script" to make sure you are up (start/running). (and do a reload when you update your conf file)

Here is my version:

description "My service"
author  "Some Dude <blah@foo.com>"

env PYTHON_HOME=/<pathtovirtualenv>
env PATH=$PYTHON_HOME:$PATH

start on runlevel [2345]
stop on runlevel [016]

chdir <directory>

# NO expect stanza if your script uses python-daemon
exec $PYTHON_HOME/bin/python script.py

# Only turn on respawn after you've debugged getting it to start and stop properly
respawn

참고URL : https://stackoverflow.com/questions/4705564/python-script-as-linux-service-daemon

반응형