システムサービスに他のサービスを再起動させる方法は?

システムサービスに他のサービスを再起動させる方法は?

アプリケーション毎日メンテナンス開始時にデータベースから読み取られます。別個のアップデータsystemd以下の単位で説明します。

application.service:

[Unit]
Description=Application reading database
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target

[Service]
User=application
Group=application
WorkingDirectory=/var/lib/application
ExecStart=/var/lib/application/application-exec --database /var/db/database.db
StandardOutput=file:/var/lib/application/application.stdout.log
StandardError=file:/var/lib/application/application.stderr.log

StartLimitInterval=60
StartLimitBurst=10
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

updater.service:

[Unit]
Description=Database updater
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target

[Service]
Type=oneshot
User=updater
Group=updater
WorkingDirectory=/var/lib/updater
ExecStart=/var/lib/updater/updater-exec --database /var/db/database.db
StandardOutput=file:/var/lib/updater/updater.stdout.log
StandardError=file:/var/lib/updater/updater.stderr.log

[Install]
WantedBy=multi-user.target

updater.timer:

[Unit]
Description=Timer for database updater

[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=900
Persistent=true

[Install]
WantedBy=timers.target

私の質問:

どうやって作れますか?アップデートサービス再起動アプリケーションサービスアップデートは正常に実行されましたか?

この問題存在するサーバー障害似ていますが、残念ながら私のユースケースに適した答えはありません。

答え1

解決策は予想よりはるかに簡単でした。次の行を追加する必要がありますupdater.service

ExecStartPost=+/usr/bin/systemctl restart application.service

結果updater.service:

[Unit]
Description=Database updater
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target

[Service]
Type=oneshot
User=updater
Group=updater
WorkingDirectory=/var/lib/updater
ExecStart=/var/lib/updater/updater-exec --database /var/db/database.db
StandardOutput=file:/var/lib/updater/updater.stdout.log
StandardError=file:/var/lib/updater/updater.stderr.log
ExecStartPost=+/usr/bin/systemctl restart application.service

[Install]
WantedBy=multi-user.target

関連抜粋man 5 systemd.service:

├───────┼────────────────────────────────────────┤
│"+"    │ If the executable path is prefixed     │
│       │ with "+" then the process is executed  │
│       │ with full privileges. In this mode     │
│       │ privilege restrictions configured with │
│       │ User=, Group=, CapabilityBoundingSet=  │
│       │ or the various file system namespacing │
│       │ options (such as PrivateDevices=,      │
│       │ PrivateTmp=) are not applied to the    │
│       │ invoked command line (but still affect │
│       │ any other ExecStart=, ExecStop=, ...   │
│       │ lines).                                │
├───────┼────────────────────────────────────────┤
ExecStartPost= commands are only run after the commands specified in ExecStart= have been invoked
successfully, as determined by Type= (i.e. the process has been started for Type=simple or Type=idle,
the last ExecStart= process exited successfully for Type=oneshot, the initial process exited
successfully for Type=forking, "READY=1" is sent for Type=notify, or the BusName= has been taken for
Type=dbus).

説明する:

  • ExecStartPost=以前の理由により、コマンドはroot権限で実行されます(最初の抜粋を参照+application.servicesystemctlUser=Group=
  • ExecStartPost=成功した場合にのみコマンドを実行しますExecStart=(2番目の抜粋を参照)。これにより、条件付き再始動が許可されます。application.service

答え2

これを調べるのは楽しかったです!

3番目のサービスを混合に追加し、次の依存関係を次のように並べ替えますrestart-application.servicerestart-applicationserviceupdater.service

  • restart-application.service始めるupdater.service
  • restart-application.serviceupdater.service完了するまで実際には実行されません。
  • restart-application.serviceupdater.service成功しないと実行されません。

私たちはrestart-application.serviceこれを次のようにします:

[Unit]
Description=Restart application
BindsTo=updater.service
After=updater.service

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart application

私たちはBindsToここに依存関係があります。文書の主な部分は次のとおりです。

BindsTo =の動作は、同じセルでAfter =と一緒に使用するとより強力になります。この場合、厳密にバインドされたユニットをアクティブにする必要があり、このユニットもアクティブになります。

次にUnit、部品をupdater.service次のように修正します。

[Unit]
Description=Database updater
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target
StopWhenUnneeded=true

そしてService含める部分は次のとおりです。

RemainAfterExit=true

この変更は、(a)updater.serviceコマンドが完了した後も「アクティブ」のままになることを意味します。これは、コマンドがアクティブな場合にのみ実行されるExecStartためです。restart-application.serviceこのオプションは、StopWhenUnneeded=true他の何も依存しない(つまり停止したとき)、restart-application.serviceデバイスが無効になることを意味します。

最後に、タイマーが代わりrestart-application.serviceに開始されるように変更する必要がありますupdater.service


application.service私は(単純なWebサーバーを実行する)ダミーとランダムにupdater.service成功または失敗するダミーを作成しました。

[Unit]
Description=Database updater
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target
StopWhenUnneeded=true

[Service]
Type=oneshot
User=updater
Group=updater
WorkingDirectory=/home/updater
ExecStart=/bin/bash -c 'rc=$(( RANDOM % 2 )); echo "rc=$rc"; exit $rc'
RemainAfterExit=true

ログを見てみましょうsystemctl start restart-application.serviceupdater.service失敗した場合はどうなりますか?

... systemd[1]: Starting updater.service - Database updater...
... bash[1253]: rc=1
... systemd[1]: updater.service: Main process exited, code=exited, status=1/FAILURE
... systemd[1]: updater.service: Failed with result 'exit-code'.
... systemd[1]: Failed to start updater.service - Database updater.
... systemd[1]: Dependency failed for restart-application.service - Restart application.
... systemd[1]: restart-application.service: Job restart-application.service/start failed with result 'dependency'.

updater.service成功すると、次のようになります。

... systemd[1]: Starting updater.service - Database updater...
... systemd[1]: Finished updater.service - Database updater.
... darkhttpd[1193]: darkhttpd/1.13, copyright (c) 2003-2021 Emil Mikulic.
... darkhttpd[1193]: listening on: http://0.0.0.0:8080/
... systemd[1]: Starting restart-application.service - Restart application...
... bash[1262]: rc=0
... systemd[1]: Stopping application.service - Application reading database...
... systemd[1]: application.service: Deactivated successfully.
... systemd[1]: Stopped application.service - Application reading database.
... systemd[1]: Started application.service - Application reading database.
... systemd[1]: restart-application.service: Deactivated successfully.
... systemd[1]: Finished restart-application.service - Restart application.
... systemd[1]: updater.service: Deactivated successfully.
... systemd[1]: Stopped updater.service - Database updater.

現在のすべての状況:

# systemctl status application.service updater.service restart-application.service
● application.service - Application reading database
     Loaded: loaded (/etc/systemd/system/application.service; disabled; vendor preset: disabled)
     Active: active (running) since Sat 2022-09-17 20:48:27 UTC; 1min 53s ago
   Main PID: 1264 (darkhttpd)
      Tasks: 1 (limit: 4661)
     Memory: 172.0K
        CPU: 1ms
     CGroup: /system.slice/application.service
             └─ 1264 /usr/sbin/darkhttpd /home/application/htdocs --port 8080

○ updater.service - Database updater
     Loaded: loaded (/etc/systemd/system/updater.service; disabled; vendor preset: disabled)
     Active: inactive (dead)

○ restart-application.service - Restart application
     Loaded: loaded (/etc/systemd/system/restart-application.service; static)
     Active: inactive (dead)

私はこれがあなたが望むすべてを行うと思います。

関連情報