我有一个应用程序,它在启动时从数据库中读取,该数据库由单独的 updater每天更新,由以下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
我的问题:
如果更新成功执行,如何让更新服务重新启动应用服务(以便应用重新读取现在更新的数据库;成功/失败由更新的退出代码指示)?
这个关于serverfault的问题类似,但遗憾的是没有适用于我的用例的答案。
这是一个有趣的发现!
我们将向组合中添加第三个服务
restart-application.service
,然后安排和之间的依赖关系restart-applicationservice
,updater.service
这样:restart-application.service
开始updater.service
restart-application.service
直到updater.service
完成才真正运行。restart-application.service
updater.service
除非成功,否则不会运行。我们
restart-application.service
这样创建:我们在
BindsTo
这里使用依赖项。文档的关键部分是:现在我们将 的
Unit
部分修改updater.service
为如下所示:以及要包括的
Service
部分:这些更改意味着 (a)在命令完成
updater.service
后将保持“活动” ;ExecStart
我们需要这个,因为restart-application.service
只有当这个处于活动状态时才会运行。该StopWhenUnneeded=true
选项意味着当没有其他东西依赖它时(即restart-application.service
停止时),该单元将变为非活动状态。最后,我们需要修改您的计时器以启动
restart-application.service
而不是updater.service
.我创建了一个假人
application.service
(只运行一个简单的网络服务器)和一个updater.service
随机成功或失败的假人:让我们在
systemctl start restart-application.service
. 这是updater.service
失败时会发生的情况;updater.service
以下是成功时会发生的情况:此时一切的状态:
我认为这可以满足您的所有需求。
结果证明解决方案比预期的要简单得多。以下行需要添加到
updater.service
:结果
updater.service
:相关摘录
man 5 systemd.service
:解释:
ExecStartPost=
由于前面的原因,命令以 root 权限执行(+
参见第一个摘录),尽管指定和application.service
systemctl
User=
Group=
ExecStartPost=
只有在命令成功时才会执行ExecStart=
命令(参见第二个摘录),这允许有条件地重新启动application.service