我一直在奋斗两天编写一些应该很简单的东西:一个一次性的 systemd 服务,它在计算机关闭之前运行并与已安装的文件系统交互。
(我已经在 RAM 中安装了“~/.mozilla”目录,并且我试图在计算机关闭时将更改保存到硬盘上。)
我已经尝试了阳光下的一切,但没有任何效果。这是我最好的尝试:
[Unit]
Description=Save Firefox and Thunderbird to the hard drive
DefaultDependencies=no
BindsTo=home-andy-.mozilla.mount
After=home-andy-.mozilla.mount
Before=halt.target poweroff.target reboot.target shutdown.target
Conflicts=umount.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/mozilla-save
TimeoutStartSec=infinity
[Install]
WantedBy=halt.target poweroff.target reboot.target shutdown.target
以下是我添加每个声明的原因的解释:
[Unit]
Before=halt.target poweroff.target reboot.target shutdown.target
[Install]
WantedBy=halt.target poweroff.target reboot.target shutdown.target
我添加这个是因为我的脚本应该在计算机关闭时运行。我不清楚其中任何一项是否会暗示所有其他项,或者是否必须全部指定。我也不清楚“之前”声明是否绝对必要,因为“[安装]”部分似乎已经包含该信息。
我也尝试过涉及“umount.target”的变体
[Unit]
DefaultDependencies=no
[Service]
TimeoutStartSec=infinity
这应该是为了防止我可能长时间运行的进程在几分钟后被积极的关闭进程杀死。
[Unit]
BindsTo=home-andy-.mozilla.mount
After=home-andy-.mozilla.mount
Conflicts=umount.target
我添加这个是因为我的进程依赖于 tmpfs 文件系统(安装在“/home/andy/.mozilla”)。当我的进程启动时必须安装该文件系统并且必须保持安装状态直到我的过程完成。关闭过程并行运行许多操作,包括卸载文件系统。
为了其他人的利益:如果您在“/etc/fstab”文件中声明了一个挂载点,那么它将自动可供 systemd 使用。以下是列出您可能需要的各种安装点的方法:
systemctl list-units --type=mount
这就是我现在的处境。我在这上面花了几天时间,我已经筋疲力尽了。我厌倦了 systemd,需要帮助。任何东西,即使是面包屑,都会受到赞赏。
郑重声明:在“/lib/systemd/system-shutdown/mozilla-save”安装脚本将不起作用,因为此时文件系统已重新挂载为只读。
这也行不通:
Unit]
Description=Save Firefox and Thunderbird to the hard drive
BindsTo=home-andy-.mozilla.mount home.mount
After=home-andy-.mozilla.mount home.mount
Conflicts=umount.target
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/usr/local/sbin/mozilla-stop
[Install]
WantedBy=multi-user.target
……虽然我不知道为什么。
答案1
这是一项有效的服务:
[Unit]
Description=Save Firefox and Thunderbird to the hard drive
RequiresMountsFor=/home /home/andy/.mozilla
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/usr/local/sbin/mozilla-save
TimeoutSec=infinity
[Install]
WantedBy=multi-user.target
为了检查竞争条件,我在备份脚本的开头添加了 300 秒的睡眠。关闭过程延迟了 300 秒,然后备份脚本成功运行。
这终于是一个可以工作的配置了。我希望这个解决方案对其他人有帮助。
这是我对为什么会起作用的猜测:
我相信
[Service]
Type=oneshot
ExecStart=/bin/true
[Install]
WantedBy=multi-user.target
...导致“/bin/true”在多用户运行级别的一开始就执行。
这本身没有任何作用。但声明:
[Service]
RemainAfterExit=true
...导致 systemd 认为“/bin/true”是仍在运行在多用户运行级别结束时(即在关闭之前拆除所有内容)。
此时,systemd 调用 ExecStop 来终止“/bin/true”进程:
ExecStop=/usr/local/sbin/mozilla-save
...运行我的备份脚本反而。
现在,通常情况下,systemd 会终止长时间运行的 ExecStop 进程,因此有必要为备份脚本提供足够的时间来完成:
TimeoutSec=infinity
并且 systemd 会同时关闭所有其他内容,因此这对于在备份过程中保持文件系统已挂载和可写是必要的:
[Unit]
RequiresMountsFor=/home /home/andy/.mozilla
这是一个简洁易读的描述系统和单元文件在数字海洋上。这是完整的技术文档如果你需要的话。
请注意:如果您对服务的“[安装]”部分进行更改,您将必须将更改通知 systemctl。我就是这样做的:
systemctl disable mozilla-save
systemctl enable mozilla-save
...其中“/lib/systemd/system/mozilla 保存.service”是我的服务的名称。
这些命令将导致符号链接被添加或删除。如果您不调用这些命令,您的测试就没有意义。