从系统管理员的角度来看,在基于 UNIX 的系统上部署服务时有哪些实际差异?
答案1
对于守护进程,您想要的是一个与任何事物都没有联系的进程。至少,您希望它位于自己的会话中,不附加到终端,没有从父级继承的任何文件描述符打开任何东西,没有父级照顾您(除了 init 之外)拥有当前目录/
以免阻止卸载...
要从终端分离,您需要创建一个新会话,但是,要创建会话,您不能是组(或会话)领导者,因此最好是分叉一个新进程。假设父进程退出,这也意味着该进程将不再有父进程,并将被 init 采用。然后,关闭所有可能的文件描述符,你chdir("/")
(不能关闭当前工作目录来释放该资源,就像文件描述符一样,使/
当前工作目录至少不会阻止卸载目录)。
因为该进程是会话领导者,所以存在这样的风险:如果它打开终端设备,它就会成为该终端的控制进程。第二次分叉可确保这种情况不会发生。
另一方面,&,在交互式 shell 中,分叉并创建一个新的进程组(以免位于终端的前台进程组中),在非交互式 shell 中,分叉进程并忽略其中的 SIGINT。它不会与终端分离,不会关闭文件描述符(尽管有些 shell 会重新打开标准输入/dev/null
)...
答案2
传统的守护进程方式是:
fork()
setsid()
close(0) /* and /dev/null as fd 0, 1 and 2 */
close(1)
close(2)
fork()
这确保该进程不再与终端位于同一进程组中,因此不会与终端一起被杀死。 IO重定向是为了让输出不会出现在终端上。
答案3
作为守护进程运行程序/进程与使用 & 符号将其分叉到后台之间的区别基本上与所有权有关。
最常见的是,守护进程的父进程是在里面进程(Unix 系统上启动的第一个进程),守护进程是该进程的子进程,意味着它不受您作为非特权用户的直接控制。另一方面,将程序/进程分叉到后台意味着您可以随时将其调用回前台和/或终止它。
答案4
当父进程死亡时,您的进程command &
将被 SIGHUP 信号杀死。
如果程序没有明确支持“守护程序模式”(即忽略 HUP 信号),系统管理员仍然可以访问一些解决方法。
在 bash 系统上,您可以使用:
(trap '' HUP; command) &
这将打开一个子 shell,HUP
用空处理程序捕获信号并对其进行“&”号/分叉。
输出可能仍会被重定向到错误的tty
。或者迷路。
您可以使用&>command.out
或1>output.out
和修复该问题2>errors.out
在大多数系统上,您可能还可以访问该nohup
命令。
nohup
大大简化了这个过程。这是相当标准的,但我发现许多 busybox 嵌入式 ARM 发行版都缺少它。你只需写:
nohup command &
..你就完成了。输出被重定向到 IIRC nohup.out
,但可以使用选项更改此文件名。