我想更好地了解什么是后台进程。阅读这行代码后,问题就出现了:
/usr/sbin/rsyslogd -niNONE &
文件说:
-i pid file Specify an alternative pid file instead of the default one. This option must be used if multiple instances of rsyslogd should run on a single machine. To disable writing a pid file, use the reserved name "NONE" (all upper case!), so "-iNONE". -n Avoid auto-backgrounding. This is needed especially if the rsyslogd is started and controlled by init(8).
&符号&
似乎意味着请求该命令在后台运行,请参见,例如这里。
如果我的理解是正确的,pid文件与守护进程一起使用,即程序在后台运行时。
因此,从表面上看,所讨论的命令似乎首先告诉程序不要在后台运行-n
,然后为 pid 文件指定 NONE ,以表明它不是守护进程1,然后紧接着指定&
发送它进入背景。
我无法理解这一点。进程通常进入的背景是否是使用 发送到的不同背景&
?从我读到的所有内容来看,后台的唯一含义似乎是 shell 未被阻止。在这方面,要求进程不要自动后台运行然后后台运行并没有多大意义。
我在这里缺少什么吗?具体的背景是什么? (当我们这样做时,谁负责删除 pid 文件?)
1 - 在出现问题的 docker 容器上下文中,当容器停止然后重新启动时,pid 文件的存在可能会导致问题。我不清楚是什么负责删除 pid 文件,一些消息来源表明它是init 系统,例如 systemd,而其他人暗示这是程序的责任。但是,如果使用 SIGKILL 杀死进程,则程序可能没有机会删除它,因此后续容器重新启动将失败,因为 pid 文件已经存在,但预计不会存在。
答案1
UNIX 后台进程的概念是作业控制的一部分。作业控制是围绕终端会话的进程组织。
守护进程通常不在终端会话中运行,因此它们不是 Unix 作业控制意义上的后台进程,只是在属于机器的“不可见”活动的一般计算意义上。这很可能是rsyslogd
文档所指的内容:它指的是成为守护进程,而不是作业控制后台进程。
在交互式终端会话中,用户管理工作。每个工作是一组进程(可能是一个),由某些软件(通常是作业控制外壳)安排到该组中。会话中的每个作业都将终端作为其控制终端。
后台/前台概念与这些作业之间终端设备的共享有关。在任何时候,进程组之一都会被指定为前台进程组。它可以从终端读取字符,并将输出发送到终端。其他进程组都是后台进程组。
作业控制 shell 结合来自 TTY 的信令和某些功能(例如tcsetpgrp
.
前台进程组不仅可以从终端读取和写入,还可以接收 TTY 生成的信号,例如SIGINT
fromCtrlC和SIGTSTP
from CtrlZ。
通常,您使用CtrlZ将作业挂起到后台,然后使用作业控制命令让它bg
在后台执行。
当您发出 时CtrlZ,前台进程组中的每个进程都会收到SIGTSTP
信号并被挂起。作业控制 shell 检测到此更改,并进行库调用以将该作业移至后台,并使本身前台进程组。因此,shell 现在再次处于前台,它可以接收来自 TTY 的命令。
现在您可以输入背景,shell 将导致暂停的后台作业执行。
这弗格命令将导致 shell 将自身从前台删除,并再次将后台作业放入前台。
后台作业不会接收来自 TTY 的字符驱动信号,例如SIGINT
来自CtrlC.然而,当他们尝试读取或写入终端时,他们会收到类似的信号SIGTTOU
,并被阻止执行该操作。
作业控制就像交通警察,守卫对终端的访问。
它类似于 GUI 中的窗口管理。在典型的 GUI 中,一个窗口具有“键盘焦点”。按键会转到该窗口。作业控制也是如此:可以说,前台进程组拥有“终端焦点”。
该rsyslogd
文档几乎可以肯定使用术语“背景”实际上意味着“变成守护进程”或“守护进程”。这与 POSIX 作业控制下的“后台作业”不同。
当服务器应用程序自动守护进程时,这意味着如果它在终端会话中运行,它将采取措施将自身从该会话中删除。它分叉一个孩子,然后分叉一个孙子。子进程终止,因此孙子成为孤儿,并且成为init
守护进程的子进程。这是其中的一部分。另一部分是孙子将关闭标准输入、输出和错误文件描述符。因此它失去了与 TTY 的连接。可能会采取一些其他操作,例如更改到某些特定的工作目录。
rsyslogd
如果由 运行,它不会自行守护进程,这是有道理的init
,因为没有终端会话可以与之分离。 (但是,rsyslogd
可以检测到它不是终端会话的一部分,并且在这种情况下不需要该-n
标志。)
因此,实际上,服务器中 do-not-daemonize 命令行选项的主要用途是用于调试,具体原因如下:
也许守护进程有一些调试跟踪模式,消息可以发送到标准输出。如果您想在控制台上观看这些消息,您不希望守护程序关闭其标准输出文件描述符。
如果您想在调试器下调试守护进程,如果它只是退出,那么实际的守护进程活动发生在分叉的孙子中,这是不方便的。
当您进行测试时,您可能希望对守护进程进行作业控制,例如使用 终止它CtrlC,或使用 挂起它CtrlZ。
有时,人们喜欢在终端多路复用软件(例如 GNU Screen 或 Termux)下运行服务器,其中服务器在终端会话中运行。自动守护进程会破坏其目的。
关于谁负责删除PID文件:主要是服务应用程序本身,如果它被干净地关闭的话。如果某个主进程正在管理服务,它可以知道其 PID 文件的路径,并在它们终止但未删除文件的情况下对其进行清理。 PID 文件通常放置在重新启动时会被擦除的目录中,例如/var/run
,因此,如果系统发生灾难性故障并且必须重新启动,则重新启动会处理 PID 文件。