跳转至

当文件系统卸载时如何停止 Systemd 服务

文章背景与核心概要

在 Linux 系统管理中,确保服务在其所需的文件系统消失时能够优雅地关闭是一个常见的挑战。虽然 RequiresMountsFor= 是标准做法,但它在处理手动卸载和动态挂载时存在明显的局限性。本指南深入探讨了使用 Requires=BindsTo= 的区别与细微之处,从而在 systemd 中实现可靠的服务依赖管理。

通过本文,您将了解如何针对不同的挂载场景(如静态 /etc/fstab 挂载与动态挂载)选择正确的配置指令,以确保文件系统一旦卸载,相关的系统服务能够立即停止,从而保障系统的数据一致性和服务的安全性。


The Basic Approach: RequiresMountsFor=

The most straightforward method to link a service to a filesystem is using the RequiresMountsFor= directive. This automatically adds Requires= and After= dependencies to the corresponding systemd.mount unit.

基本方法:RequiresMountsFor=

将服务链接到文件系统的最直接方法是使用 RequiresMountsFor= 指令。这会自动向对应的 systemd.mount 单元添加 Requires=After= 依赖关系。

Limitations: * Manual Unmounts: It only triggers a service stop if the mount unit is explicitly stopped via systemctl stop <fs>.mount. It does not react to standard umount commands. * Dynamic Mounts: It fails if the filesystem is mounted on-the-fly by another service (e.g., ZFS) rather than being defined in /etc/fstab or a dedicated .mount unit.

局限性: * 手动卸载: 只有通过 systemctl stop <fs>.mount 显式停止挂载单元时,它才会触发服务停止。它对标准的 umount 命令没有反应。 * 动态挂载: 如果文件系统是由另一个服务(例如 ZFS)动态挂载的,而不是在 /etc/fstab 或专用的 .mount 单元中定义,它将失效。


Handling Missing Filesystems

If you use ConditionPathExists= in your service file, the service will refuse to start if the target directory is missing. However, if the filesystem is managed by another service, you must ensure your service includes an After= directive pointing to that mounting service to ensure the correct startup order.

处理缺失的文件系统

如果您在服务文件中使用了 ConditionPathExists=,当目标目录不存在时,服务将拒绝启动。但是,如果该文件系统是由另一个服务管理的,您必须确保服务中包含指向该挂载服务的 After= 指令,以保证正确的启动顺序。

Note that systemd does not support "triggering" (automatically starting a service once a mount appears). To ensure your service starts on boot, you generally need a formal /etc/fstab entry or a dedicated .mount unit.

请注意,systemd 不支持“触发”(即一旦出现挂载就自动启动服务)。为确保您的服务在引导时启动,通常需要一个正式的 /etc/fstab 条目或专用的 .mount 单元。


The Robust Solution: BindsTo=

If your goal is to ensure the service stops immediately when a filesystem is unmounted—even if that unmount happens outside of systemd (e.g., via a manual umount command)—you must use BindsTo= instead of Requires=.

稳健的解决方案:BindsTo=

如果您的目标是确保文件系统卸载时服务立即停止——即使该卸载操作发生在 systemd 之外(例如通过手动的 umount 命令)——您必须使用 BindsTo= 代替 Requires=

  • How it works: BindsTo= creates a much stronger dependency than Requires=. If the target unit (the .mount unit) becomes inactive, the service bound to it will be stopped automatically.
  • Requirements: For this to be most effective, you should still have an /etc/fstab entry or a .mount unit defined.
  • Caveat for Dynamic Mounts: If you use BindsTo= with a filesystem that lacks a formal .mount unit, the service will not start automatically. You will need to manually orchestrate the startup sequence to ensure the service only launches after the filesystem and its associated unit are present.

  • 工作原理: BindsTo= 创建了比 Requires= 更强的依赖关系。如果目标单元(.mount 单元)变为非活动状态,与其绑定的服务将自动停止。

  • 要求: 为了达到最佳效果,您仍然需要定义一个 /etc/fstab 条目或 .mount 单元。
  • 动态挂载的注意事项: 如果将 BindsTo= 用于缺少正式 .mount 单元的文件系统,服务将不会自动启动。您需要手动编排启动顺序,以确保服务仅在文件系统及其关联单元就绪后才启动。

Conclusion

While RequiresMountsFor= is sufficient for basic dependency management, BindsTo= is the necessary tool for scenarios where service integrity depends strictly on the presence of a mounted filesystem. When using BindsTo=, be prepared to handle the startup orchestration manually if your filesystem is not defined in standard system configuration files.

结论

虽然 RequiresMountsFor= 对于基本的依赖管理已经足够,但对于服务完整性严格依赖于挂载文件系统存在的场景,BindsTo= 是必不可少的工具。当使用 BindsTo= 时,如果您的文件系统未在标准系统配置文件中定义,请准备好手动处理启动编排。