在 systemd 服务中,是否可以对同一个单元(服务)同时使用 `After=` 和 `Before=` 选项?

在 systemd 服务中,是否可以对同一个单元(服务)同时使用 `After=` 和 `Before=` 选项?

单位每小时由 启动一次,但运行。单位也是。Type=oneshot这里的要求是它们的进程在运行时永远不应重叠(确保这一点),到目前为止一切都很好。现在想象一个场景,其中和一起运行超过一个小时(火灾之间的时间)。这里有两种可能性:A.serviceA.timerWants=B.serviceBefore=B.serviceB.serviceType=oneshotoneshotABA.timer

  1. A运行超过一个小时,那么虽然A.timer想要启动,并且可能确实会启动,但无论如何,A在第一个实例完成之前不会启动另一个实例,因为服务实例唯一性是 的基本原则之一systemd。我相信它只是排队而已。同样,到目前为止一切都很好,我们在这里没有运行时重叠进程的风险。
  2. A运行时间足够长,因此B,之后运行的 也运行时间足够长,总共超过一小时,结果,在 仍在运行时A.timer触发启动新进程。这就是我们遇到进程重叠的地方,因为中没有 ,因为 已经有 了。ABAfter=B.serviceA.serviceBefore=B.service

我的问题是,基本上,一开始同时使用After=B.service和是否有效?当然,它是否会像我理论上预期的那样解决第二种可能性中描述的重叠问题?还有其他方法可以解决这个问题吗(例如,我不想卷入容易出错的锁文件膨胀)?Before=B.serviceA.servicesystemd

答案1

如果你在文件中创建Before=和,则会出现错误:After=A.service

A.service: Job B.service/start deleted to break ordering cycle starting with A.service/start

因为 Systemd 不希望在同一个单元上同时拥有这两种依赖关系。我认为 Michael 提到的任何一种都不Condition...=适合man systemd.unit您要完成的任务,除非您的命令确实创建并清理了自己的文件。在我看来,您有两种主要可能的解决方案:

  1. ExecCondition=在您的单元文件中创建一个A.service运行命令以检查是否B.service正在运行的程序。这有点棘手,只能在您的单元文件中使用 ps 和 grep,因此您可能希望执行一些外部脚本,但您已经说过您想避免混乱的锁文件,所以这可能不是理想的选择。
  2. 使用你提到的你不想使用的混乱的锁文件解决方案
  3. 将第二个命令移出B.service并移入ExecStopPost=中的选项A.service。这将导致第二个命令仅在第一个命令停止后运行。它还将阻止A.service在第一个命令完全完成之前运行新命令。我相信这可以满足您的所有愿望,因为命令A.serviceB.service命令永远不会同时运行,两个A.service命令永远不会同时运行,并且新执行只会排队。

这是我用来测试选项 3 的单元文件:

[Unit]
Description = A.service for serverfault
[Service]
Type = oneshot
# A.service command
ExecStart = /usr/bin/sleep 3 
# B.service command
ExecStopPost = /usr/bin/sleep 30

然后systemctl start A.service在多个终端窗口中反复测试使用,监控在任何给定时刻实际运行的进程的进度ps

相关内容