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-tty
agetty@*
agetty
getty@*
mgetty
setsid()
追加読書
- ジョナサンデボインポラード(2018)。
setsid
。スナックガイド。ソフトウェア。 - ジョナサンデボインポラード(2018)。
open-controlling-tty
。スナックガイド。ソフトウェア。 - ジョナサンデボインポラード(2015)。 」継承とデーモンエラー
」。
service
これ以上コマンドに問題はありません。。ノッシュについて。ソフトウェア。 - ジョナサン・ドボイン・ポラード(2001)。 」
fork()
このために「デーモンをバックグラウンドに置かないでください」。」。Unixデーモンを設計する際に避けるべき間違い。よく与えられる答えです。 - ジョナサン・デ・ボーインポラード。 」仮想端末ログイン」。スナックガイド。ソフトウェア。
- ジョナサン・デ・ボーインポラード。 」実際の端末ログイン」。スナックガイド。ソフトウェア。
- http://git.musl-libc.org/cgit/musl/tree/src/stdio/__fmodeflags.c
- https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/libio/fileops.c#L274
答え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
。