systemdサービスマニュアルを何度も読みましたが、まだデフォルトのsystemdモードを把握できません。
起動時に起動プロセス(Dockerコンテナやドライブフォーマットなど)を一度実行し、正常に完了したいと思います。ただし、これにType = oneshotを使用するとRestart = on-failureは使用できず、失敗した場合は操作を再試行しません。ここで明らかなものを見逃していますか?
また、Restart = on-failureを使用してType = simpleを設定しようとしましたが、多くの場合、マンページのワンショットサービスが提供する次の動作が必要です。
oneshotは単に動作しますが、systemdが後続のユニットを起動する前にプロセスを終了する必要があります。
修正する:
答え1
私が試している1つの可能な回避策は次のとおりです。
[Unit]
Description=Tags instance and EBS vols
After=docker.service
Requires=docker.service
[Service]
ExecStartPre=/usr/bin/docker run --rm -v /opt/tag.sh:/tag.sh -v /opt:/ack --entrypoint=/bin/sh alpine /tag.sh
ExecStartPre=/usr/bin/sh -c '[[ -e /opt/TAG_SUCCESS ]]'
ExecStart=/usr/bin/rm /opt/TAG_SUCCESS
Restart=on-failure
RestartSec=30
スクリプトの実行が終了する場所ですtag.sh
。touch /ack/TAG_SUCCESS
私はこれが望む動作に非常に近いと思います。ExecStartPre
実行は順番に行われ、呼び出す前に成功した完了を待ちExecStart
、ユニットはStarting
一度だけ考慮されExecStart
、この時点で私たちは開始タスクを完了したと確信しています。
しかし、それでも巨大なハッキングのように感じますか?
答え2
ツアーの後、systemdのnotify
-typeにoneshot
次のようなexec
属性があることがわかりました。
通知はexecのように動作しますが、サービスは開始が完了した後にsd_notify(3)または同等の呼び出しを介して通知メッセージを送信すると予想されます。この通知メッセージを送信した後、systemd は後続のデバイスを起動します。このオプションを使用する場合は、Systemdが提供する通知ソケットへのアクセスを開くようにNotifyAccess =(以下を参照)を設定する必要があります。 NotifyAccess=が存在しないかなしに設定されている場合は、デフォルトで強制されます。
中:
exec型は単純型に似ていますが、サービス管理者は基本サービスバイナリを実行した直後にその単位が開始されると見なします。サービス管理者はこの時間まで後続のデバイスの起動を延期します。 (つまり、単純はfork()が返された直後に追加の操作を続行しますが、execはサービスプロセスのfork()とexecve()が成功するまで続きません。)これはexecサービスを開始するコマンドラインです意味します。 systemctlを使用すると、サービスバイナリが正常に呼び出せない場合(たとえば、選択したUser =が存在しない場合、またはサービスバイナリが欠落している場合など)が失敗を報告します。
つまり、組み合わせsimple
とoneshot
動作:
# <your service>.service
[Unit]
Description=Your awesome service
[Service]
ExecStart=/usr/local/bin/your-daemon-script
Restart=on-failure
RestartSec=30
NotifyAccess=all
# your-daemon-script
# Start everything
# ...
# If an error happens here, the service will restart
# If everything went fine systemd-notify --ready is used to notify systemd about that.
# After notifying systemd, systemd will switch the services state into ready and then starts other services which had to wait for this serivce to get ready.
systemd-notify --ready