OSSEC HIDS用のsystemdユニットファイルを作成しています。問題は、systemdがサービスを開始するとすぐに停止することです。
そのExecStartディレクティブを使用すると、すべて正常に動作します。
ExecStart=/var/ossec/bin/ossec-control start
しかし、OSSECログで細かい改善を行うと、起動後にSIG 15を受け取ることになります。
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'
別の小さな変更サービスを作成すると、20秒後にSIG 15を受け取ります。
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'
つまり、systemdはサービスの開始後に/ bin/shプロセスを終了し、bin/shはOSSECを終了します。
この問題を解決するにはどうすればよいですか?
ヴィーランドが示唆したように、サービスのType
は重要です。その設定は準備プロトコル systemdがサービスが話すことを期待するものを示します。 simple
サービスはすぐに準備ができていると見なされます。 forking
サービスは、その初期プロセスが子をフォークして終了した後に準備ができていると見なされます。 dbus
サービスは、サーバーがデスクトップバスに表示されたときに準備ができていると見なされます。などなど。
サービスユニットで準備されたプロトコルがサービスの動作と一致するように宣言されていない場合、問題が発生します。準備プロトコルの不一致により、サービスが正しく開始されない、または(より一般的には)systemdが失敗したと(誤って)診断されます。サービスがsystemdの起動に失敗したと見なされた場合、サービスの孤立したすべての孤立したプロセスを実行するために、(サービスの観点から)失敗の一部として実行されたままになっている可能性があるものを強制終了します。サービスは適切に非アクティブ状態に戻ります。
あなたはまさにこれをやっています。
まず、単純なもの:sh -c
はType=simple
またはType=forking
と一致しません。
simple
プロトコルでは、初期プロセスはbeサービスプロセスに渡されます。しかし実際には、sh -c
ラッパーが実際のサービスプログラム子プロセスとしてを実行します。つまり、MAINPID
はうまくいかず、最初にExecReload
が機能しなくなります。 Type=simple
を使用する場合、最初にsh -c 'exec …'
またはnot usesh -c
を使用する必要があります。後者は、多くの場合、一部の人々が考えるよりも正しいコースです。
sh -c
はType=forking
とも一致しません。 forking
サービスの準備プロトコルは非常に具体的です。最初のプロセスは子をforkしてから終了する必要があります。 systemdはこのプロトコルにタイムアウトを適用します。最初のプロセスが割り当てられた時間内に分岐しない場合、準備ができていないことになります。最初のプロセスが割り当てられた時間内に終了しない場合、それも失敗です。
ossec-control
である不要な恐怖これにより、複雑なもの、つまりossec-control
スクリプトが表示されます。
判明しました System 5のrc
スクリプトであり、4から10のプロセス間で分岐し、それ自体が分岐して終了します。 rc
ループ、競合状態、任意のfor
sを使用して1つのスクリプトでサーバープロセスのセット全体を管理しようとするSystem 5 sleep
スクリプトの1つです。それらを避け、半起動状態でシステムを窒息させる可能性がある障害モード、および20年前に人々がAIXシステムリソースコントローラーやデーモンツールなどを発明した他のすべての恐怖。そして、特異なenable
およびdisable
動詞を実装するために、オンザフライで書き換えるバイナリディレクトリ内の非表示のシェルスクリプトを忘れないでください。
したがって、/bin/sh -c '/var/ossec/bin/ossec-control start'
を実行すると、次のようになります。
ossec-control
をフォークするシェルです。ossec-control
は終了します。forking
norsimple
準備プロトコル。systemdはサービス全体が失敗したと見なし、サービスをシャットダウンします。Systemdでは、この恐怖は実際にはまったく必要ありません。どれでもない。
代わりに、非常にシンプルなテンプレートユニットを記述します。
[Unit] Description = OSSEC HIDS%i server After = network.target [Service] Type = simple ExecStartPre =/usr/bin/env/var/ossec/bin /%p-%i -t ExecStart =/usr/bin/env/var/ossec/bin /% p-%i -f [インストール] WantedBy = multi-user.target
これを/etc/systemd/system/[email protected]
として保存します。
さまざまな実際のサービスは、このテンプレートのinstantiationsで、次の名前が付けられています。
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
次に、機能を有効または無効にしますサービス管理システムから直接( RedHatバグ752774 修正済み)。非表示のシェルスクリプトは必要ありません。
systemctl enable ossec @ dbd ossec @ agentlessd ossec @ csyslogd ossec @ maild ossec @ execd ossec @ analysisd ossec @ logcollector ossec @ remoted ossec @ syscheckd ossec @ monitord
さらに、systemdは実際の各サービスを直接知り、追跡します。 journalctl -u
でログをフィルタリングできます。個々のサービスがいつ失敗したかを知ることができます。これは、どのサービスが有効になって実行されているかを認識しています。
ちなみに、Type=simple
と-f
オプションは、他の多くの場合と同じようにここにあります。実際にはごく少数のサービス実際に準備ができていることを示すexit
の提供により、これらのサービスもそのようなケースではありません。しかし、それがforking
タイプの意味です。デーモンが本来行うべきであるという誤った受け止められた知恵の概念が原因で、メインのサービスは実際には分岐して終了します。実際、そうではありません。それは1990年代以来ありません。追いつく時間です。
Type = forkingを維持し、start service/appがpidを維持している場合は、pidファイルの場所を指定します。
[単位]
Description = "起動時にアプリを実行"
After = network.target syslog.target auditd.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
[インストール]
WantedBy = multi-user.target
エイリアス= webapps
ある程度関連していますが、systemdが30秒後に「殺す」ように見えるsystemdサービスがありました。
systemctl status service-name
は、30秒が経過するとmain process exited, code=exited, status=1/FAILURE
と表示されます。
「単独で」正常に実行されます(手動で 同じ環境 を使用してターミナルで)。
だったことが判明
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秒後の「セットアップ段階」。