编辑

编辑

我目前正在阅读《Unix 环境下的高级编程》。在其中一项练习中,它说:

唯一不是会话领导者的用户级守护进程是 rsyslogd 进程。解释为什么 syslogd 守护进程不是会话领导者。

然而,当我自己去验证这一点时,我发现在我的系统(Linux 4.4)上它确实是一个会话领导者(因为 PID == SID):

UID        PID  PPID  PGID   SID  CMD
syslog    1171     1  1171  1171  /usr/sbin/rsyslogd -n

这是系统的事情吗?由于每个人都追随了 systemd 的潮流,本书中的一些信息有点过时了,而它主要讨论的是经典的 System V init。或者也许他们只是改变了它的工作方式?

这本书显然想说明为什么它是不同的,所以如果有人知道为什么历史上它过去没有成为会议主持人,以及为什么现在是会议主持人,那就太好了。

答案1

编辑

我实际上查看了运行 rsyslogd 4.2.0 的旧 ubuntu 10.04 系统。

那个setsid()根本没有调用(因此从执行它的进程继承了 sid),而是调用了(此处来自strace输出):

 19391 open("/dev/tty", O_RDWR|O_LARGEFILE|O_CLOEXEC) = 0
 19391 ioctl(0, TIOCNOTTY)               = 0

与终端分离。

看着源代码HAVE_SETSID仅当未设置时才执行此操作。显然 Linux 已经setsid()存在了几十年了,所以有些地方出了问题。

现在,更多地查看源代码,这只是构建过程从未设置,因为它首先HAVE_SETSID不检查对的支持。setsid()

该错误(拼写错误:在 autoconf 文件中setsid拼写)是setid2013年修复(首次在 rsyslogd 7.5.3 中发布)。

(顺便说一句,请参阅去做关于 HP/UX 的部分在旧代码中,这表明作者已经意识到存在问题(但直到很久以后才进行调查))。

将原始答案保留在下面,因为人们可能会发现其中的信息有用。


一个疯狂的猜测:

如果您是会话领导者并打开tty没有O_NOCTTY标志的设备,那么您将成为终端的控制进程。

这就是为什么当尝试执行一个应用程序(否则未被设计为作为守护进程运行)以使其作为守护进程运行时,建议在setsid()执行它之前再执行一次 fork,以确保该进程不会无意中成为一个守护进程。终端控制器(如果由于某种原因打开了 tty 设备)。

syslogd通常会打开 tty 设备来发送用户消息,因此这可能就是为什么您的书说 syslogd 不是会话领导者,描述了 O_NOCTTY 标志不存在时 syslogd 实现的行为(尽管该标志至少已经存在)自20世纪80年代末以来)。

另一种方法是 syslogd 确保它打开的所有文件都是用 O_NOCTTY 打开的,这可能是您的rsyslogd(与 无关systemd)所做的。

相关内容