0. 概述
在之前我介绍过 Linux 下的 Crontab 配置的语法:Crontab使用教程,但是这是简单地介绍一下如何配置以及如何定位问题之类的,这篇文章我将着重地介绍关于 Crontab 的各种配置是什么意思,以及如何被加载的。
1. cron vs anacron
在我用的系统(Arch 系)中,运行着一个 crond,例如:
[[email protected]]# systemctl status cronie
● cronie.service - Periodic Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/cronie.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2020-08-03 20:19:37 HKT; 1h 43min ago
Main PID: 709 (crond)
Tasks: 1 (limit: 13364)
Memory: 1.9M
CGroup: /system.slice/cronie.service
└─709 /usr/bin/crond -n
但是,当你看 crond 的 man 文档的时候,你会发现有这么一段:
Cron also searches for /etc/anacrontab and any files in the /etc/cron.d directory, which have a different format (see crontab(5))
然而看 man 5 crontab
文档也没看出 anacron 是什么,所以直接看 man anacron
会更简单一些。其实他们之间的联系很简单:
- anacron 只运行每天/周/月的任务
- 如果一项任务在预定的时间机器处于关机状态,那么在下次开机的时候会执行;
- anacron 自己没有守护进程运行,需要依赖于外部工具(例如 crond);
- 可以设置一个延时时间,当到指定时间时,等待一个延时时间再执行任务;
- crond:以分为单位执行定期任务
- 到点准时执行,没有等待时间
- 如果关机了,关机期间的定时任务不会执行
- 自己有守护进程(crond)进行定时处理
2. crond 读取的目录
根据文档显示,crond 会读取几个位置的配置文件,分别是:
/etc/crontab
:一个文件,以前用来执行每日/周/月的任务,现在被 anacron 取代;/etc/cron.d
:一个目录,存储了不同用户的定期任务;/var/spool/cron
:存储用户用crontab
命令编辑的任务。
3. anacron 如何被执行
看上面 anacron 的配置文件似乎不在 crond 的读取目录中,那么 anacron 的任务又是如何被执行的呢?于是我就跟踪了一下,发现这么一条调用链路:
[[email protected]]# cat /etc/cron.d/0hourly
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
01 * * * * root run-parts /etc/cron.hourly
[[email protected]]# ll /etc/cron.hourly
总用量 24
drwxr-xr-x 2 root root 4096 3月 11 22:30 .
drwxr-xr-x 104 root root 12288 8月 3 22:23 ..
-rwxr-xr-x 1 root root 580 11月 1 2019 0anacron
然后再来看下 /etc/cron.hourly/0anacron
的任务详情:
[[email protected]]# cat /etc/cron.hourly/0anacron
# 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
... ...
这一段是这个,那么可以发现,anacrontab 将执行任务的上一次时间记录在了文件:/var/spool/anacron/cron.daily
中,执行的第一件事就是确认一下今天有没有运行,如果运行了,因为最小执行单位是天,所以就不用检查了,直接跳过。(那么问题来了,如果新增了每日任务,今天就不会执行了?)
第二段代码就是:Do not run jobs when on battery power,检测是否运行在电池工作的状态,如果是,那么也不执行。
第三段代码就一句:/usr/sbin/anacron -s
,看一下文档的意思:Serializes execution of jobs. Anacron does not start a new job before the previous one finished.
,那么整条链路也就串起来了。