
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-tty
agetty@*
agetty
getty@*
mgetty
setsid()
参考文献
- ジョナサン・デ・ボイン・ポラード(2018年)。
setsid
。noshガイド. ソフトウェア。 - ジョナサン・デ・ボイン・ポラード(2018年)。
open-controlling-tty
。noshガイド. ソフトウェア。 - ジョナサン・デ・ボイン・ポラード(2015年)。継承と悪魔化の誤謬
「」。
service
コマンドに関する問題はもうありません. ノッシュの宣伝文句。ソフトウェア。 - ジョナサン・デ・ボイン・ポラード(2001年)。
fork()
デーモンをバックグラウンドに置くためにこれを行わないでください。「」。Unixデーモンプログラムを設計する際に避けるべき間違いよくある質問。 - ジョナサン・デ・ボイン・ポラード。仮想端末ログイン「」。noshガイド. ソフトウェア。
- ジョナサン・デ・ボイン・ポラード。実際の端末ログイン「」。noshガイド. ソフトウェア。
- http://git.musl-libc.org/cgit/musl/tree/src/stdio/__fmodeflags.c
- https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/libio/fileops.c#L274 翻訳: 翻訳: 翻訳:
答え2
O_NOCTTY
systemd は、サービス プログラムが制御端末を取得するのを防止しません。フラグを使用して、ユーザー指定のログ ファイルを開くときに、サービス プログラム自身を保護する必要があります。
$ 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
プロセスが停止することも確認しました。