在关闭电源之前,在完成所有其他操作之后运行脚本

在关闭电源之前,在完成所有其他操作之后运行脚本

如何配置 systemd 在断电处理结束时运行脚本(二十多年前,这被称为“断电运行级别”)?该脚本应该是计算机关闭之前运行的最后一件事。理想情况下,如果系统要重新启动,则不应运行该脚本。

我尝试过Before=shutdown.target,但这会导致脚本在关闭开始时运行。

我知道,在关闭电源之前的最后一点,系统非常接近关闭,以至于实际上无法使用:不再有安装的文件系统,没有网络,也没有其他服务。

内核似乎在关闭旋转硬盘时出现问题。当系统断电时,我听到磁盘头正在缩回(不安全断电)。 SMART“断电缩回计数”属性正在增加。我知道有一个解决方案,但尚未发布。所以我想使用该 hdparm -Y /dev/sda命令作为解决方法。

所以我想我需要在卸载根文件系统之前运行脚本,但在所有其他磁盘 I/O 活动(包括同步)完成之后运行。

答案1

所以我想我需要在卸载根文件系统之前运行脚本,但在所有其他磁盘 I/O 活动(包括同步)完成之后运行。

这可能行不通,因为卸载文件系统,即使是同步的文件系统,仍然会导致 I/O,并且只会再次唤醒磁盘。 (我不确定 systemd 是否会进行单独的同步 - 我相信它只是让 umount 调用处理这个问题,因为 umount 总是意味着完全同步/刷新。)

使用 systemd,此时您可以通过将自定义脚本放入其中来运行它们/usr/lib/systemd/system-shutdown/(如systemd 关闭(8)),但只要它们从同一磁盘运行,它们很可能不会达到您想要的效果。

使用 systemd 所谓的“shutdown initramfs”可能会更好:
如果您/run/initramfs在关闭之前准备好目录(例如使用属于 shutdown.target 一部分的服务),那么 systemd 将返回到内存中的 /run 文件系统,这将然后能够完全卸载旧的根文件系统,并且然后它可以在触发实际断电之前要求 HDD 停止旋转。

(Arch Linux 的 mkinitcpio 有一个mkinitcpio-generate-shutdown-ramfs.service可以用作示例;我相信 Dracut 现在也支持这个。)

相关内容