Systemdとプロセスの生成


14

通常はここに投稿しないでくださいが、私はこの髪の毛を切り取っています。起動時に分岐し、他のプロセスの束を開始するPythonスクリプトがあります。このスクリプトは、起動時にsysvinitを介して起動されていましたが、最近Debian Jessieにアップグレードしたため、systemdを介して起動するように適合させました。

残念ながら、解決できない問題に直面しています。ユーザーシェルでスクリプトを直接起動すると、その子プロセスが正しく起動され、スクリプトが終了すると、子プロセスは孤立して実行を継続します。

systemdを介して起動した場合、親プロセスが終了すると、子もすべて終了します(まあ、画面はダイで起動し、死んでいるように見えますか?)

理想的には、すべての子プロセスを強制終了せずに親スクリプトを再起動できる必要がありますが、何か足りないものはありますか?

ありがとう!

[Unit]
Description=Server commander
After=network.target

[Service]
User=serveruser
Type=forking
PIDFile=/var/Server/Server.pid

ExecStart=/var/Server/Server.py
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

編集:Pythonスクリプトは、本質的にその子プロセスの「コントローラー」であると指摘することはおそらく関連があります。中央サーバーからの要求に応じて、GNU画面でサーバーを起動および停止します。通常は常に実行されており、サービスを生成して終了しません。ただし、プロセスがpid 1に孤立していることを意味する場合でも、子プロセスを強制終了せずにスクリプトをリロードできるようにしたい場合があります。実際、Pythonスクリプトが可能であれば、親プロセス。

仕組みのより良い説明:

  • Systemdは/Server.pyを生成します
  • Server.pyはSystemdのpidファイルを分岐して書き込みます
  • Server.pyは、その指示に基づいてgnu画面にサーバープロセスを生成します
  • Server.pyは、サーバーから要求された再起動を実行するために実行を続けます

Systemdを使用せずに起動すると、Server.pyを再起動でき、起動するgnu画面は影響を受けません。Systemdで起動すると、Server.pyがシャットダウンすると、それらのスクリーンプロセスがpid 1に孤立する代わりに、それらは強制終了されます。


1
Server.pyコードと起動されたサービスのフォーク方法(フォークする場合)がなければ、ソリューションを提供するのは困難です。ただし、一般的に言えば、これは準備プロトコル不一致の問題です。
intelfx

ところで、これExecStop=は必要ありません。systemdの停止時のデフォルトアクションは、プロセスを強制終了することです。KillMode=ディレクティブのドキュメントをご覧ください。
intelfx

1
もし適切な準備プロトコル(の一つが存在しない場合や、最後に... simpleまたはforking実際には、)、最後は次のようになりType=oneshotRemainAfterExit=yesそしてKillMode=control-group
intelfx

@intelfx基本的にPythonスクリプトは、Subprocess.callを使用して画面でサーバーを起動します。スクリプトは他の場所からコマンドを受信し、どの画面を開始するか、しないかを指示するため、それよりも複雑です。利用可能な画面も動的であるため、それ自体でsystemdサービスにできないのはなぜですか。systemdでこれらの画面をサービスの一部として扱うのは理想的ではありませんが、現在は同じプロセスグループにダンプされ、再起動するとマスターと共に停止します。
ボットスワナ

私の考えでは、systemdはそのような制御プロセスを「処理」しません(開始時にPIDを検索するだけで、後のものを認識しません...):|
rogerdpack

回答:


9

KillModeをcontrol-group(デフォルト)の代わりにprocessに設定するだけで、これを修正できました。皆さんありがとう


しかし、それは修正以上の回避策のように見えますが、他の答えを参照してください...これを行い、「systemctl stop」を実行すると、まだ実行されている子プロセスを殺しません[?] systemctlの監視外ですか?
rogerdpack

5

起動時に分岐し、他のプロセスの束を開始するPythonスクリプトがあります。

これは、あなたが間違っていることを示しています。これについては後ほど説明します。

スクリプトが終了すると、子プロセスは孤立し、実行を継続します。

これは正しいデーモンの振る舞いではありません。「メイン」プロセス(この場合は指定したためにフォークした子)がType=forking終了すると、systemdはサービスが非アクティブになったと見なし、整頓するために他のまだ実行中のプロセス(制御グループ内)を終了します。

rcsystemdの下で物事を行う正しい方法はまったく異なるため、System 5 スクリプトからsystemd への変換は簡単ではない場合があります。systemdで(たとえば)OpenVPN、OpenStack、またはOSSEC HIDSを実行する正しい方法は、rcスクリプトを使用して行う方法とは異なります。分岐しているスクリプトがあり、孫プロセスの負荷をすべて生成し、それらの孫が実行し続けることを期待して終了しているという事実は、分岐のossec-controlレベルが2つ少ないにもかかわらず、同じ種類の恐怖を犯していることを示しています。「有効」フラグをチェックし、システムの「有効」な部分の子プロセスを実行する「マスター」スクリプトを作成していることに気付いossec-controlた場合、恐ろしいと同じ間違いを犯しています。

systemdでは、こうした独自のメカニズムは必要ありません。これは、すでにあるサービスマネージャ。パー/unix//a/200365/5132、systemdにこのについて移動する正しい方法は、「サブサービス」を持っているスポーンいくつかの奇抜な混乱の試みというつのサービスを持っているではありません。それは、それぞれの子プロセスがそれ自体で完全なsystemdサービスとして持つことです。次に、通常のsystemdコントロールを使用して、システムのさまざまな部分を有効または無効にし、起動および停止します。OSSEC HIDSのケースでわかるように、シンプルなテンプレートサービスユニットはほとんどすべてのサービス(1つの例外は/ubuntu//a/624871/43344にあります)をカバーし systemctl enable ossec@agentlessd.service、オプションを有効にするなどのことを可能にしますagentlessdサービス、System 5で必要だった恐ろしい「マスタースクリプト」メカニズムはまったく必要ありませんrc

OSSEC HIDSほど極端ではないかもしれませんが、そのような再考が必要なケースはたくさんあります。eximやsendmailのようなMTSはそのようなものです。rcキューランナー、SMTP送信デーモン、およびSMTPリレーデーモンを生成する単一のスクリプトがあり、実行するものを正確に制御するために、構成ファイルに多数のアドホックシェル変数が含まれている場合があります。しかし、systemdでこれを行う正しい方法は、3つの適切なサービスユニット(そのうち2つはソケットユニットに関連付けられています)を使用し、アドホックなものはまったくなく、サービスマネージャーの通常のメカニズムだけです。


これに関するフィードバックに感謝します。サブセットサービスを使用することは理にかなっていますが、Pythonで行われたのは、私が説明できない理由です。私の唯一の解決策は、この方法を機能させる方法を見つけることです。でもありがとう。ちゃんとやってみたい。
ボットスワナ

スクリプトが起動する「サブ」サービスは、特定のユーザーとしてgnu画面で実行されているサーバーです。これらのサーバーは大幅に変更され、一部は追加され、一部は削除され、これは他の場所で制御されるため、systemdで実際のサービスになることはできません。また、同じスクリプトがsystemd以外のサーバーでも使用されます。
ボットスワナ

systemdには、ルートアクセスを必要とせずにサービスを追加および削除できる明示的な機能があります。「systemd以外のサービスでも使用される」は、上記の引数のうち、systemdを追加しても修正できない唯一の引数です。:)
チャールズダフィー

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.