使进程与终端分离的步骤是什么?为此我找到了手册页daemon()
在描述中,他们提到
如果 nochdir 为零,则 daemon() 将进程的当前工作目录更改为根目录(“/”);否则,当前工作目录保持不变。
如果 noclose 为零,则 daemon() 将标准输入、标准输出和标准错误重定向到 /dev/null;否则,不会对这些文件描述符进行任何更改。
实际上,我试图让我的 python 代码作为守护进程运行。我找到了tcollector
代码这里。在该代码中,他们也遵循与 的描述中相同的步骤daemon()
。所以我的问题是,我们为什么要执行这些步骤(wrtdaemonize()
在tcollector
)像
为什么更改dir
为/
、umask
to022
然后调用os.setsid()
等等。
答案1
实际上比您引用的内容更多,但我认为手册页可能更清晰。
如果 nochdir 为零,
daemon()
则将进程的当前工作目录更改为根目录 (/
)
这里的假设是该程序是从管理员命令行启动的,其想法是将守护进程与管理员当时正在执行的操作分离。更改工作目录以/
防止守护程序使安装点保持繁忙。例如,如果工作目录是/home/admin
,一段时间后您想卸载/home
,守护进程会阻止这种情况。
如果 noclose 为零,
daemon()
则将标准输入、标准输出和标准错误重定向到/dev/null
;
这是为了防止守护进程通过向终端写入杂散错误消息等来迷惑用户。守护进程可能应该做的是打开一些(配置的)日志文件,并在那里写入它想要与外部通信的任何内容。
(此函数分叉,如果 fork(2) 成功,则父级调用 _exit(2),以便只有子级才能看到更多错误。)
再次强调,要与 admins shell 会话解除关联,主程序会立即返回,而其他部分则留在后台,因此无需显式要求程序在后台启动(例如./daemon &
)
现在,手册页没有明确说明,但在这里暗示(在错误下):
该函数的 GNU C 库实现取自 BSD,并且不采用确保生成的守护进程所必需的双叉技术(即 fork(2)、setsid(2)、fork(2))。不是会话负责人。相反,生成的守护进程是会话领导者。
daemon()
还打电话setsid()
从会话中释放自己控制终端,因此来自终端发送的信号。但正如引用所述,这留下了一种可能性:如果它打开一个终端设备,它可能会意外地将其作为控制终端。为了避免这种情况,一些程序从子进程中调用,fork()
然后setsid()
再次 fork ,退出两个父进程,这样生成的进程就不是会话领导者(中间的进程是/曾经是),并且无法获得控制终端。你提到的Python程序正是这样做的。
更改umask
似乎与守护进程无关。也许该程序对此有特殊的需求。