[翻译]下一代 cron - systemd
原文地址: https://linuxhint.com/cron_systemd_timer/
cron 的问题
你是否在你的计算机上调度过任务,这似乎听起来很简单,当听到这个问题的时候第一反应想到的可能是cron
,cron
被设计来在特定时间执行特定的任务.cron
的设计非常简单,所有有很多问题都没有考虑得到,下面介绍以下 cron
存在的问题.
-
你使用
cron
添加了一个数据备份服务,每个月29日的凌晨执行数据远程备份,但是如果这一天系统正好被关闭(可能是停电或者其他问题),当系统恢复的时候以及错过了时间,那么你就错过了一次备份数据,存在数据丢失的风险. -
你使用
cron
创建了一个任务,每隔10分钟执行一次,但是因为某些原因,你的任务需要15分钟才能执行完毕,这个时候cron 不会等待任务当前的任务执行完毕,而会重新创建一个新的任务,那么这个时候系统上存在2个任务同时运行,存在并发的问题.
system timer 怎么解决這些问题
cron
能将运行记录在系统上,及时系统宕机了,下次启动后任务还能继续执行,虽然定时任务执行的最佳时间是制定的时间,但是在启动后执行总要好过不执行.要使用 timer 首先你要创建一个 service 文件加入到系统中,举例这里编写 backup.service如下
# 文件 /usr/lib/systemd/system/backup.service;
[Unit]
Description=clash
After=network.target
[Service]
ExecStart=/usr/bin/date
[Install]
WantedBy=multi-user.target
然后再编写 timer 文件
# 文件 /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,但是要明确一点,这个任务知会被执行一次,以后就不会再次被出发执行了。如果你希望能够返回被触发执行可以用*
来设置日期
OnClendar=*-*-* 03:00:00
上面这个例子用*-*-*
替代年月日了,也就意味着在每年每月每日的 03:00:00 任务都会被触发执行,下面这个例子来设置每年的特定执行
OnClendar=*-12-25 03:00:00
我们也可以在最后加上 UTC 来表示不要使用本地时间,使用 UTC 时间来代替
OnClendar=daily UTC
上面说到了RandomizeDelaySec
来设置一个任务延迟的最大时间,它的单位是:秒.
RandomizedDelaySec=900
最多延迟 15 分钟
Peristent
选项允许记录执行的历史,这样保证服务器宕机重启以后任务还能继续执行
Peristet=true
OnBootSec
选项能设置任务在系统启动后面触发任务,它和OnCalendar
不冲突,只要满足2者之一都能触发任务执行.
OnBootSec=180
系统启动以后3分钟执行
默认情况下,timer添加到系统是被禁止的,如果需要开始,则需要执行
sudo systemctl enable --noew xxx.timer
如果修改了 timer 或者 service 也需要通告 systemd 重新加载他们
sudo systemctl daemon-reload