如何使用python-daemon设置守护进程?

时间:2021-08-13 23:17:41

I'm new to daemons so apologies if this is a newbie question.

如果这是一个新手问题,我是守护进程的新手。

In several other answers (for example, this question) people suggested the python-daemon package was the way to go because it fully implements the PEP 3143 standard.

在其他几个答案中(例如,这个问题),人们建议使用python-daemon包,因为它完全实现了PEP 3143标准。

Unfortunately, python-daemon is a bit light on documentation (or more likely I am a bit light on knowledge / experience... ;) ), and I think I am probably missing something really basic. Here's what I'm doing:

不幸的是,python-daemon对文档有点了解(或者更有可能我对知识/经验有点轻视......;)),我想我可能遗漏了一些非常基本的东西。这就是我正在做的事情:

I have the following:

我有以下内容:

import daemon

logfile = open('daemon.log', 'w')

context = daemon.DaemonContext(stdout = logfile, stderr = logfile)

context.open()

with context:
    do_something_1()
    do_something_2()

Question: How do I set up a daemon with python-daemon, how can I start it and stop it?

问题:如何使用python-daemon设置守护进程,如何启动并停止它?


Side notes:

I'm basically taking a wild guess about how / whether the .open() method should be used here -- docs were not real clear on this point. Same thing seems to happen whether I include it or not.

我基本上猜测应该如何/在这里使用.open()方法 - 文档在这一点上并不是真正清楚。无论我是否包括它,似乎都会发生同样的事情。

So, now what do I do? When I try running this file, eg:

所以,现在我该怎么办?当我尝试运行此文件时,例如:

python startConsumerDaemons.py

it appears to run do_something_1(), but not the second. And, it appears to leave the program attached to the terminal window. IE, stdout isn't redirected, and when I close the terminal window the process is killed. So, I'm pretty sure I'm doing something wrong here... what should I be doing differently?

它似乎运行do_something_1(),但不是第二个。并且,它似乎将程序保留在终端窗口中。 IE,stdout没有重定向,当我关闭终端窗口时,进程被终止。所以,我很确定我在这里做错了什么......我应该做些什么呢?

And, lastly, once I get the daemon running, how do I stop / restart it (for example if I make changes to the underlying code)?

最后,一旦我让守护进程运行,我该如何停止/重启它(例如,如果我对底层代码进行了更改)?

6 个解决方案

#1


9  

Here is what I have, that works for me. It also has a sysv init script. Repo is at GitHub, and I also have a brief blog post with links to other possible solutions I found.

这就是我所拥有的,对我有用。它还有一个sysv init脚本。 Repo在GitHub上,我还有一篇简短的博客文章,其中包含我发现的其他可能解决方案的链接。

There can only be one daemon process running: that is managed by the PID lock file, like most other Linux daemons. To stop it, do

只能运行一个守护程序进程:它由PID锁定文件管理,就像大多数其他Linux守护程序一样。要阻止它,做

kill `cat /var/run/eg_daemon.pid`

To see if it is running:

要查看它是否正在运行:

ps -elf | grep `cat /var/run/eg_daemon.pid`

Using the pidfile submodule, the PID file is managed automatically. When the daemon is stopped, the pidfile is cleared up. Please see the linked GitHub repo for the init script.

使用pidfile子模块,自动管理PID文件。守护程序停止后,pidfile将被清除。请参阅链接的GitHub repo以获取init脚本。

Here's the Python daemon code:

这是Python守护程序代码:

#!/usr/bin/env python3.5
import sys
import os
import time
import argparse
import logging
import daemon
from daemon import pidfile

debug_p = False

def do_something(logf):
    ### This does the "work" of the daemon

    logger = logging.getLogger('eg_daemon')
    logger.setLevel(logging.INFO)

    fh = logging.FileHandler(logf)
    fh.setLevel(logging.INFO)

    formatstr = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    formatter = logging.Formatter(formatstr)

    fh.setFormatter(formatter)

    logger.addHandler(fh)

    while True:
        logger.debug("this is a DEBUG message")
        logger.info("this is an INFO message")
        logger.error("this is an ERROR message")
        time.sleep(5)


def start_daemon(pidf, logf):
    ### This launches the daemon in its context

    ### XXX pidfile is a context
    with daemon.DaemonContext(
        working_directory='/var/lib/eg_daemon',
        umask=0o002,
        pidfile=pidfile.TimeoutPIDLockFile(pidf),
        ) as context:
        do_something(logf)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Example daemon in Python")
    parser.add_argument('-p', '--pid-file', default='/var/run/eg_daemon.pid')
    parser.add_argument('-l', '--log-file', default='/var/log/eg_daemon.log')

    args = parser.parse_args()

    start_daemon(pidf=args.pid_file, logf=args.log_file)

For completeness' sake, here is the init script. Note that "kill" is really just a method for sending a POSIX signal -- see man page for signal(7) for an overview. The python-daemon context will catch the signal, terminate the process cleanly closing file descriptors, and delete the PID file automatically. So, it really is a clean termination.

为了完整起见,这里是init脚本。请注意,“kill”实际上只是发送POSIX信号的方法 - 有关概述,请参阅信号(7)的手册页。 python-daemon上下文将捕获信号,彻底终止进程关闭文件描述符,并自动删除PID文件。所以,这真的是一个干净的终止。

You can write your code to catch SIGUSR1 or something similar, in order to do a reload of the daemon config. There is no advantage to writing Python stop the daemon.

您可以编写代码以捕获SIGUSR1或类似的东西,以便重新加载守护程序配置。编写Python停止守护进程没有任何好处。

#!/bin/bash
#
# eg_daemon      Startup script for eg_daemon
#
# chkconfig: - 87 12
# description: eg_daemon is a dummy Python-based daemon
# config: /etc/eg_daemon/eg_daemon.conf
# config: /etc/sysconfig/eg_daemon
# pidfile: /var/run/eg_daemon.pid
#
### BEGIN INIT INFO
# Provides: eg_daemon
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Short-Description: start and stop eg_daemon server
# Description: eg_daemon is a dummy Python-based daemon
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/eg_daemon ]; then
        . /etc/sysconfig/eg_daemon
fi

eg_daemon=/var/lib/eg_daemon/eg_daemon.py
prog=eg_daemon
pidfile=${PIDFILE-/var/run/eg_daemon.pid}
logfile=${LOGFILE-/var/log/eg_daemon.log}
RETVAL=0

OPTIONS=""

start() {
        echo -n $"Starting $prog: "

        if [[ -f ${pidfile} ]] ; then
            pid=$( cat $pidfile  )
            isrunning=$( ps -elf | grep  $pid | grep $prog | grep -v grep )

            if [[ -n ${isrunning} ]] ; then
                echo $"$prog already running"
                return 0
            fi
        fi
        $eg_daemon -p $pidfile -l $logfile $OPTIONS
        RETVAL=$?
        [ $RETVAL = 0 ] && success || failure
        echo
        return $RETVAL
}

stop() {
    if [[ -f ${pidfile} ]] ; then
        pid=$( cat $pidfile )
        isrunning=$( ps -elf | grep $pid | grep $prog | grep -v grep | awk '{print $4}' )

        if [[ ${isrunning} -eq ${pid} ]] ; then
            echo -n $"Stopping $prog: "
            kill $pid
        else
            echo -n $"Stopping $prog: "
            success
        fi
        RETVAL=$?
    fi
    echo
    return $RETVAL
}

reload() {
    echo -n $"Reloading $prog: "
    echo
}

# See how we were called.
case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status -p $pidfile $eg_daemon
    RETVAL=$?
    ;;
  restart)
    stop
    start
    ;;
  force-reload|reload)
    reload
    ;;
  *)
    echo $"Usage: $prog {start|stop|restart|force-reload|reload|status}"
    RETVAL=2
esac

exit $RETVAL

#2


5  

A full example is available here.

这里有一个完整的例子。

You should be able to better understand the inner workings of python-daemon.

您应该能够更好地理解python-daemon的内部工作原理。

Moreover the code provided also gives an example of an init script to simply start/stop the daemon. However, you can start/stop it simply by calling the original function again with the argument stop:

此外,提供的代码还给出了一个简单启动/停止守护进程的init脚本示例。但是,您可以通过参数stop再次调用原始函数来启动/停止它:

python original_func.py stop

#3


2  

As you can see in the 'with' statement documentation, it statement does perform some 'magic', which is related to our purpose. Specifically:

正如您在'with'语句文档中所看到的,它声明确实执行了一些与我们的目的相关的“魔术”。特别:

The execution of the with statement with one “item” proceeds as follows:

带有一个“item”的with语句的执行过程如下:

  1. The context expression (the expression given in the with_item) is evaluated to obtain a context manager.

    评估上下文表达式(with_item中给出的表达式)以获取上下文管理器。

  2. The context manager’s __exit__() is loaded for later use.

    加载上下文管理器的__exit __()以供以后使用。

  3. he context manager’s __enter__() method is invoked.

    调用上下文管理器的__enter __()方法。

  4. If a target was included in the with statement, the return value from __enter__() is assigned to it.

    如果目标包含在with语句中,则会为__enter __()分配返回值。

  5. The suite is executed.

    该套件已执行。

  6. The context manager’s __exit__() method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to __exit__(). Otherwise, three None arguments are supplied.

    调用上下文管理器的__exit __()方法。如果异常导致退出套件,则其类型,值和回溯作为参数传递给__exit __()。否则,提供三个None参数。

What does this mean? If you look closely to the PEP in question, which serves as python-daemon documentation as well (and which indeed could be much improved), you'll see that it implements __enter__() and __exit__():

这是什么意思?如果仔细观察有问题的PEP,它也可以作为python-daemon文档(确实可以进行大量改进),你会发现它实现了__enter __()和__exit __():

The class also implements the context manager protocol via __enter__ and __exit__ methods.

该类还通过__enter__和__exit__方法实现上下文管理器协议。

__enter__()

Call the instance's open() method, then return the instance.

调用实例的open()方法,然后返回实例。

__exit__(exc_type, exc_value, exc_traceback)

__exit __(exc_type,exc_value,exc_traceback)

Call the instance's close() method, then return True if the exception was handled or False if it was not.

调用实例的close()方法,如果处理了异常则返回True,否则返回False。

In other words, open() is not needed, the example given in the PEP (though not explained correctly) works as is. While the with statement does mean something, it does not keep any loop, once the end of its scope is reached, it calls exit(), which in python-daemon means close(). Therefore, you need to put there a while True or which ever infinite loop you consider.

换句话说,不需要open(),PEP中给出的示例(尽管没有正确解释)按原样工作。虽然with语句确实意味着什么,但它不会保留任何循环,一旦达到其范围的末尾,它就会调用exit(),这在python-daemon中意味着close()。因此,您需要在那里放置一段时间的True或者您考虑的无限循环。

On behave of your second script not working, I can't really tell you, I'm surprised the first already works. If your daemon is stopping, there is a problem with your scripts for sure, you can check your consumerDaemonLogFile. (as a side note, you have a typo 'sderr' --> 'stderr')

如果你的第二个剧本不能正常工作,我真的不能告诉你,我很惊讶第一个已经有效。如果您的守护程序正在停止,那么您的脚本确实存在问题,您可以检查您的consumerDaemonLogFile。 (作为附注,你有一个错字'sderr' - >'stderr')

Also, you can see in the PEP that if not specified, the working directory property defaults to '/'. this might be the source of your problem if you are using relative paths in your scripts.

此外,您可以在PEP中看到,如果未指定,则工作目录属性默认为“/”。如果您在脚本中使用相对路径,这可能是您的问题的根源。

Finally, about the last question, you can easily kill you're daemon finding its PID:

最后,关于最后一个问题,你可以很容易地杀死你的守护进程找到它的PID:

ps ax | grep startConsumerDaemons.py

and sending it a SIGTERM:

并发送SIGTERM:

kill <pid>

The answer provided by gromain does provide a more handy way to start and stop it, with 'daemon.runner()', but it's far more complicated to setup.

gromain提供的答案确实提供了一种更方便的启动和停止方式,使用'daemon.runner()',但设置起来要复杂得多。

#4


0  

On linux, you can stop the Daemon by running:

在linux上,您可以通过运行以下命令来停止守护程序:

$ ps -x

and find the PID that corresponds to your daemon and then just kill the process.

找到与你的守护进程对应的PID然后杀死进程。

#5


0  

A useful documentation is still missing for the module "python-daemon". I personally gave up about using it, and now I successfully use Sander Marechal's daemon code referenced in this answer.

模块“python-daemon”仍然缺少有用的文档。我个人放弃了使用它,现在我成功地使用了Sander Marechal在这个答案中引用的守护进程代码。

I slightly modified it in order to be able to do things when you call python testdaemon.py stop.

我稍微修改了它,以便在调用python testdaemon.py stop时能够执行操作。

Here is the code.

这是代码。


Sample usage:

import sys, daemon, time

class testdaemon(daemon.Daemon):
    def run(self):
        self.i = 0
        with open('test1.txt', 'w') as f:
            f.write(str(self.i))
        while True:
            self.i += 1
            time.sleep(1)

    def quit(self):
        with open('test2.txt', 'w') as f:
            f.write(str(self.i))

daemon = testdaemon()

if 'start' == sys.argv[1]: 
    daemon.start()
elif 'stop' == sys.argv[1]: 
    daemon.stop()
elif 'restart' == sys.argv[1]: 
    daemon.restart()

#6


-1  

The daemon.DaemonContext constructor accepts a lockfile parameter. Use a lockfile library that will record the PID of the process, such as lockfile.PIDLockFile.

守护进程.DaemonContext构造函数接受lockfile参数。使用将记录进程PID的lockfile库,例如lockfile.PIDLockFile。

Then, the PID of the process is found simply by reading the content of the named PID file. Use that PID to send signals to your running daemon.

然后,仅通过读取指定的PID文件的内容就可以找到该过程的PID。使用该PID将信号发送到正在运行的守护程序。

#1


9  

Here is what I have, that works for me. It also has a sysv init script. Repo is at GitHub, and I also have a brief blog post with links to other possible solutions I found.

这就是我所拥有的,对我有用。它还有一个sysv init脚本。 Repo在GitHub上,我还有一篇简短的博客文章,其中包含我发现的其他可能解决方案的链接。

There can only be one daemon process running: that is managed by the PID lock file, like most other Linux daemons. To stop it, do

只能运行一个守护程序进程:它由PID锁定文件管理,就像大多数其他Linux守护程序一样。要阻止它,做

kill `cat /var/run/eg_daemon.pid`

To see if it is running:

要查看它是否正在运行:

ps -elf | grep `cat /var/run/eg_daemon.pid`

Using the pidfile submodule, the PID file is managed automatically. When the daemon is stopped, the pidfile is cleared up. Please see the linked GitHub repo for the init script.

使用pidfile子模块,自动管理PID文件。守护程序停止后,pidfile将被清除。请参阅链接的GitHub repo以获取init脚本。

Here's the Python daemon code:

这是Python守护程序代码:

#!/usr/bin/env python3.5
import sys
import os
import time
import argparse
import logging
import daemon
from daemon import pidfile

debug_p = False

def do_something(logf):
    ### This does the "work" of the daemon

    logger = logging.getLogger('eg_daemon')
    logger.setLevel(logging.INFO)

    fh = logging.FileHandler(logf)
    fh.setLevel(logging.INFO)

    formatstr = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    formatter = logging.Formatter(formatstr)

    fh.setFormatter(formatter)

    logger.addHandler(fh)

    while True:
        logger.debug("this is a DEBUG message")
        logger.info("this is an INFO message")
        logger.error("this is an ERROR message")
        time.sleep(5)


def start_daemon(pidf, logf):
    ### This launches the daemon in its context

    ### XXX pidfile is a context
    with daemon.DaemonContext(
        working_directory='/var/lib/eg_daemon',
        umask=0o002,
        pidfile=pidfile.TimeoutPIDLockFile(pidf),
        ) as context:
        do_something(logf)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Example daemon in Python")
    parser.add_argument('-p', '--pid-file', default='/var/run/eg_daemon.pid')
    parser.add_argument('-l', '--log-file', default='/var/log/eg_daemon.log')

    args = parser.parse_args()

    start_daemon(pidf=args.pid_file, logf=args.log_file)

For completeness' sake, here is the init script. Note that "kill" is really just a method for sending a POSIX signal -- see man page for signal(7) for an overview. The python-daemon context will catch the signal, terminate the process cleanly closing file descriptors, and delete the PID file automatically. So, it really is a clean termination.

为了完整起见,这里是init脚本。请注意,“kill”实际上只是发送POSIX信号的方法 - 有关概述,请参阅信号(7)的手册页。 python-daemon上下文将捕获信号,彻底终止进程关闭文件描述符,并自动删除PID文件。所以,这真的是一个干净的终止。

You can write your code to catch SIGUSR1 or something similar, in order to do a reload of the daemon config. There is no advantage to writing Python stop the daemon.

您可以编写代码以捕获SIGUSR1或类似的东西,以便重新加载守护程序配置。编写Python停止守护进程没有任何好处。

#!/bin/bash
#
# eg_daemon      Startup script for eg_daemon
#
# chkconfig: - 87 12
# description: eg_daemon is a dummy Python-based daemon
# config: /etc/eg_daemon/eg_daemon.conf
# config: /etc/sysconfig/eg_daemon
# pidfile: /var/run/eg_daemon.pid
#
### BEGIN INIT INFO
# Provides: eg_daemon
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Short-Description: start and stop eg_daemon server
# Description: eg_daemon is a dummy Python-based daemon
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/eg_daemon ]; then
        . /etc/sysconfig/eg_daemon
fi

eg_daemon=/var/lib/eg_daemon/eg_daemon.py
prog=eg_daemon
pidfile=${PIDFILE-/var/run/eg_daemon.pid}
logfile=${LOGFILE-/var/log/eg_daemon.log}
RETVAL=0

OPTIONS=""

start() {
        echo -n $"Starting $prog: "

        if [[ -f ${pidfile} ]] ; then
            pid=$( cat $pidfile  )
            isrunning=$( ps -elf | grep  $pid | grep $prog | grep -v grep )

            if [[ -n ${isrunning} ]] ; then
                echo $"$prog already running"
                return 0
            fi
        fi
        $eg_daemon -p $pidfile -l $logfile $OPTIONS
        RETVAL=$?
        [ $RETVAL = 0 ] && success || failure
        echo
        return $RETVAL
}

stop() {
    if [[ -f ${pidfile} ]] ; then
        pid=$( cat $pidfile )
        isrunning=$( ps -elf | grep $pid | grep $prog | grep -v grep | awk '{print $4}' )

        if [[ ${isrunning} -eq ${pid} ]] ; then
            echo -n $"Stopping $prog: "
            kill $pid
        else
            echo -n $"Stopping $prog: "
            success
        fi
        RETVAL=$?
    fi
    echo
    return $RETVAL
}

reload() {
    echo -n $"Reloading $prog: "
    echo
}

# See how we were called.
case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status -p $pidfile $eg_daemon
    RETVAL=$?
    ;;
  restart)
    stop
    start
    ;;
  force-reload|reload)
    reload
    ;;
  *)
    echo $"Usage: $prog {start|stop|restart|force-reload|reload|status}"
    RETVAL=2
esac

exit $RETVAL

#2


5  

A full example is available here.

这里有一个完整的例子。

You should be able to better understand the inner workings of python-daemon.

您应该能够更好地理解python-daemon的内部工作原理。

Moreover the code provided also gives an example of an init script to simply start/stop the daemon. However, you can start/stop it simply by calling the original function again with the argument stop:

此外,提供的代码还给出了一个简单启动/停止守护进程的init脚本示例。但是,您可以通过参数stop再次调用原始函数来启动/停止它:

python original_func.py stop

#3


2  

As you can see in the 'with' statement documentation, it statement does perform some 'magic', which is related to our purpose. Specifically:

正如您在'with'语句文档中所看到的,它声明确实执行了一些与我们的目的相关的“魔术”。特别:

The execution of the with statement with one “item” proceeds as follows:

带有一个“item”的with语句的执行过程如下:

  1. The context expression (the expression given in the with_item) is evaluated to obtain a context manager.

    评估上下文表达式(with_item中给出的表达式)以获取上下文管理器。

  2. The context manager’s __exit__() is loaded for later use.

    加载上下文管理器的__exit __()以供以后使用。

  3. he context manager’s __enter__() method is invoked.

    调用上下文管理器的__enter __()方法。

  4. If a target was included in the with statement, the return value from __enter__() is assigned to it.

    如果目标包含在with语句中,则会为__enter __()分配返回值。

  5. The suite is executed.

    该套件已执行。

  6. The context manager’s __exit__() method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to __exit__(). Otherwise, three None arguments are supplied.

    调用上下文管理器的__exit __()方法。如果异常导致退出套件,则其类型,值和回溯作为参数传递给__exit __()。否则,提供三个None参数。

What does this mean? If you look closely to the PEP in question, which serves as python-daemon documentation as well (and which indeed could be much improved), you'll see that it implements __enter__() and __exit__():

这是什么意思?如果仔细观察有问题的PEP,它也可以作为python-daemon文档(确实可以进行大量改进),你会发现它实现了__enter __()和__exit __():

The class also implements the context manager protocol via __enter__ and __exit__ methods.

该类还通过__enter__和__exit__方法实现上下文管理器协议。

__enter__()

Call the instance's open() method, then return the instance.

调用实例的open()方法,然后返回实例。

__exit__(exc_type, exc_value, exc_traceback)

__exit __(exc_type,exc_value,exc_traceback)

Call the instance's close() method, then return True if the exception was handled or False if it was not.

调用实例的close()方法,如果处理了异常则返回True,否则返回False。

In other words, open() is not needed, the example given in the PEP (though not explained correctly) works as is. While the with statement does mean something, it does not keep any loop, once the end of its scope is reached, it calls exit(), which in python-daemon means close(). Therefore, you need to put there a while True or which ever infinite loop you consider.

换句话说,不需要open(),PEP中给出的示例(尽管没有正确解释)按原样工作。虽然with语句确实意味着什么,但它不会保留任何循环,一旦达到其范围的末尾,它就会调用exit(),这在python-daemon中意味着close()。因此,您需要在那里放置一段时间的True或者您考虑的无限循环。

On behave of your second script not working, I can't really tell you, I'm surprised the first already works. If your daemon is stopping, there is a problem with your scripts for sure, you can check your consumerDaemonLogFile. (as a side note, you have a typo 'sderr' --> 'stderr')

如果你的第二个剧本不能正常工作,我真的不能告诉你,我很惊讶第一个已经有效。如果您的守护程序正在停止,那么您的脚本确实存在问题,您可以检查您的consumerDaemonLogFile。 (作为附注,你有一个错字'sderr' - >'stderr')

Also, you can see in the PEP that if not specified, the working directory property defaults to '/'. this might be the source of your problem if you are using relative paths in your scripts.

此外,您可以在PEP中看到,如果未指定,则工作目录属性默认为“/”。如果您在脚本中使用相对路径,这可能是您的问题的根源。

Finally, about the last question, you can easily kill you're daemon finding its PID:

最后,关于最后一个问题,你可以很容易地杀死你的守护进程找到它的PID:

ps ax | grep startConsumerDaemons.py

and sending it a SIGTERM:

并发送SIGTERM:

kill <pid>

The answer provided by gromain does provide a more handy way to start and stop it, with 'daemon.runner()', but it's far more complicated to setup.

gromain提供的答案确实提供了一种更方便的启动和停止方式,使用'daemon.runner()',但设置起来要复杂得多。

#4


0  

On linux, you can stop the Daemon by running:

在linux上,您可以通过运行以下命令来停止守护程序:

$ ps -x

and find the PID that corresponds to your daemon and then just kill the process.

找到与你的守护进程对应的PID然后杀死进程。

#5


0  

A useful documentation is still missing for the module "python-daemon". I personally gave up about using it, and now I successfully use Sander Marechal's daemon code referenced in this answer.

模块“python-daemon”仍然缺少有用的文档。我个人放弃了使用它,现在我成功地使用了Sander Marechal在这个答案中引用的守护进程代码。

I slightly modified it in order to be able to do things when you call python testdaemon.py stop.

我稍微修改了它,以便在调用python testdaemon.py stop时能够执行操作。

Here is the code.

这是代码。


Sample usage:

import sys, daemon, time

class testdaemon(daemon.Daemon):
    def run(self):
        self.i = 0
        with open('test1.txt', 'w') as f:
            f.write(str(self.i))
        while True:
            self.i += 1
            time.sleep(1)

    def quit(self):
        with open('test2.txt', 'w') as f:
            f.write(str(self.i))

daemon = testdaemon()

if 'start' == sys.argv[1]: 
    daemon.start()
elif 'stop' == sys.argv[1]: 
    daemon.stop()
elif 'restart' == sys.argv[1]: 
    daemon.restart()

#6


-1  

The daemon.DaemonContext constructor accepts a lockfile parameter. Use a lockfile library that will record the PID of the process, such as lockfile.PIDLockFile.

守护进程.DaemonContext构造函数接受lockfile参数。使用将记录进程PID的lockfile库,例如lockfile.PIDLockFile。

Then, the PID of the process is found simply by reading the content of the named PID file. Use that PID to send signals to your running daemon.

然后,仅通过读取指定的PID文件的内容就可以找到该过程的PID。使用该PID将信号发送到正在运行的守护程序。