[翻译]下一代 cron - systemd

原文地址: https://linuxhint.com/cron_systemd_timer/

cron 的问题

你是否在你的计算机上调度过任务,这似乎听起来很简单,当听到这个问题的时候第一反应想到的可能是cron,cron被设计来在特定时间执行特定的任务.cron的设计非常简单,所有有很多问题都没有考虑得到,下面介绍以下 cron存在的问题.

  1. 你使用cron添加了一个数据备份服务,每个月29日的凌晨执行数据远程备份,但是如果这一天系统正好被关闭(可能是停电或者其他问题),当系统恢复的时候以及错过了时间,那么你就错过了一次备份数据,存在数据丢失的风险.

  2. 你使用cron创建了一个任务,每隔10分钟执行一次,但是因为某些原因,你的任务需要15分钟才能执行完毕,这个时候cron 不会等待任务当前的任务执行完毕,而会重新创建一个新的任务,那么这个时候系统上存在2个任务同时运行,存在并发的问题.

system timer 怎么解决這些问题

cron能将运行记录在系统上,及时系统宕机了,下次启动后任务还能继续执行,虽然定时任务执行的最佳时间是制定的时间,但是在启动后执行总要好过不执行.要使用 timer 首先你要创建一个 service 文件加入到系统中,举例这里编写 backup.service如下

1
2
3
4
5
6
7
8
9
10
# 文件 /usr/lib/systemd/system/backup.service;
[Unit]
Description=clash
After=network.target

[Service]
ExecStart=/usr/bin/date

[Install]
WantedBy=multi-user.target

然后再编写 timer 文件

1
2
3
4
5
6
7
8
9
10
# 文件 /usr/lib/systemd/system/backup.timer
[Unit]
Description= backup evey minute

[Timer]
OnCalendar=minutely
Unit=backup.service

[Install]
WantedBy=timers.target

这里 OnCalendar 设置为每分钟执行依次,如果系统宕机了,下次重启服务了,还是会继续执行,因为执行单元是 service 所以不会存在被启动多个实例的情况.OnClendar还能设置很多其他的值

  • minutely
  • hourly
  • daily
  • monthly
  • weekly
  • yearly
  • quartly
  • semiannually

这里会存在一哥问题,daily 是什么执行呢?实际上它总是在凌晨00:00的时候执行,也许这个时候是任务执行高峰期,这里建议如果有需要的话配置RandomizeDelaySec选项。如果想要更加精细的控制任务时间可以配置一个准确的日期如:2020-08-26 12:49:37,但是要明确一点,这个任务知会被执行一次,以后就不会再次被出发执行了。如果你希望能够返回被触发执行可以用*来设置日期

1
OnClendar=*-*-* 03:00:00

上面这个例子用*-*-*替代年月日了,也就意味着在每年每月每日的 03:00:00 任务都会被触发执行,下面这个例子来设置每年的特定执行

1
OnClendar=*-12-25 03:00:00

我们也可以在最后加上 UTC 来表示不要使用本地时间,使用 UTC 时间来代替

1
OnClendar=daily UTC

上面说到了RandomizeDelaySec来设置一个任务延迟的最大时间,它的单位是:秒.

1
RandomizedDelaySec=900

最多延迟 15 分钟

Peristent选项允许记录执行的历史,这样保证服务器宕机重启以后任务还能继续执行

1
Peristet=true

OnBootSec选项能设置任务在系统启动后面触发任务,它和OnCalendar不冲突,只要满足2者之一都能触发任务执行.

1
OnBootSec=180

系统启动以后3分钟执行

默认情况下,timer添加到系统是被禁止的,如果需要开始,则需要执行

1
sudo systemctl enable --noew  xxx.timer

如果修改了 timer 或者 service 也需要通告 systemd 重新加载他们

1
sudo systemctl daemon-reload