追加読書

追加読書

man 7 daemon

既存のSysVデーモンが起動したら、初期化の一部として次の手順を実行する必要があります。このステップは、最新のデーモン(以下を参照)には必要ではなく、SysV互換性が必須の場合にのみ実装する必要があります。

[...]

6.子プロセスでsetid()を呼び出して端末から切り離し、独立セッションを作成します。

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互換性なしにシステムサービスとして実行されるようにプログラムを作成または変換するとき、これはマイナートラップのようです。システム化されたスタイルを擁護するこの記事では、この点を指摘していないようです。この記事では、SysVでこのような状況を回避するためにデュアルフォークを使用する必要があると主張しながら、その反対を示しています。

そうですか? systemdは私が見落としているものに対していくつかの保護を提供しますか、それともsystemdドキュメントの他の場所で問題が指摘されていますか?

答え1

systemdはこの状況に対してどの程度の保護を提供しますか?

あなたはそうすべきだと思います。代わりに、同じ設定TTYPathとサービスを検討してください[email protected]。実際に端末を制御する能力を得ることは必要、サービス管理に正確に必要なTTYログインサービスを含めることができます。

実際にこれが起こらないようにするのは、あらゆる場所で制御端末の自動割り当てを放棄し、open()古い意味を放棄することです。または会議予防してください。 Linuxではそうではありませんが、FreeBSD、NetBSD、OpenBSD、およびHurdでは現在のO_NOCTTYフラグはopen()完全に冗長です。これただ制御端末を取得する方法はioctl(…TIOSCTTY)

同時に、Linuxで開発された習慣はsystemd以前から長い間存在してきました。O_NOCTTYどこでも。 ☺

(はい、GNUおよびmusl Cライブラリはこの機能を提供していませんfopen()。これがまだ有用なメカニズムであるいくつかの理由の1つです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

関連情報