【发布时间】:2016-06-12 02:46:56
【问题描述】:
(我知道在 SO 上存在一些关于同一主题的问题,并且我已经阅读了热门答案。这些答案很好,但我仍有一些不清楚的地方。) 最近偶然发现了一段用于在 Unix 系统中创建守护进程的 Python:sample code 还有我想谈的那篇:
def daemonize(self):
"""
do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
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, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
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())
file(self.pidfile,'w+').write("%s\n" % pid)
所以流程是:
- 创建当前进程的分支并杀死父进程。所以在这种情况下,分叉的进程 1 现在是一个孤儿。
- 与父环境解耦--我们为什么要这样做?是不是说通过设置分叉进程1的sid,我们就可以隔离分叉进程了?此时fork出的进程1有了自己的进程组和会话(等于它的pid),这意味着它是一个会话领导者,这意味着它可以获取一个新的控制终端。
- 再次分叉并终止分叉进程 1。分叉进程 2 现在也是一个孤立进程。它绝对不是会话负责人(分叉进程 1 是)。并且它不与原始父进程环境共享任何内容。
- 进行输入/输出/错误重定向。
那么我对创建守护进程的过程的理解是否正确?还有人在SO question中提到“这可以防止僵尸进程”,为什么这段代码甚至与僵尸进程有关?父进程会被杀死,让进程被init监控,“守护进程”不就是这个意思吗?
有些人还提到,fork once 应该已经为我们提供了一个好的守护进程。这有什么例子吗?任何 fork once 可能不仅仅作为一个好的守护进程工作的示例(系统)?
【问题讨论】:
-
我确实在我的问题中提到了这个问题,并且我已经阅读了该问题下的前 3 个答案。他们是很好的答案,但我仍然有一些不清楚的地方,这已经包含在我的问题中
-
链接问题中的一些答案,也解释了双分叉,只有当父进程预计比子进程寿命更长时才需要(因此让子进程在父进程中成为僵尸表)。
标签: python linux unix daemon sys