![如何使用 systemd 在关机时运行命令?](https://linux22.com/image/1066741/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20systemd%20%E5%9C%A8%E5%85%B3%E6%9C%BA%E6%97%B6%E8%BF%90%E8%A1%8C%E5%91%BD%E4%BB%A4%EF%BC%9F.png)
我在每台机器上都有一个本地 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=oneshot
和RemainAfterExit=yes
,这可确保您的单元将“启动”并保持该状态,直到系统关闭。一旦系统开始关闭,它将把您的单元视为要停止的单元之一,并将ExecStop=
在其上执行命令。
至于依赖项,您可以根据启动单元来设置它们,因此您可以说明单元启动时需要启动的所有项。当系统停机时,依赖项将按相反顺序停止,因此如果您希望 PostgreSQL 在单元停止时启动,则需要依赖After=
它。
你不需要任何对关机等的依赖,因为这就像一个正常的单元(在启动时启动,或者在系统运行时手动启动,在关机时停止,全部其他单位也停止了。)
综合起来:
[单元] 描述=PostgreSQL 维护 之后=postgresql.service [服务] 类型=oneshot 退出后继续保留=是 用户=postgres 工作目录=/opt/postgres ExecStart=/bin/true ExecStop=/opt/postgres/run-maintenance.sh 超时时间=3600 [安装] WantedBy=多用户.目标