Linux 计划任务
1、计划任务简介
计划任务是指将需要定时或周期性执行的任务通过计算机程序自动执行。在 Linux 中,提供这类服务的程序通常是 crond,常常也叫 crontab。
crond 是 Linux 下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与 Windows 下的计划任务类似。通常的,crond 是 Linux 发行版自带的服务,并且设置了开机自动启动,crond 进程的最小调度单位是分钟,即每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。
2、深入了解 crontab
crond 的任务类别分为两类,系统任务和用户任务。他们对应的配置文件分别是 /etc/crontab
和 /var/spool/cron/用户名
。
先看用户任务,用户任务的配置文件在 /var/spool/cron/用户名
,其定义如下:
* | * | * | * | * | command |
---|---|---|---|---|---|
分 | 时 | 日 | 月 | 周 | 命令 |
分
- 0-59:具体的分钟
- *:每分钟
- */n:n为数值,表示每n分钟
时
- 0-23:具体的小时
- *:每小时
- */n:n为数值,表示每n小时
日
- 1-31:具体的日期
- *:每日
- */n:n为数值,表示每n天
月
- 1-12:具体的月份
- *:每月
- */n:n为数值,表示每n月
周
- 0-7:具体的周几,0和7都表示周日
- *:每周
- */n:n为数值,表示每n周
再看系统任务,其配置文件 /etc/crontab 内容:
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
从上述配置文件中,我们可以清楚的知道计划任务的格式。
除此之外,crond 还会读取 /etc/cron.d/ 目录下的所有文件,如果需要新增系统任务,在这里新建一个文件,只要遵守 crond 的语法规则编写即可。
在 /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
需要关注的是最后一行:01 * * * * root run-parts /etc/cron.hourly
,那么这一行是什么意思呢?这是 crond 的语法之一,意思是说每小时01分执行 /etc/cron.hourly
目录下的所有计划任务。
我们再看一下 /etc/cron.hourly
目录里有什么,我们发现只有一个文件 0anacron
,看一下这个文件的内容。
#!/bin/bash
# Skip excecution unless the date has changed from the previous run
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
# Skip excecution unless AC powered
if test -x /usr/bin/on_ac_power; then
/usr/bin/on_ac_power &> /dev/null
if test $? -eq 1; then
exit 0
fi
fi
/usr/sbin/anacron -s
这是一个 Shell 脚本,大意的意思是检查 /var/spool/anacron/cron.daily
的内容,当文件内容等于当前时间的值则退出,否则执行 /usr/sbin/anacron -s
。
需要注意的是/usr/sbin/anacron -s
命令执行结束后,会把当前时间写入 /var/spool/anacron/cron.daily
。
那么上述脚本的作用就是每天只会执行一次 /usr/sbin/anacron -s
。
到这里,你是不是也有疑问,到底 /usr/sbin/anacron -s
做了哪些事情呢?
anacron 介绍
想象一种场景,我们服务器有一个计划任务是每周六凌晨2点进行数据备份,但是很不巧,周六停电了,那么此计划任务就没法执行了。
如果这个任务是很重要的呢?我们希望在系统启动时能够检查没有执行成功的任务,将其执行。那么 anacron 就是这么一款软件。
在前面的分析中,我们发现其实 anacron 也是被 crond 每小时执行一次的,然后 anacron 去检查相关的计划任务有没有被执行,如果有超过期限的任务没有被执行,那么就执行它,执行完毕或没有任何执行时,anacron 就退出了。
anacron 的执行频率是以天为单位,我们可以看一下 anacron 的配置文件 /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
从上述默认配置文件上看,配置分为参数配置和任务配置。
参数配置:
- RANDOM_DELAY:在基本延时基础上,增加随机延迟,目的是为了分散任务执行时间,避免多个任务同时执行
- START_HOURS_RANGE:anacron 的执行时间范围,在这个时间范围内,anacron 才会执行任务
任务配置,分为 4 段
- 天数:anacron 执行时的时间与上一次执行时间(记录在/var/spool/anacron/cron.daily)相差的天数,若超过此天数,则开始执行,若没有超过,则不执行
- 延迟时间:若确定需要执行了,延时执行,这个数值单位为分钟
- 任务名称:没有实际意义
- 执行动作:同 crond 的定义
那么 anacron 的执行流程应该是这样,以 cron.daily 为例:
- 当前时间在不在 START_HOURS_RANGE 定义的范围内,如果在则继续,如果不在则退出
- /etc/anacrontab 分析到 cron.daily 的执行间隔为 1 天
- 从
/var/spool/anacron/cron.daily
取出上一次的执行时间 - 与当前日期对比较,相差为 1 或大于 1 时,准备执行
- 根据设置,将延时 5 分钟执行
- 延时时间过后,开始执行指令 run-parts /etc/cron.daily
- 执行完成,程序退出
最后,我们来总结一下 crond 与 anacron 的关系:
- crond 会去读取 /etc/crontab, /var/spool/cron/, /etc/cron.d/ 等配置文件,並依据『分、時、日、月、周』的时间设定执行各项任务;
- 根据 /etc/cron.d/0hourly 的配置,crond 会执行 /etc/cron.hourly/ 下的任务;
- /etc/cron.hourly/0anacron 脚本会调用 /usr/sbin/anacron -s;
- 根据 anacron 的配置文件 /etc/anacrontab 的设定,分别每天执行/etc/cron.daily、每周执行/etc/cron.weekly、每月执行/etc/cron.monthly ;
3、单次任务
Linux 还支持定义单次任务,使用 at 命令定义,依赖 atd 服务。工作中用得很少,这里就不做介绍了,有兴趣的同学可以搜索相关文章学习。