進一步閱讀

進一步閱讀

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過程。

相關內容