プロトコルミスマッチの準備

プロトコルミスマッチの準備

systemdOSSEC HIDS用のユニットファイルを作成しています。問題は、systemdサービスを開始するとすぐに停止することです。

次のコマンドを使用すると、ExecStartすべてがうまく機能します。

ExecStart=/var/ossec/bin/ossec-control start

ただし、次のような小さな改善が適用されたときに、ブートSIG 15後に受信したOSSECログにこれらの事実が見つかりました。

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'

別の小さな変更を加えると、サービスはSIG 1520秒後にそれを受け取ります。

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'

だから私はサービスが開始した後、プロセスを終了しますsystemd/bin/sh/bin/shOSSEC

この問題をどのように解決できますか?

答え1

プロトコルミスマッチの準備

Wielandが示唆しているように、Typeこの品質は重要です。この設定はどういう意味ですか?契約の準備systemdはサービスが会話できると期待しています。simpleサービスは即時準備とみなされます。forking初期プロセスが子プロセスに分岐して終了すると、サービスは準備済みと見なされます。dbusデスクトップバスにサーバーがある場合、サービスは準備ができていると見なされます。など。

サービス機能に一致するサービスユニットで準備プロトコルを宣言しないと、問題が発生する可能性があります。準備プロトコルの不一致により、サービスが正しく開始されないか(より一般的に)systemdでエラーと診断される可能性があります。サービスを開始できないと見なされると、systemdは次のことを保証します。サービスの各孤児追加プロセスエラーの一部として(該当する観点から)実行されていた可能性があるサービスは、サービスを非アクティブ状態に適切に戻すために終了します。

それがまさにあなたがすることです。

まず、単純なもの:sh -c一致しType=simpleないかType=forking

simpleプロトコルの初期プロセスは次のとおりです。はいサービスプロセスただし、実際にsh -cラッパーは実際のサービスプログラムを実行します。子プロセスとして。まず、問題が発生して動作が停止しますMAINPIDExecReloadを使用するときは、またはをType=simple使用する必要があります。sh -c 'exec …'使用しないでください sh -c最初。後者は、一部の人が考えるよりも本当であることがよくあります。

sh -cやはり一致しませんType=forking。サービス準備プロトコルはforking非常に具体的です。初期プロセスは子プロセスを分岐してから終了する必要があります。 systemdはこのプロトコルにタイムアウトを適用します。初期プロセスが割り当てられた時間内にフォークされない場合は、準備ができていません。指定された時間内に初期プロセスが終了しないと失敗します。

不要な恐怖ossec-control

これは私たちに複雑なもの、つまりスクリプトを紹介しますossec-control

それは明らかですrcこれは、4〜10個のプロセスを分岐し、独自に分岐して終了するSystem 5スクリプトです。これは、ループ、競合状態、これを回避する任意のs、およびシステムを半分のブート状態にすることができる障害モードをrc使用して、1つのスクリプトでサーバープロセス全体を管理しようとするSystem 5スクリプトの1つです。他のすべての怖いものAIXシステム・リソース・コントローラーやdaemontoolsなどのものは20年前に発明されました。特別な機能と動詞を実装するために動的に書き換えられたバイナリディレクトリに隠されたシェルスクリプトを忘れないでください。forsleepenabledisable

次のよう/bin/sh -c '/var/ossec/bin/ossec-control start'な場合はどうなりますか?

  1. systemd は期待するサービスプロセスをフォークします。
  2. それが知覚であり、二股に分かれていますossec-control
  3. すると、4~10人の孫が誕生することになります。
  4. 孫はすべて順番にフォークして出かけた。
  5. すべての子孫は分岐して並列に終了します。
  6. ossec-controlやめる。
  7. 最初のシェルが終了します。
  8. サービスプロセスはいいね -孫ですが、これがうまくいく方法がよく似合います。どちらもありませんこれforking ...でもない準備プロトコルに従って、simplesystemd はサービス全体が失敗したとみなし、再び終了します。

systemdでは、これらの恐ろしいことは実際にはまったく必要ありません。何もない。

systemdテンプレートサービスユニット

代わりに非常に簡単に書いてください。テンプレートユニット:

[単位]
説明=OSSEC HIDS %i サーバー
以降 = network.target

[提供する]
タイプ=シンプル
ExecStartPre=/usr/bin/env /var/ossec/bin/%p-%i -t
ExecStart=/usr/bin/env /var/ossec/bin/%p-%i -f

[インストールする]
WantedBy =マルチユーザー。ターゲット

別の名前で保存してください。/etc/systemd/system/[email protected]

様々な実務サービスはインスタンス化テンプレート名は次のとおりです。

その後、機能を有効または無効にします。サービス管理システムから直接(そしてRed Hat エラー 752774修正)シェルスクリプトを隠すことなく。

systemctl を有効にする

さらに、systemdは各実サービスの直接的な可視性と追跡機能を備えています。これはログをフィルタリングするために使用できますjournalctl -u。単一のサービスがいつ失敗するかがわかります。どのサービスを有効にして実行する必要があるかを知っています。

注:ここのType=simpleオプションは-f他の多くの場合と同様に正確です。現場サービスがほとんどない実際に彼らは準備ができていることを示しています。おかげでexitここでもそうではありません。しかし、それはforkingタイプに関するものです。野生のサービスはほとんどフォークして終了することです。なぜなら、これがデーモンがしなければならないことであるという誤解があるからです。実際にはそうではありません。 1990年代以降はそうではありませんでした。今追いつく時間です。

追加読書

答え2

スタートアップサービス/アプリケーションがPIDを維持している場合は、Type=forkingPIDファイルの場所を維持して提供してください。

[Unit]
Description="Run app on boot"
After=network.target syslog.target auditd.service

[Service]
Type=forking
PIDFile=/var/run/apache2/apache2.pid
ExecStart=/etc/init.d/apache2 start
ExecStop=/etc/init.d/apache2 stop
StandardOutput=syslog
StandardError=syslog
Restart=on-failure
SyslogIdentifier=webappslog

[Install]
WantedBy=multi-user.target
Alias=webapps

答え3

やや関連があるのはsystemdサービスがあり、systemdが30秒後にそのサービスを「終了」するようです。

systemctl status service-namemain process exited, code=exited, status=1/FAILURE30秒後に表示されます。

端末で手動で使用するなど、「スタンドアロン」でうまく動作します。同じ環境)。

それが明らかになった

Type=forking
...
Environment=ABC="TRUE"
ExecStart=/path/to/my_script_to_spawn_process.sh

内部でmy_script_to_spawn_process.sh行われています。

/bin/something > /dev/null 2>&1 &

それはうまくいきますが、出力ログ情報を削除します(通常はファイルに保存されるか、そうでない場合はそうですjournalctl)。

他の場所からログインするように変更してください。/bin/something > /tmp/my_file

その後、追跡によって/tmp/my_file実際の理由が明らかになった。 (接線)bashと同じ構文は使用できませんEnvironment=ABC="true"。引用符が含まれていないか、キー値がすべて引用符内になければなりません。Environment="ABC=true"これにより、プロセスは約30秒後に「設定ステップ」で終了しました。

答え4

systemdのデーモンモデルは非常に単純であり、複数のブランチ、実行、およびsetuidを実行する既存の多くのデーモンと互換性がありません。最も一般的なのは、設定のために root で始まり、日常的な作業のために権限の低い UID に切り替えるデーモンです。たとえば、Pidファイルの初期化は、権限の問題のためにsystemdで失敗するものの1つです。解決策(修正はありません)がありますが、文書化のレベルが低いです。

JdeBPの説明は歓迎されていますが、不完全であり、彼はこれがすべてossec-controlの誤りであると主張していますが、これは本当ではありません。問題をデバッグするためにプロセスを終了したときに検閲されていないログ行を取得したり、systemd自体から意味のあるエラーメッセージを取得するなど、非常にマイナーなものでさえ問題になる可能性があります。

関連情報