如何使用 systemd 在关机时运行命令?

如何使用 systemd 在关机时运行命令?

我在每台机器上都有一个本地 postgresql。我想在关机时运行维护脚本,这样用户可以单击“关闭”并在机器进行维护时离开,然后在完成后真正关机。

该脚本必须在 postgresql.service 停止之前运行。

我还想显示一条关机消息,通知用户将进行维护。

我曾尝试创建一项服务:

[Unit]
Description=PostgreSQL Maintenance
Requires=postgresql.service
Before=shutdown.target

[Service]
User=postgres
WorkingDirectory=/opt/postgres
ExecStart=/bin/true
ExecStop=/opt/postgres/run-maintenance.sh

[Install]
WantedBy=multi-user.target

和:

[Unit]
Description=PostgreSQL Maintenance
Requires=postgresql.service

[Service]
Type=oneshot
User=postgres
WorkingDirectory=/opt/postgres
ExecStart=/opt/postgres/run-maintenance.sh

[Install]
WantedBy=halt.target shutdown.target

它们不工作。

维护脚本是:

#!/usr/bin/env bash

plymouth display-message --text="Maintenance Message"
psql -d db -f /opt/postgres/maintenance.sql

维护.sql

reindex (verbose) database db;
vacuum (full, analyze, verbose);

我发现了很多类似的问题,但没有找到明确的解决方案。

答案1

这对我有用:

[Unit]
Description=PostgreSql Maintenance.
After=postgresql.service

[Service]
Type=oneshot
User=postgres
WorkingDirectory=/opt/postgres
ExecStart=/opt/postgres/run-maintenance.sh
TimeoutSec=3600

[Install]
WantedBy=shutdown.target halt.target

答案2

这是一个在关闭前执行任务的简单服务的示例。请注意,该选项禁用了默认依赖项DefaultDependencies=no(我猜省略此配置是您的 oneshot 单元文件无法正常工作的主要原因)。正如其他评论所指出的那样,最好RemainAfterExit=yes也提供此选项。我也同意评论中对超时的担忧。

[Unit]
Description=SleepBeforeShutdown Service
DefaultDependencies=no
Before=halt.target shutdown.target reboot.target

[Service]
Type=oneshot
ExecStart=/bin/sleep 30
RemainAfterExit=yes

[Install]
WantedBy=halt.target shutdown.target reboot.target

编辑服务单元文件后,运行 systemctl enable yourservice.service并重启。此后,每次运行关机、停机或重启时,type-oneshot 服务都会先执行其操作,然后系统才会进行实际关机/重启。

编辑
我现在找到了以前的邮政那里提供了相同的解决方案。我没有资格发表评论并附上上述问题的链接,所以我将保留我的答案(尽管严格来说,这是重复的)(版主,如果违反规则,请删除此帖子)

编辑2
还有另一个老邮政答案是一样的。

答案3

您的第一次尝试接近正确。我的建议是使用带有ExecStop=命令的单元在系统关闭时运行,因为这是最可靠的方法,而且很容易获得正确的顺序。

一个重点是使用Type=oneshotRemainAfterExit=yes,这可确保您的单元将“启动”并保持该状态,直到系统关闭。一旦系统开始关闭,它将把您的单元视为要停止的单元之一,并将ExecStop=在其上执行命令。

至于依赖项,您可以根据启动单元来设置它们,因此您可以说明单元启动时需要启动的所有项。当系统停机时,依赖项将按相反顺序停止,因此如果您希望 PostgreSQL 在单元停止时启动,则需要依赖After=它。

你不需要任何对关机等的依赖,因为这就像一个正常的单元(在启动时启动,或者在系统运行时手动启动,在关机时停止,全部其他单位也停止了。)

综合起来:

[单元]
描述=PostgreSQL 维护
之后=postgresql.service

[服务]
类型=oneshot
退出后继续保留=是
用户=postgres
工作目录=/opt/postgres
ExecStart=/bin/true
ExecStop=/opt/postgres/run-maintenance.sh
超时时间=3600

[安装]
WantedBy=多用户.目标

相关内容