我有一个相当烦人的系统计时器和漂移开始时间的问题。我有一个旧的 cron.d 脚本(每 10 分钟忠实执行一次),我正在尝试对其进行现代化改造。问题是它启动的服务运行时间超过 10 分钟。对于 cron,这不是问题,我只是让两个实例运行了一段时间,但 systemd 的工作方式不同。
定时器如下:
[Timer]
OnCalendar=*:0/10:0
Persistent=false
AccuracySec=1s
据我了解,这应该在 08:00:00、08:10:00、08:20:00 等精确运行。但它启动的关联服务的运行时间略长于 10 分钟,这会导致计时器每次运行逐渐漂移约 10 秒。这意味着开始时间为 08:00:00、08:10:10、08:20:20 等。有什么办法可以强制计时器完全按照我的意愿行事吗?
我还尝试让该服务在后台运行,不受监控的由 systemd 提供,但我在这方面并没有取得太大成功。尝试了诸如ExecStart=/bin/sh -c "/run/my/cmd -options &"
and with 之类的方法nohup
,并将整个命令放入单独的 shell 脚本中,但无济于事。不会cmd
立即启动或终止。
那么我怎样才能让我的 systemd 计时器像旧的 cron 脚本一样运行呢?我唯一剩下的想法/解决方法是制作两个计时器,间隔设置为 20 分钟,但这听起来是一个非常愚蠢的想法..
答案1
看起来这种类型的行为确实不受 直接支持systemd
,由于它跟踪其运行的每个服务的方式,这种行为是有道理的。我最终不得不创建两个相同的服务,每 20 分钟运行一次,而不是每 10 分钟运行一次。
相关定时器部分如下:
myservice-even.timer
[Timer]
OnCalendar=*:0/20:0
Persistent=false
AccuracySec=1s
和
myservice-奇数定时器
[Timer]
OnCalendar=*:10/20:0
Persistent=false
AccuracySec=1s
此外,我还包括了RuntimeMaxSec=900
这两项服务,这样即使它们行为不当,下一轮也会在正确的时间开始。
答案2
如果您想异步启动进程(并且独立于任何其他实例),您可以使用systemd-run
. systemd-run
创建瞬态服务或范围单元。默认情况下,它会自动为单位生成唯一的名称。
换句话说,systemd 服务 S 可以用来systemd-run
启动进程 P。 systemd-run
不会等待 P 完成(除非您使用该--wait
选项)。进程 P 不会成为服务 S 的一部分。并且当服务 S 停止时,进程 P 不会被终止。
如果您愿意,您应该能够使用像--property RuntimeMaxSec=900
with之类的选项systemd-run
。 (具体可以设置哪些属性systemd-run
略有不同。我认为旧版本的 systemd 不允许在瞬态单元上设置尽可能多的属性)。
如果您需要添加比 提供的控件更复杂的控件cron
,或者比瞬态服务单元可能提供的控件更复杂的控件,则您可能需要找到另一个具有所需功能的任务计划程序。或者编写您自己的服务来生成子进程并监视它们的状态:-)。 (你可以仍然使用 systemd 计时器来向此类服务发送消息,但我认为它看起来不太干净。如果你想让它易于理解,我认为服务本身实现计时器会更好。)