brief introduction
Python daemon implements Unix daemons. Reference resources: PEP 3143
This library implements the good behavior daemons specification of PEP 3143 "standard daemons library".
The DaemonContext instance stores the behavior of the program and the configured process environment.
quick get start
import time 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)
Implementation:
$ 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
To stop the above process, you can find the process number through ps, and then kill.
Note that the above code has no problem in python2, but in Python, you need to modify the way the library file runner.py opens the file.
# 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)
More practical examples
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()
Implementation:
$ python2 daemon2.py usage: daemon2.py start|stop|restart $ python3 daemon2.py start andrew@andrew-MS-7A71:~/code/python-chinese-library/libraries/daemon$ andrew@andrew-MS-7A71:~/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 andrew@andrew-MS-7A71:~/code/python-chinese-library/libraries/daemon$ python3 daemon2.py stop Terminating on signal 15 andrew@andrew-MS-7A71:~/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
Note that the above error is caused by repeated start or stop when the process does not exist.
Reference material
- Discussion on qq group 144081101 591302926 567351477 nail free group 21745728
- Download related books of this article
- python test development library involved in this article Thanks a lot!
- Article code address
- Address of the latest version of this article
- daemonize demo cannot run
- https://pypi.python.org/pypi/python-daemon
A way of old style writing background process
import time import logging import logging.handlers 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)
In this way, it can't be executed in the background, but you can use the nohup and &. Add the following start and stop scripts for this purpose, which is not troublesome in fact:
For shell scripts, see: http://t.cn/R8scWAe
$ sh startup.sh ================================================================================================================ Starting older.py(PID=15315)...[Success] ================================================================================================================ $ sh startup.sh ================================================================================================================ older.py already started(PID=15315) ================================================================================================================ $ sh shutdown.sh ================================================================================================================ Stopping older.py(PID=15315)...[Success] ================================================================================================================ $ sh shutdown.sh ================================================================================================================ older.py is not running ================================================================================================================
Other
supervisord linux can control the linux process, of course, it can also be backstage.
How do you create a daemon in Python?
You can also register with Linux system D as a background process.