你想编写一个做为一个在Unix或类Unix系统上面运行的守护进程运行的程序。python
建立一个正确的守护进程须要一个精确的系统调用序列以及对于细节的控制。 下面的代码展现了怎样定义一个守护进程,能够启动后很容易的中止它。bash
#!/usr/bin/env python3 # daemon.py import os import sys import atexit import signal def daemonize(pidfile, *, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): if os.path.exists(pidfile): raise RuntimeError('Already running') # First fork (detaches from parent) try: if os.fork() > 0: raise SystemExit(0) # Parent exit except OSError as e: raise RuntimeError('fork #1 failed.') os.chdir('/') os.umask(0) os.setsid() # Second fork (relinquish session leadership) try: if os.fork() > 0: raise SystemExit(0) except OSError as e: raise RuntimeError('fork #2 failed.') # Flush I/O buffers sys.stdout.flush() sys.stderr.flush() # Replace file descriptors for stdin, stdout, and stderr with open(stdin, 'rb', 0) as f: os.dup2(f.fileno(), sys.stdin.fileno()) with open(stdout, 'ab', 0) as f: os.dup2(f.fileno(), sys.stdout.fileno()) with open(stderr, 'ab', 0) as f: os.dup2(f.fileno(), sys.stderr.fileno()) # Write the PID file with open(pidfile,'w') as f: print(os.getpid(),file=f) # Arrange to have the PID file removed on exit/signal atexit.register(lambda: os.remove(pidfile)) # Signal handler for termination (required) def sigterm_handler(signo, frame): raise SystemExit(1) signal.signal(signal.SIGTERM, sigterm_handler) def main(): import time sys.stdout.write('Daemon started with pid {}\n'.format(os.getpid())) while True: sys.stdout.write('Daemon Alive! {}\n'.format(time.ctime())) time.sleep(10) if __name__ == '__main__': PIDFILE = '/tmp/daemon.pid' if len(sys.argv) != 2: print('Usage: {} [start|stop]'.format(sys.argv[0]), file=sys.stderr) raise SystemExit(1) if sys.argv[1] == 'start': try: daemonize(PIDFILE, stdout='/tmp/daemon.log', stderr='/tmp/dameon.log') except RuntimeError as e: print(e, file=sys.stderr) raise SystemExit(1) main() elif sys.argv[1] == 'stop': if os.path.exists(PIDFILE): with open(PIDFILE) as f: os.kill(int(f.read()), signal.SIGTERM) else: print('Not running', file=sys.stderr) raise SystemExit(1) else: print('Unknown command {!r}'.format(sys.argv[1]), file=sys.stderr) raise SystemExit(1)
要启动这个守护进程,用户须要使用以下的命令:session
bash % daemon.py start bash % cat /tmp/daemon.pid 2882 bash % tail -f /tmp/daemon.log Daemon started with pid 2882 Daemon Alive! Fri Oct 12 13:45:37 2012 Daemon Alive! Fri Oct 12 13:45:47 2012 ...
守护进程能够彻底在后台运行,所以这个命令会当即返回。 不过,你能够像上面那样查看与它相关的pid文件和日志。要中止这个守护进程,使用:ui
bash % daemon.py stop bash %