# 可唤醒停机期间的工作任务
考虑一个场景:你有一个定时任务,每周星期天凌晨 2 点 ,执行一次,但是很不幸,这个时间点停电了,等你上班周 1 去开机时,这个定时任务句错过了执行时机。
这种情况下,需要靠 anacron 指令:主动帮你进行时间到了但却没有执行的定时任务
# 什么是 anacron
anacron:主动帮你进行时间到了但却没有执行的定时任务,不是来替代 crond 的
anacron 其实是前面谈到过的,每小时被 crond 执行一次,会去检测相关定时任务是否有执行,由于 anacron 预设以 每天、每周、每个月去检查未进行的 crontab 任务,因此对于某些特殊的使用环境非常有帮助
比如:你的主机,是共用的,周末 2 天没有人使用,需要关机,但是有一些任务在周日早上执行,而又关机了,那么重新开机的时候,就可以利用 anacron 的功能,执行没有执行的任务。
anacron 读取的时间记录文件(timestamps),分析现在的时间记录文件所记载的上次执行 anacron 的时间,两者比较后若发现有差异,那就是在某些时刻没有进行 crontab,此时就会开始执行未进行的 crontab 任务
简要说:anacron 的原理是,依赖每小时的执行一次的任务记录下时间,下一次执行时,对比当前时间的差异,如果中间有缺少执行,那么表示 crontab 任务在这期间没有被执行过(笔者有疑问就是,一小时,那么怎么知道每小时的 5 分钟到 59 分这个时间点的任务是否被执行过了呢?)
# anacron 与 /etc/anacrontab
anacron 不是一个服务,是一个程序,每小时被主动执行一次,所以 anacron 的配置文件放置在 /etc/cron.hourly/
目录中的
[root@study ~]# cat /etc/cron.hourly/
0anacron mcelog.cron
[root@study ~]# cat /etc/cron.hourly/0anacron
#!/bin/sh
# Check whether 0anacron was run today already
if test -r /var/spool/anacron/cron.daily; then
day=`cat /var/spool/anacron/cron.daily`
fi
if [ `date +%Y%m%d` = "$day" ]; then
exit 0;
fi
# 上面校验前一次执行 anacron 时间的时间戳
# Do not run jobs when on battery power
if test -x /usr/bin/on_ac_power; then
/usr/bin/on_ac_power >/dev/null 2>&1
if test $? -eq 1; then
exit 0
fi
fi
/usr/sbin/anacron -s
# 经过了一些判断,然后执行了 anacron -s 指令
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
anacron [-sfn] [job]..
anacron -u [job]...
选项与参数:
-s:开始一连续的执行各项工作 job,会依据时间记录文件的数据判断是否进行
-f:强制进行,而不去判断时间记录文件的时间戳
-n:like进行未进行的任务,而不言辞(delay)等待时间
-u:仅更新时间记录文件的时间戳,不进行任何工作
job:由 /etc/anacrontab 定义的各项工作名称
2
3
4
5
6
7
8
9
在 CentOS 中,anacron 每小时都会执行一次,为了担心 anacron 误判时间参数,因此 /etc/cron.hourly/
中的 anacron 文件名前加了一个 0(0anacron)
,让 anacron 最先执行。
[root@study ~]# cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45 # 随机给予最大延迟时间,单位是分钟
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22 # 延迟多少个小时内应该要执行的任务时间
# 天数 延迟时间 工作名称定义 实际要执行的指令串
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@study ~]# more /var/spool/anacron/*
::::::::::::::
/var/spool/anacron/cron.daily
::::::::::::::
20200308
::::::::::::::
/var/spool/anacron/cron.monthly
::::::::::::::
20200212
::::::::::::::
/var/spool/anacron/cron.weekly
::::::::::::::
20200308
# 上面则是三个工作名称的时间记录文件以及记录的时间戳
2
3
4
5
6
7
8
9
10
11
12
13
14
15
以 /etc/cron.daily
的设置来说明:
- 天数:anacron 执行当前与时间戳(
/var/spool/anacron
内时间记录文件)相差的天数,若超过此天数,就准备开始执行,若没有超过此天数,则不执行后续的指令 - 延迟时间:若确定超过天数导致要执行任务了,那么延迟执行的时间,因为担心立即启动会有其他资源冲突的问题
- 工作名称定义:无意义,只在
/var/log/cron
里记录的名称,通常与后续的目录资源名相同 - 实际要进行的指令串:与 0hourly 很细,通过 run-parts 来处理的
根据上面的配置文件内容,大概知道 anacron 的执行流程应该如下(以 cron.daily 为例):
- 由
/etc/anacrontab
分析到 cron.daily 这项工作名称的天数为 1 天 - 由
/var/spool/anacron/cron.daily
取出最仅一次执行 anacron 的时间戳 - 又上个步骤与目前的时间比较,若相差 1 天以上(含 1 天),就准备进行指令
- 若准备进行指令,根据
/etc/anacrontab
的设置,将延迟 5 分钟 + 3 小时(看 START_HOURS_RANGE 的设置) - 延迟时间后,开始执行后续指令,即
run-parts /etc/cron.daily
指令 - 执行完毕后,anacron 程序结束
这也是为什么你的系统开机后,一小时左右会有一段时间忙碌,就是因为在执行上述的配置任务
# 总结:crond 与 anacron 的关系
- crond 会主动读取
/etc/crontab、/var/spool/cron/*、/etc/cron.d/*
等配置文件,并依据设置的时间去执行任务 - 根据
/etc/cron.d/0hourly
的配置,主动去/etc/cron.hourly/
目录下,执行所有在该目录下的执行文件 - 因为
/etc/cron.houly/0anacron
脚本文件的缘故,主动的每小时执行 anacron,并调用/etc/anacrontab
的配置文件 - 根据
/etc/anacrontab
的配置,每天、每周、每月去分析/etc/cron.daily、/etc/cron.weekly、/etc/cron.monthly
内的执行文件,进行固定周期所执行的指令
也就是说,如果你每个周日所需要执行的配置是放置在 /etc/crontab
中的话,那么该动作只要过期了就过期了,而放在 /etc/cron.weekly
目录下,那么该工作就会定期,每周执行一次的频率,如果你关机超过一周,那么开机后的数个小时内,该工作就会主动的被执行
← 循环执行的例行性工作排程 重点回顾 →