Python脚本作为linux服务/守护进程

时间:2022-07-25 23:55:58

Hallo,

喂,

I'm trying to let a python script run as service (daemon) on (ubuntu) linux.

我试图让python脚本作为服务(守护程序)运行在(ubuntu) linux上。

On the web there exist several solutions like:

在网上有几种解决方案,如:

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

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

A well-behaved Unix daemon process is tricky to get right, but the required steps are much the same for every daemon program. A DaemonContext instance holds the behaviour and configured process environment for the program; use the instance as a context manager to enter a daemon state.

一个行为良好的Unix守护进程很难处理好,但是对于每个守护进程程序来说,所需的步骤都是一样的。DaemonContext实例保存程序的行为和配置的流程环境;使用实例作为上下文管理器来输入守护进程状态。

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

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

However as I want to integrate my python script specifically with ubuntu linux my solution is a combination with an init.d script

但是,当我想要将我的python脚本与ubuntu linux集成时,我的解决方案是与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

and in python:

在python中:

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"?

我现在的问题是,这种方法是否正确。我需要处理其他信号吗?它会是一个“行为良好的Unix守护进程”吗?

2 个解决方案

#1


84  

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

假设您的守护进程有某种持续运行的方法(某些事件循环、twisted或其他),您可以尝试使用upstart。

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

下面是一个假想的Python服务的暴发户配置示例:

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

如果您将其保存为脚本。从conf到/etc/init您只需执行一次

$ 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.

您可以使用stop脚本停止它。上面的新贵conf所说的是在reboot上启动这个服务,并在它死后重新启动它。

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.

至于信号处理——您的进程应该自然地对SIGTERM做出响应。默认情况下,除非您专门安装了自己的信号处理程序,否则应该处理这个问题。

#2


8  

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.

Rloton的回答是好的。这里有一个轻微的改进,因为我花了大量的时间调试。我需要一个新的答案,这样我就能正确地格式化。

A couple other points that took me forever to debug:

还有几点我花了很长时间来调试:

  1. When it fails, first check /var/log/upstart/.log
  2. 当失败时,首先检查/var/log/upstart/.log
  3. 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!)
  4. 如果您的脚本使用python-daemon实现了一个守护进程,那么就不使用“expect守护进程”一节。没有期待的作品。我不知道为什么。(如果有人知道为什么,请留言!)
  5. Also, keep checking "initctl status script" to make sure you are up (start/running). (and do a reload when you update your conf file)
  6. 另外,继续检查“initctl状态脚本”以确保您已经启动(启动/运行)。(更新conf文件时进行重载)

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

#1


84  

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

假设您的守护进程有某种持续运行的方法(某些事件循环、twisted或其他),您可以尝试使用upstart。

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

下面是一个假想的Python服务的暴发户配置示例:

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

如果您将其保存为脚本。从conf到/etc/init您只需执行一次

$ 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.

您可以使用stop脚本停止它。上面的新贵conf所说的是在reboot上启动这个服务,并在它死后重新启动它。

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.

至于信号处理——您的进程应该自然地对SIGTERM做出响应。默认情况下,除非您专门安装了自己的信号处理程序,否则应该处理这个问题。

#2


8  

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.

Rloton的回答是好的。这里有一个轻微的改进,因为我花了大量的时间调试。我需要一个新的答案,这样我就能正确地格式化。

A couple other points that took me forever to debug:

还有几点我花了很长时间来调试:

  1. When it fails, first check /var/log/upstart/.log
  2. 当失败时,首先检查/var/log/upstart/.log
  3. 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!)
  4. 如果您的脚本使用python-daemon实现了一个守护进程,那么就不使用“expect守护进程”一节。没有期待的作品。我不知道为什么。(如果有人知道为什么,请留言!)
  5. Also, keep checking "initctl status script" to make sure you are up (start/running). (and do a reload when you update your conf file)
  6. 另外,继续检查“initctl状态脚本”以确保您已经启动(启动/运行)。(更新conf文件时进行重载)

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