端末を絶対に閉じることができない場合、デーモンが制御端末から自分で分離されるのはなぜですか?

端末を絶対に閉じることができない場合、デーモンが制御端末から自分で分離されるのはなぜですか?

デーモンの作成について私が読んだすべての内容は、デーモンが制御端末から切り離され、端末が閉じられるとデーモンがSIGHUP信号を受信しないようにする必要があることを示しています。

ただし、デーモンプロセスは常にinitプロセスによって開始されます。htopこれは、私のinitプロセス(systemd)に制御端末がないため、生成されたデーモンにも制御端末がないことを示しています。 SysVinitでどのように機能するのかわかりませんが、変更ログに制御端末がないか、「/dev/console」を使用するというヒントがあります。私が間違っている可能性がありますが、これは常に存在して終了できない特別なカーネルttyのようです。

私は何を逃したことがありませんか?

これは、制御端末から切り離すよりも、各デーモンに対して新しいプロセスセッションを開始することに関するものだと思います。セッションは、デーモンが子プロセスを作成するのに役立ちます。セッションはこれらのサブプロセスを追跡します。これにより、我々はそれらすべてを殺すことができます。

ベストアンサー1

@AndyDaltonと@muruが指摘したように(ありがとう!)SysVinitとSystemdは異なる動作をします。

systemd では、デーモンは init プロセスによってのみ生成されます。 systemctlなどのデーモンを制御するために使用されるcli-toolsは、IPCを介してinitプロセスにコマンドを送信し、それを実行します。彼らは独自にDバスを実装したsdバスを使用します。 D-busシステムメッセージバスが正しく機能していない場合は、ソケットを使用して置き換えることができますが、これにはroot権限が必要です。 (実際に再び降りることができるかどうかはわかりません。説明に基づいて推測したものです。この場合そしてこの議論)

SysVinitに関する限り、デーモンにシグナルを送信してデーモンを生成することは、デーモン固有のbashスクリプトの作業です。 initプロセスは起動時にこのスクリプトを実行します。ただし、cliを介して手動でデーモンを起動したい場合は、このスクリプトを直接実行できます。その後、デーモンはbashプロセスの子プロセスになり、制御端末を持ちます。詳細については、sysvinitデーモンスクリプトの例とインターネットの「service」cliツールを参照してください。 「サービス」は単にbashスクリプトです。 Debian パッケージ "sysvinit-utils" にあります。 initプロセスは、実行中のデーモンを追跡するためにPIDファイルのみを使用するようです。

これがSysVinitデーモンが制御端末から切り離される必要がある理由です。最新のデーモン(systemd、upstartなど)には必要ありません。これはまた、この部分がなぜ出てくるのかを説明します。手動:

  1. 最新のデーモンは制御TTYなしで(しかし独自のセッションリーダーとして)呼び出されるので、制御TTYが誤って取得されないようにTTYデバイスノードを参照できる呼び出しを常に指定するように注意する必要がありますO_NOCTTYopen()

結論として:

  1. SystemdはSysVinitスタイルの2つの分岐デーモン(type = forking)をサポートしていますが、これはデーモンの作成に推奨される方法ではありません。。デュアルフォークは必要ありません。

  2. systemdがあなたのためにsetid()を実行しているようです:

   Note that new-style init systems guarantee execution of daemon
   processes in a clean process context: it is guaranteed that the
   environment block is sanitized, that the signal handlers and mask
   is reset and that no left-over file descriptors are passed.
   Daemons will be executed in their own session, with standard
   input connected to /dev/null and standard output/error connected
   to the systemd-journald.service(8) logging service, unless
   otherwise configured. The umask is reset

これは、デーモンが制御端末から切り離される必要がないもう1つの理由です。すでに新しいセッションに参加しています。

  1. デーモンはそのセッションのリーダーです。したがって、デーモンは制御端末を取得しないように制御端末を開くときに注意する必要があります。しかし、最新のオペレーティングシステムでは、誤ってこれを行うのは少し難しいです。SIGHOPが設定を再ロードするように要求されている場合、制御端末をインポートすることはそれほど大きな問題ではない可能性があります。

  2. 確かではありませんが、そうだと思います。systemd は制御グループを使用してデーモンの子プロセスを追跡して終了します。では、なぜsetidが必要なのですか?私の場合は、今会議しているのか、それともコントロールグループが別々の会議を必要とするのかわかりません。おそらく、セッションがこの目的に使用されていない可能性があります。しかし、今はコントロールグループを使用します。

修正する:

  1. @Uncle Billyは、端末を介してプロセスに送信できる他のシグナルについて言及しました。私は少し研究をしました。SIGINT、SIGQUIT、および SIGSTP は tty ラインルールによって送信されます。これらの信号は、termios の c_lflag に ISIG フラグが設定されている場合に送信されます。ワイヤルールは、フォアグラウンドプロセスグループに信号を送信します。砲撃するほどではありません。シェルは、フォアグラウンドプロセスグループのpidをラインルールにプレビューします。 ISIG のデフォルト値が見つかりません。ただし、フォアグラウンドプロセスグループが手動で設定されていない場合(つまり、プロセスがジョブ認識シェルでない場合)、プロセスはこれらの信号を受信できない可能性があります。おそらく、これは端末が制御されているかどうかに関係しないかもしれません。職業管理に関することです。しかし、私は間違っているかもしれません。 Bourneシェルのように、どのように動作するかわからないシェルがSIGINTをどのように処理するのか疑問に思います。 「trap」コマンドは、そのメカニズムが異なることを示します。

おすすめ記事