参考文献

参考文献

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()理由の 1 つです。)fdopen()

nosh ツールセットによるサービス管理では、service-managerこの点について少し異なるアプローチを採用しています。デーモン プロセスを常にセッション リーダーにするのではなく、各サービスに独自のカーネル セッション オブジェクトを割り当てて使用しないようにし、を使用するサービス、が制御端末を設定するサービス、および サービスなどの特定のサービスsetsidのみが明示的にチェーンされます。(サービス ソースに記載されているように、は自身を呼び出します。)ttylogin@*open-controlling-ttyagetty@*agettygetty@*mgettysetsid()

参考文献

答え2

O_NOCTTYsystemd は、サービス プログラムが制御端末を取得するのを防止しません。フラグを使用して、ユーザー指定のログ ファイルを開くときに、サービス プログラム自身を保護する必要があります。

$ 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プロセスが停止することも確認しました。

関連情報