Linux | systemd - 时间和定时器

2020 08 17, Mon

上一篇我们随便说了说systemd的基础的一些东西,组件啊、类型啊服务啊什么的。这篇稍微提一下systemd中的时间和定时器。

计算机中的时间

计算机是一个讲究时间的玩意儿,几乎任何程序都会涉及到什么时候去做什么,会有时刻的问题,也会有时长的问题。

要搞清楚定时任务怎么回事,我们得先搞清楚时间的问题。

挂钟计时器

挂钟计时器指的是一个本地的时间,这个时间会因为网络时间服务的调整而作细微的调整,也会因为时区变化甚至标准时钟时间的调整而变化。并不是连续增长的。一般按照日历来计算的时间都是挂钟计时器。

单调计时器

单调计时器就是我们自然中持续增长的时间。比如说我们说每天要吃饭,我们不会因为横穿时区而不吃饭,这个每天就是一个单调计时器。这种一般都是单调计时器。

定时器

systemd除了正常的资源以外,还定义了一类资源叫timer。会根据需求定时触发,可以单次可以循环。可以替代cron和at。

timer类似于service,都是systemd unit,所以Unit和Install这两段timer同样可以用。

基本的定时器: 根据挂钟计时器定时启动unit

timer最简单的用法和cron类似,就是定义一个时刻,systemd会在这个时刻启用某个资源。

举个例子,我们可以让systemd在某一个或者某一些时刻启动服务。我们的服务就是打印Happy Birthday

[Service]
ExecStart=/usr/bin/echo Happy Birthday

如果我们要在每年我的生日之时打印这个,就需要一个Timer:

[Timer]
OnCalandar=*-6-15 00:00:00 CST

如果只是要运行一次,那我们写一个具体的时间就行:

[Timer]
OnCalandar=1995-6-15 00:00:00 CST

不过这样的话,systemd不会和你说Happy Birthday。

错过了?没事,补上。

有的时候机器维护,或者出现了故障,定时任务需要在恢复后马上跑一次。怎么办呢?

有一个Persistent选项:

[Timer]
OnCalandar=*-6-15 00:00:00 CST

即使2020年6月15号机器关机,16号启动的时候,systemd还是会告诉你: Happy Birthday。

我不要按照日历

ok,没问题。timer也可以根据下面这些条件周期性启动(不带单位都是秒):

  • OnActiveSec: 相对于timer启动的时间
  • OnBootSec: 相对于计算机启动的时间
  • OnStartupSec: 相对于服务管理器启动的时间
  • OnUnitActiveSec: 相对于上次unit启动的时间
  • OnUnitInactiveSec: 相对于上次unit停止的时间

比如说

[Timer]
OnBootSec=300
OnUnitActiveSec=1w

机器启动后五分钟启动一次,然后每周启动一次。

我不想让它扎堆

有的时候服务开机扎堆跑,导致负载比较高。我想让时间随机一点。

没问题。

[Timer]
RandomizedDelaySec=10
OnCalandar=1995-6-15 00:00:00 CST

会在设置的时间前后,随机加不超过10s的一段时间。

我想临时新建并启动一个timer,在关机前有效

systemd提供了一个命令叫systemd-run,来提供生成并启动一个timer、关机前有效的能力。

比如说:

systemd-run --on-calendar='*-6-15 00:00:00 CST' echo Happy Birthday

这里有一个略微有趣的用法就是,通过systemd-run来替代at

systemd-run --on-active=30 /bin/echo Welcome!