systemd oneshot 一度だけ実行する必要がある

systemd oneshot 一度だけ実行する必要がある

生成されたEnvironmentFileを必要とする複数のsystemdサービスがあります。このEnvironmentファイルを生成するシェルスクリプトがありますが、そのEnvironmentファイルが必要なので前にExec... コマンドを実行する場合、 ExecStartPre=generate_env_file.sh は使用できません。そのため、そのスクリプトをワンショットで実行するように別のサービス (generate_env_file.service) を設定しています。

[Service]
Type=oneshot
ExecStartPre=/usr/bin/touch /path/to/config.ini
ExecStart=/path/to/generate_env_file.sh

また、次のような他のサービス ファイルも複数あります。

[Unit]
Requires=generate_env_file.service
After=generate_env_file.service

2 つ以上の依存サービス (generate_env_file.service を必要とする) が並行して実行され、generate_env_file.service の 2 つの並行実行が生成されないことをどのように保証できますか?

RemainAfterExit=true または StartLimitIntervalSec= と StartLimitBurst= を使用して、一定期間に一度に 1 つのコピーのみが実行されるようにすることを検討しましたが、これを行うための最良の方法がわかりません。

答え1

RemainAfterExit=trueが正しい方法です。この場合、Systemdはサービスを開始し、Systemdはそれを開始済みでライブであると見なします。ただし、これは を実行するユースケースをカバーしていませんsystemctl restart generate_env_file.service。この場合、systemdはサービスを再実行します。これを解決するには、実行ファイルシステムにマーカーファイルを作成しExecStartPost=ConditionPathExists=ファイルの存在を確認するためのディレクティブ。

答え2

ConditionFirstBootこれも興味深いかもしれません:

ブール引数を取る。この条件は、システムが初めて起動するかどうかに基づいてユニットを条件付けするために使用できる。これは、/etc/システムが起動を開始したときには未設定であったことを意味する(詳細については、「初回起動セマンティクス」を参照)。 マシンID(5))。マネージャーが起動フェーズを完了すると、最初のブートは完了したとみなされます (この条件は false と評価されます)。

/etc/この条件は、工場出荷時設定にリセットした後の最初の起動時、または新しいシステム インスタンスが初めて起動したときに入力するために使用できます。

堅牢性のために、 を持つユニットは、を持つこのパッシブ ターゲットConditionFirstBoot=yesの前に順序付けされfirst-boot-complete.target、 を持つこのパッシブ ターゲットにプルインする必要Wants=があります。これにより、最初のブートが中止された場合でも、これらのユニットが次のシステム起動時に再実行されることが保証されます。

オプションがカーネルのコマンドラインで指定されている場合systemd.condition-first-boot=(ブール値を取る)、この条件チェックの結果が上書きされ、/etc/machine-id 存在チェックよりも優先されます。

答え3

起動するとすぐにロック ファイルが存在するかどうかを確認するように更新しますgenerate_env_file.sh。ロック ファイルが存在する場合は、すぐに終了します。

ロック ファイルが存在しない場合は、すぐにロック ファイルにアクセスし、構成ファイルの生成処理を実行してから、ロック ファイルを削除します。

言い換えれば、systemdあなたが説明している状況を構成を通じて処理するネイティブな方法はないと思うので、ロック ファイルを使用してください。

systemdそして、@shellter が指摘しているように、将来的にはUnix サイトの方が質問に適したサイトになります。

関連情報