0

这是我正在使用的守护程序类

它充当一个基类,我想从另一个控制器文件中生成 2 个单独的守护进程

class Daemon:

    """A generic daemon class.

    Usage: subclass the daemon class and override the run() method."""

    def __init__(self, pidfile,outfile='/tmp/daemon_out',errfile='/tmp/daemon_log'): 
        self.pidfile = pidfile
        self.outfile = outfile
        self.errfile = errfile

    def daemonize(self):

        """Deamonize class. UNIX double fork mechanism."""

        try: 
            pid = os.fork() 
            if pid > 0:
                # exit first parent
                sys.exit(0) 
        except OSError as err: 
            sys.stderr.write('fork #1 failed: {0}\n'.format(err))
            sys.exit(1)

        # decouple from parent environment
        os.chdir('/') 
        os.setsid() 
        os.umask(0) 

        # do second fork
        try: 
            pid = os.fork() 
            if pid > 0:

                # exit from second parent
                sys.exit(0) 
        except OSError as err: 
            sys.stderr.write('fork #2 failed: {0}\n'.format(err))
            sys.exit(1) 

        # redirect standard file descriptors
        sys.stdout.flush()
        sys.stderr.flush()
        si = open(os.devnull, 'r')
        so = open(self.outfile, 'a+')
        se = open(self.errfile, 'a+')

        os.dup2(si.fileno(), sys.stdin.fileno())
        os.dup2(so.fileno(), sys.stdout.fileno())
        os.dup2(se.fileno(), sys.stderr.fileno())

        # write pidfile
        atexit.register(self.delpid)

        pid = str(os.getpid())
        with open(self.pidfile,'w+') as f:
            f.write(pid + '\n')

    #method for removing the pidfile before stopping the program
    #remove the commented part if you want to delete the output & error file before stopping the program
    def delpid(self):
        os.remove(self.pidfile)
        #os.remove(self.outfile)
        #os.remove(self.errfile)

    def start(self):
        """Start the daemon."""

        # Check for a pidfile to see if the daemon already runs
        try:
            with open(self.pidfile,'r') as pf:

                pid = int(pf.read().strip())
        except IOError:
            pid = None

        if pid:
            message = "pidfile {0} already exist. " + \
                    "Daemon already running?\n"
            sys.stderr.write(message.format(self.pidfile))
            sys.exit(1)

        # Start the daemon
        self.daemonize()
        self.run()

    def stop(self):
        #Stop the daemon.

        # Get the pid from the pidfile
        try:
            with open(self.pidfile,'r') as pf:
                pid = int(pf.read().strip())
        except IOError:
            pid = None

        if not pid:
            message = "pidfile {0} does not exist. " + \
                    "Daemon not running?\n"
            sys.stderr.write(message.format(self.pidfile))
            return # not an error in a restart

        # Try killing the daemon process    
        try:
            while 1:
                os.kill(pid, signal.SIGTERM)
                time.sleep(0.1)
        except OSError as err:
            e = str(err.args)
            if e.find("No such process") > 0:
                if os.path.exists(self.pidfile):
                    os.remove(self.pidfile)
            else:
                print (str(err.args))
                sys.exit(1)

    def restart(self):
        """Restart the daemon."""
        self.stop()
        self.start()

    def run(self):
        """override this method when you subclass Daemon.

        It will be called after the process has been daemonized by 
        start() or restart()."""

这是我在不同文件中使用的代码

在这个文件中,我从单独的类扩展守护程序类并覆盖 run() 方法。

#! /usr/bin/python3.6
import sys, time, os, psutil, datetime
from daemon import Daemon

class net(Daemon):
    def run(self):
        while(True):
            print("net daemon : ",os.getpid())
            time.sleep(200)

class file(Daemon):
    def run(self):
        while(True):
            print("file daemon : ",os.getpid())
            time.sleep(200)



if __name__ == "__main__":
    net_daemon = net(pidfile='/tmp/net_pidFile',outfile='/tmp/network_out.log',errfile='/tmp/net_error.log')
    file_daemon = file(pidfile='/tmp/file_pidFile',outfile='/tmp/filesys_out.log',errfile='/tmp/file_error.log')

    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            net_daemon.start()
            file_daemon.start()
        elif 'stop' == sys.argv[1]:
            file_daemon.stop()
            net_daemon.stop()
        elif 'restart' == sys.argv[1]:
            file_daemon.restart()
            net_daemon.restart()
        else:
            print("Unknown command")
            sys.exit(2)
        sys.exit(0)
    else:
        print("usage: %s start|stop|restart" % sys.argv[0])
        sys.exit(2)

运行 start() 方法的第一个类当前正在运行,并且现在只有网络守护进程可以工作我如何让 2 个类生成 2 个单独的守护进程?

4

1 回答 1

0

这里真正的问题是你为你想要的任务选择了错误的代码。你在问“我如何使用这个电锯来敲钉子?” 在这种情况下,它甚至不是带有说明书的专业生产锯,它是你在某人的车库里找到的自制锯,由一个可能知道他在做什么但你实际上无法确定的人制造,因为你不知道他在做什么。

您抱怨的最接近的问题是daemonize

try: 
    pid = os.fork() 
    if pid > 0:
        # exit first parent
        sys.exit(0) 

第一次调用时,父进程退出。这意味着父进程永远不会启动第二个守护进程,或者做任何其他事情。

对于可以由单独的程序管理的自我守护程序,这正是您想要的。(是否所有细节都正确,我不知道,但基本思想绝对正确。)

对于产生守护进程的管理程序,这正是您想要的。这就是你想要写的。所以这是错误的工作工具。

但任务并没有太大的不同。如果您了解自己在做什么(并打开您的副本——Unix Network Programming没有人对这些东西了解得足够透彻,以至于无法将其从头顶上理解),您就可以将一个转换为另一个。这可能是一个有用的练习,即使对于任何实际应用程序,我只使用 PyPI 上经过良好测试、记录良好、维护良好的库之一。

如果您只是用 替换sys.exit(0)父进程中发生的调用(但不是中间子进程中发生的调用!)会发生return True什么?(好吧,您可能还想sys.exit(1)用 a 替换父级中的return False或引发某种异常。)然后daemonize不再守护您,而是生成一个守护程序并报告它是否成功。哪个是你想要的,对吧?

不能保证它做的一切都是正确的(我敢打赌它不会),但它确实解决了你所问的具体问题。

如果在那之后没有什么明显的问题,下一步可能是通读PEP 3143(它将 Stevens 书中的所有细节都翻译成 Python 术语并确保它们在 21 世纪是最新的linux 和 BSD)并提出要运行的测试清单,然后运行它们以查看您仍然遇到的不太明显的问题。

于 2018-03-22T16:17:25.207 回答