1. 程式人生 > >python-daemon: 實現python後臺程式的工具

python-daemon: 實現python後臺程式的工具

簡介

python-daemon實現Unix守護程序。 參考: 瞭解更多

該庫實現了PEP 3143“標準守護程序庫”的良好行為守護程序規範。

DaemonContext例項儲存程式的行為和配置的程序環境。

快速入門

 import time            #  資料學習交流群   QQ 519970686    #

with daemon.DaemonContext():
    f = open("/tmp/test.log",'w')
    while True:
        f.write('''
        Library to implement a well-behaved Unix daemon process.

This library implements the well-behaved daemon specification of PEP 3143, “Standard daemon process library”.

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.
''')
        f.write("{0}\n".format(time.ctime(time.time())))
        time.sleep(1)

執行:

 $ python3 daemon1.py 

$ tail -f /tmp/test.log 
This library implements the well-behaved daemon specification of PEP 3143, “Standard daemon process library”.

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.
Thu Feb  8 14:21:43 2018

$ ps afx | grep -i daemon1
 8646 pts/2    S+     0:00          |           \_ grep --color=auto -i daemon1
 8640 ?        S      0:00          \_ python3 daemon1.py
$ kill -9 8640

要想停止上述程序,可以通過ps查詢到程序號,然後kill。

注意上述程式碼在python2沒有任何問題,不過在python需要修改庫檔案runner.py開啟檔案的方式。

 # vi /usr/local/lib/python3.5/dist-packages/daemon/runner.py 
# 118 -120
        self.daemon_context = DaemonContext()
        self.daemon_context.stdin = open(app.stdin_path, 'wb+',buffering=0)
        self.daemon_context.stdout = open(app.stdout_path,  'wb+',buffering=0)
        self.daemon_context.stderr = open(
                app.stderr_path, 'wb+', buffering=0)

更實用的例子

 import time
import logging
import logging.handlers
from daemon import runner

class App():

    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path =  '/tmp/foo.pid'
        self.pidfile_timeout = 5

    def run(self):

        logs = logging.getLogger('MyLogger')
        logs.setLevel(logging.DEBUG)
        fh = logging.handlers.RotatingFileHandler(
            '/tmp/test.log',maxBytes=10000000,backupCount=5)
        fh.setLevel(logging.DEBUG)
        formatter = logging.Formatter(u'%(asctime)s [%(levelname)s] %(message)s')
        fh.setFormatter(formatter)
        logs.addHandler(fh)  

        while True:
            for i in range(10):
                logs.info("Beginning Scan {0}! \n".format(i))
            time.sleep(1)

app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()

執行:

 $ python2 daemon2.py 
usage: daemon2.py start|stop|restart

$ python3 daemon2.py  start
[email protected]:~/code/python-chinese-library/libraries/daemon$ 
[email protected]:~/code/python-chinese-library/libraries/daemon$ Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/lockfile/pidlockfile.py", line 77, in acquire
    write_pid_to_pidfile(self.path)
  File "/usr/local/lib/python3.5/dist-packages/lockfile/pidlockfile.py", line 161, in write_pid_to_pidfile
    pidfile_fd = os.open(pidfile_path, open_flags, open_mode)
FileExistsError: [Errno 17] File exists: '/tmp/foo.pid'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "daemon2.py", line 39, in <module>
    daemon_runner.do_action()
  File "/usr/local/lib/python3.5/dist-packages/daemon/runner.py", line 274, in do_action
    func(self)
  File "/usr/local/lib/python3.5/dist-packages/daemon/runner.py", line 182, in _start
    self.daemon_context.open()
  File "/usr/local/lib/python3.5/dist-packages/daemon/daemon.py", line 389, in open
    self.pidfile.__enter__()
  File "/usr/local/lib/python3.5/dist-packages/lockfile/__init__.py", line 197, in __enter__
    self.acquire()
  File "/usr/local/lib/python3.5/dist-packages/daemon/pidfile.py", line 60, in acquire
    super(TimeoutPIDLockFile, self).acquire(timeout, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/lockfile/pidlockfile.py", line 85, in acquire
    self.path)
lockfile.LockTimeout: Timeout waiting to acquire lock for /tmp/foo.pid

[email protected]:~/code/python-chinese-library/libraries/daemon$ python3 daemon2.py  stop
Terminating on signal 15
[email protected]:~/code/python-chinese-library/libraries/daemon$ python3 daemon2.py  stop
Traceback (most recent call last):
  File "daemon2.py", line 39, in <module>
    daemon_runner.do_action()
  File "/usr/local/lib/python3.5/dist-packages/daemon/runner.py", line 274, in do_action
    func(self)
  File "/usr/local/lib/python3.5/dist-packages/daemon/runner.py", line 224, in _stop
    raise error
daemon.runner.DaemonRunnerStopFailureError: PID file '/tmp/foo.pid' not locked

注意上面的錯誤是重複啟動或者停止時程序並不存在導致的。