以前私はinit.d /スクリプトを使用して、何年も完璧に動作していたデーモンを管理しました。今、私はsystemd /スクリプトを提供する必要があることに気づき、デーモンセットアップコードを実行する方法でそれを機能させることができません。
デーモンをセットアップするとき、制御端末を緩めてセッションリーダーにならないようにするために、2回forkします。
これの問題は、あなたがそうするときsystemd /がトラックを失い、デーモンを殺すことを私が確認したことです。また、2番目のフォークをスキップすると、systemd /で再び機能することを確認しました。
私の基本的な(この議論のために少し簡略化した)systemd /スクリプトは
[Unit]
Description=GM7 Service Daemon
[Service]
Type=forking
ExecStart=/usr/bin/g7ctrl
[Install]
WantedBy=multi-user.target
だから私は私の質問だと思います:過去10年間C/C++でデーモンセットアップコードを実行した方法を変更する必要がありますか、それともsystemd /にダブルフォークを追跡するオプションがありますか?
Systemd自体が開始する各デーモンのプロセスを生成する場合、内部の仕組みを完全に読み上げていません。その場合、ダブルフォークは実際に使用されなくなります。
私はそれを行った方法(ダブルフォーク)が部分的に歴史的な理由のためであることを認めますが、当時、私はベストプラクティスについてかなり集中的に読みましたが、これが私がやってきたことです(十年ほど前)
過去10年間にC/C++でデーモンセットアップコードを実行した方法を変更する必要がありますか?
はい。
10年ほど前でさえ、これは正しい方法ではありませんでした。 1990年代初頭以来、AIXシステムリソースコントローラーは正しくありませんでした。 daemontoolsユーザーは、1990年代後半以降、このようにしないことを提唱しました。 2006年に主流のLinuxオペレーティングシステムが採用し始めたUpstartには適切ではありませんでした。1980年代の初めにAT&T System 5 Release 3 inittab
から物事を実行することは適切ではありませんでした。
Systemdには適切ではありません。人々がforking
タイプについてあなたに言うかもしれませんが、彼らが通常忘れている、または知らないことは、それを固有サービス準備プロトコル。これは、特定の方法で行われる二重分岐に依存します。さらに悪いことに、プロトコルを正しく話すためにそれを行う必要がある方法は、あなたや他の人がC/C++プログラムを書く方法とうまく混ざりません。
2008年に、この主題に関する私のよくある回答は約10分の3年間存在しており、私や他の人々は、FGA形式に変換する前にかなり同じことを人々に伝えていました。
IBMは1995年以来レッドブックでそれを言っていました。
いくつかのJohnny-come-latelysは、systemdの観点から、systemdのマニュアルでこれと同じことをわずか8年かそこら言っています。 ☺
サービス管理サブシステムにこれをすべて処理させます。プログラムは、実行を開始したときにデーモンコンテキストですでに実行されています。
デーモン化の誤りに依存するすべてのコードを本当に維持したい場合は、少なくとも過去20年間に他の多くの人々が(一部はdaemontoolsの人々に応じて)行っていることを行い、世界にコマンドを与えます- すべてをオフにする行オプション。ただし、そのコマンドラインオプションがデバッグスイッチとしての役割を果たすようにしないでください。
はい。systemdは、Type=forking
を使用する場合、ダブルフォークデーモンを処理できます。
メインプロセスが終了したときにプロセスが残っている限り、systemdはそれがメインプロセスであると想定します。
Type=forking
の機能の詳細と詳細については、systemdのドキュメントの 従来のフォークサービスのこの例 を参照してください。
systemdは、初期スタータープロセスの終了とデーモンが起動して準備ができていることについてより厳密です。その例から:
正常に終了し、少なくともプロセスが残っている場合(および
RemainAfterExit=no
)、サービスは開始されていると見なされます。
したがって、あなたの場合に起こっていることは、最初の子(systemdがサービスのメインプロセスであると考える)をフォークした直後にスタータープロセスが終了し、その後最初の子が再びフォークして終了することが考えられるため、systemdは実際にはそうではないが、サービスが終了した。
一部の人は主張します これはSystem V initでも壊れた動作です :
繰り返しますが、sysvinitの場合、systemdの場合と同様に、適切に同期しない場合は問題が発生します。ある程度はこれに対処しますが、完全に安全で正しい方法は、問題のプログラムを修正することです。
いずれにせよ、私があなたに与える最高のアドバイスは、systemdで実行しているときはダブルフォークをスキップすることです。デーモンからダブルフォーク機能をremoveする必要はありません。デーモン化をスキップするコマンドラインオプション(-f
、-F
または--foreground
など)を追加するだけですプログラムをコード化し、フォアグラウンドで実行します。 systemdサービスファイルでそのオプションを使用します。
(このようなオプションは、デーモンを実行してデバッグやトラブルシューティングを行う場合にも役立ちます。)
systemdのType=forking
は、ダブルフォークデーモンで動作しますが、最終的には互換性のためだけにあります。フォークしない(メインプロセスを追跡するのが簡単)には利点があります。そのため、プログラムを変更できる場合は、そうすることをお勧めします。