进一步阅读

进一步阅读

man 7 daemon

当传统的 SysV 守护进程启动时,它应该执行以下步骤作为初始化的一部分。请注意,这些步骤对于新型守护程序来说是不必要的(见下文),并且只有在必须与 SysV 兼容时才应实施。

[...]

6. 在子进程中,调用setsid()从任何终端分离并创建一个独立的会话。

7. 在子进程中,再次调用 fork(),确保守护进程永远不会再次重新获取终端

但将此与没有 SysV 兼容性痕迹的启动进程进行比较:

$ ps -efj
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root         1     0     1     1  0 May10 ?        00:06:44 /sbin/init
...
root       185     1   185   185  0 May10 ?        00:09:48 /lib/systemd/systemd-journald
root     16434     1 16434 16434  0 May26 ?        00:00:11 /usr/sbin/rsyslogd -n

rsyslog.service和的进程systemd-journal.service都是会话领导者 (SID = PID)。

看起来,如果这些程序被配置为登录到 TTY,它们就会将 TTY 作为控制终端,并在 TTY 挂起/接收到 Ctrl+C 时分别收到不需要的/致命信号。除非他们记得在打开 TTY 文件时设置 O_NOCTTY。

如果您的程序支持将消息写入自定义文件,那么在编写或转换程序以作为没有任何 SysV 兼容性的 systemd 服务运行时,这似乎是一个小陷阱。这个提倡systemd风格的文档似乎没有指出这一点。该文档暗示了相反的情况,坚持认为必须使用双分叉来避免 SysV 上的这种情况,然后在描述本机 systemd 服务将使用的步骤时没有提到这一点。

那是对的吗? systemd 是否提供了一些针对我忽略的保护措施,或者该问题是否在 systemd 文档的其他地方指出?

答案1

systemd 是否针对这种情况提供了一些保护 [...]?

你假设它应该。相反,请考虑诸如 之类的设置TTYPath和诸如 之类的服务[email protected]。获得控制终端的能力实际上是必要的,以便服务管理可以包含 TTY 登录服务,而这正是需要做到的。

真正防止这种情况发生的是放弃在 处自动分配控制终端open(),并放弃旧的语义。或者防止它。在 Linux 上情况并非如此,但在 FreeBSD、NetBSD、OpenBSD 和 Hurd 上,现在O_NOCTTY的 标志open()完全是多余的。这仅有的获取控制终端的方法是通过明确要求它,使用ioctl(…TIOSCTTY).事实上,自 4.4BSD 时代以来,这种情况已经持续了近四分之一个世纪。

与此同时,在 Linux 上养成的习惯也已经存在很长时间了,早在 systemd 之前:O_NOCTTY到处。 ☺

(是的,GNU 和 musl C 库不会为您提供此功能fopen()。这是仍然是一种有用机制的几个原因之一fdopen()。)

使用 nosh 工具集进行服务管理service-manager对此采取了略有不同的策略。不是总是将守护进程设置为会话领导者,而是为每个服务分配自己的内核会话对象,然后该对象就看不到任何用处,只有特定的服务也会setsid显式链接;例如使用的服务,当然是设置控制终端的服务,以及服务。 (如服务源中所述,调用自身。)ttylogin@*open-controlling-ttyagetty@*agettygetty@*mgettysetsid()

进一步阅读

答案2

systemd 不保护服务程序不获取控制终端。当打开用户指定的日志文件时,他们必须使用该O_NOCTTY标志来保护自己。

$ rpm -q systemd
systemd-238-8.git0e0aa59.fc28.x86_64

$ systemctl cat test
# /etc/systemd/system/test.service
[Service]
Type=simple
ExecStart=/bin/sh -c "exec cat </dev/tty10 >/dev/tty10"

$ systemctl status test
● test.service
   Loaded: loaded (/etc/systemd/system/test.service; static; vendor preset: disabled)
   Active: active (running) since Fri 2018-06-01 11:28:41 BST; 1min 35s ago
 Main PID: 12173 (cat)
    Tasks: 1 (limit: 4915)
   Memory: 180.0K
   CGroup: /system.slice/test.service
           └─12173 cat

Jun 01 11:28:41 alan-laptop systemd[1]: Started test.service.

$ ps -ejf
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
...
root     12173     1 12173 12173  0 11:28 tty10    00:00:00 cat

我还确认切换到 tty10 并按 Ctrl+C 会停止该cat过程。

相关内容