at / cron - Linux定时任务计划

  • 原创
  • Madman
  • /
  • 2018-05-16 09:07
  • /
  • 0
  • 304 次阅读

Linux定时任务计划-min.png

Synopsis: at通常用于执行一次性定时任务,batch命令会在CPU的工作负载小于0.8的时候,才执行设定的定时任务计划。crond用于周期性执行定时任务,使用crontab命令设置用户级别的定时任务,系统级的任务计划直接编辑/etc/crontab配置文件,注意多了一个用户名的字段,而且不能省略它。自己开发的程序要定时执行,建议在/etc/cron.d/目录下增加配置文件。如果系统在本来要执行定时任务的时间段内关机了,重新开机后,这些任务不会被执行,anacron可以解决这个问题,实现一定会定期内执行任务,把命令或脚本(不是按分钟、小时、日、月、周那样的任务格式哦)直接放到/etc/cron.daily等目录下即可(如果任务是非精确时间,也可以放在这些目录下),像CentOS预设的定时任务都放在/etc/cron.daily目录下

1. at

在类Unix 操作系统上,at命令用于在当前系统时间后的某个时刻,仅执行某个命令一次。更确切的说,at命令从标准输入读取一系列命令,把它们收集成一个计划任务,在此后的某个时刻执行。这个任务仍使用当前的环境,并在与计划制定时相同的工作目录和环境变量里执行。所以,在指定计划任务时,建议使用绝对路径来指明命令和文件!

CentOS系统使用守护进程atd在后台定期检查任务列表(任务存放在/var/spool/at/目录内),以在计划的时刻执行at命令的任务;atq命令列出当前队列里的任务(或者at -l),atrm命令从队列里删除任务(或者at -d)。

1. 查看at命令
[root@CentOS ~]# type at
at is /usr/bin/at
[root@CentOS ~]# rpm -qf /usr/bin/at
at-3.1.13-22.el7_4.2.x86_64

2. 管理atd守护进程
[root@CentOS ~]# systemctl status atd    # 查看atd进程是否运行
● atd.service - Job spooling tools
   Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2018-05-10 14:24:42 CST; 4 days ago
 Main PID: 699 (atd)
   CGroup: /system.slice/atd.service
           └─699 /usr/sbin/atd -f

May 10 14:24:42 docker systemd[1]: Started Job spooling tools.
May 10 14:24:42 docker systemd[1]: Starting Job spooling tools...

[root@CentOS ~]# systemctl restart atd  # 重启atd进程
[root@CentOS ~]# systemctl enable atd   # 设置atd进程开机启动
[root@CentOS ~]# systemctl enable atd   # 停止atd进程

1.1 权限控制

为了系统安全,不信任的用户不要允许他们使用at命令,否则可能被黑客利用,定期使用at命令在服务器上执行木马程序,然后上报给黑客。

可以利用/etc/at.allow/etc/at.deny来进行权限控制:

  • /etc/at.allow: 白名单,只有写入这个文件中的用户才能使用at命令,每个用户一行
  • /etc/at.deny: 黑名单,如果用户被存在于这个文件中,则他不能使用at命令

默认情况下,CentOS中的at程序包会创建空的/etc/at.deny,即如果你想禁止哪个用户使用at命令,就把他的用户名写入此文件。如果以上两个文件均不存在,则只有root用户可以使用at命令。

1.2 创建一个单次执行的定时任务

使用at命令关键在于设定时间的格式

1. 在今天的某时刻执行,如果此时刻已经过去了,则推迟到明天的这个时刻执行。格式为HH:MM[am|pm]
[root@CentOS ~]# date
Tue May 15 14:15:49 CST 2018
[root@CentOS ~]# at 20:15
at> /usr/bin/free -m
at> <EOT>  # 命令输入完后,按Ctrl + D结束输入,屏幕显示<EOT>
job 6 at Tue May 15 20:15:00 2018  # 定时任务的编号为6

2. 指定某一天的某时刻执行。格式为HH:MM[am|pm] YYYY-MM-DD,或者HH:MM[am|pm]  [Month] [Date]
[root@CentOS ~]# at 08pm 2018-06-01
at> /usr/bin/who     
at> <EOT>
job 7 at Fri Jun  1 20:00:00 2018

[root@CentOS ~]# at 06am July 10
at> /usr/bin/w
at> <EOT>
job 10 at Tue Jul 10 06:00:00 2018

3. 从某时刻之后推移多久时间后执行。格式为HH:MM[am|pm] + number [minutes|hours|days|weeks]
[root@CentOS ~]# who
root     pts/0        2018-05-15 13:58 (172.17.1.80)
[root@CentOS ~]# at now + 3 minutes
at> /usr/bin/echo "Test at schedule tasks" > /dev/pts/0  # 打印到当前虚拟终端
at> <EOT>
job 12 at Tue May 15 14:31:00 2018

设置好的定时任务可以在/var/spool/at/目录中找到,at命令每分钟检查一次此目录,如果当前时刻有符合条件的定时任务就执行它。

注意: at命令和下面要介绍的crontab命令,它们的最小单位都是分钟,每分钟检查一次,即整分(秒数为0的时候)

1.3 管理at任务

1. 查看at任务列表
[root@CentOS ~]# atq
6   Tue May 15 20:15:00 2018 a root
7   Fri Jun  1 20:00:00 2018 a root
或者:
[root@CentOS ~]# at -l

2. 查看某任务的详情
[root@CentOS ~]# at -c 6  # 指定任务编号

3. 删除某任务
[root@CentOS ~]# atrm 6   # 指定任务编号

2. batch

当系统比较繁忙时,如果此时还要执行at设定的定时任务的话,频繁的进程切换将导致系统的负载变得更高。此时,使用batch命令将会是个更好的选择,batch命令会在CPU的工作负载小于0.8的时候(关注最近1分钟的平均工作负载),才执行设定的定时任务计划。

batch命令也是由at程序包提供,只不过它加入一些控制参数来实现只CPU空闲时才执行定时任务:

[root@CentOS ~]# type batch
batch is hashed (/usr/bin/batch)
[root@CentOS ~]# rpm -qf /usr/bin/batch
at-3.1.13-22.el7_4.2.x86_64

模拟系统高负载时,看看batch命令何时执行定时任务:

1. 查看当前系统负载,显示很空闲
[root@CentOS ~]# uptime
 15:01:33 up 5 days, 37 min,  1 user,  load average: 0.00, 0.01, 0.05

2. 模拟高负载
[root@CentOS ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[1] 12741
[root@CentOS ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[2] 12743
[root@CentOS ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[3] 12745
[root@CentOS ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[4] 12747

[root@CentOS ~]# uptime
 15:03:08 up 5 days, 38 min,  1 user,  load average: 3.10, 1.01, 0.39

3. 设置定时任务,更新locate的查找索引数据库
[root@CentOS ~]# batch
at> /usr/bin/updatedb
at> <EOT>
job 13 at Tue May 15 15:04:00 2018

4. 此时已经超过定时任务原来要执行的时刻15:04:00,但是却没执行at的任务
[root@CentOS ~]# date; atq
Tue May 15 15:05:08 CST 2018
13  Tue May 15 15:04:00 2018 b root

5. 终止后台进程,让系统负载变低
[root@CentOS ~]# jobs
[1]   Running                 echo "scale=100000; 4*a(1)" | bc -lq &
[2]   Running                 echo "scale=100000; 4*a(1)" | bc -lq &
[3]-  Running                 echo "scale=100000; 4*a(1)" | bc -lq &
[4]+  Running                 echo "scale=100000; 4*a(1)" | bc -lq &
[root@CentOS ~]# kill -9 %1 %2 %3 %4

6. 当系统负载低于0.8后,at任务就自动执行完成
[root@CentOS ~]# uptime; atq
 15:10:10 up 5 days, 45 min,  1 user,  load average: 0.05, 0.92, 0.72

3. cron

相对于at命令只执行一次定时任务,周期性执行定时任务则由cron(crond)这个系统服务来控制(比如每个小时、每天、每个星期一或每年的某一天执行)。cron是类Unix 操作系统中,一个在后台运行的系统服务,它每分钟扫描一次计划任务,并在发现任务时执行它们。

cron在不同的Linux发行版上有不同的实现程序,CentOS中默认使用cronie程序包,还有其它的实现版本,如fcronbcrondcron等:

[root@CentOS ~]# type crond
crond is /usr/sbin/crond
[root@CentOS ~]# rpm -qf /usr/sbin/crond
cronie-1.4.11-17.el7.x86_64
[root@CentOS ~]# rpm -ql cronie-1.4.11-17.el7.x86_64
/etc/cron.d
/etc/cron.d/0hourly
/etc/cron.deny
/etc/pam.d/crond
/etc/sysconfig/crond
/usr/bin/crontab
/usr/lib/systemd/system/crond.service
/usr/sbin/crond
/usr/share/doc/cronie-1.4.11
/usr/share/doc/cronie-1.4.11/AUTHORS
/usr/share/doc/cronie-1.4.11/COPYING
/usr/share/doc/cronie-1.4.11/ChangeLog
/usr/share/doc/cronie-1.4.11/INSTALL
/usr/share/doc/cronie-1.4.11/README
/usr/share/man/man1/crontab.1.gz
/usr/share/man/man5/crontab.5.gz
/usr/share/man/man8/cron.8.gz
/usr/share/man/man8/crond.8.gz
/var/spool/cron

Linux系统本身就有很多需要周期性、定时执行的任务,所以cron(crond)系统服务默认是开机启动的:

[root@CentOS ~]# systemctl status crond
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2018-05-10 14:24:41 CST; 5 days ago
 Main PID: 692 (crond)
   CGroup: /system.slice/crond.service
           └─692 /usr/sbin/crond -n

May 10 14:24:41 docker systemd[1]: Started Command Scheduler.
May 10 14:24:41 docker systemd[1]: Starting Command Scheduler...
May 10 14:24:41 docker crond[692]: (CRON) INFO (Syslog will be used instead of sendmail.)
May 10 14:24:41 docker crond[692]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 62% if used.)
May 10 14:24:42 docker crond[692]: (CRON) INFO (running with inotify support)

另外,用户也可能要设置周期性定时任务计划,所以cronie程序包还提供了crontab命令给用户设置定时任务。

3.1 配置文件的位置

crond默认每分钟去以下文件或目录中扫描计划任务:

  • /etc/crontab: 建议将重要的系统任务计划写入此配置文件,方便管理与追踪。注意: 分钟、小时、日、月、周、用户名、执行的命令或脚本,共7个字段,必须包含执行命令或脚本的用户名,否则是语法错误,crond会报错ERROR (getpwnam() failed)
  • /etc/cron.d/*: 如果自己开发的程序需要定时执行,请在此目录下面创建与程序名关联的配置文件,并写入任务计划。注意:也是分钟、小时、日、月、周、用户名、执行的命令或脚本7个字段,必须包含执行命令或脚本的用户名
  • /var/spool/cron/*: 如果用户要设置定时任务,可以使用crontab命令添加任务,执行完命令后,会在/var/spool/cron/目录下创建一个跟用户名同名的文件,定时任务就写在这里面了。注意: 只有分钟、小时、日、月、周、执行的命令或脚本共6个字段

注意: /etc/crontab配置文件由crontabs程序包创建

[root@CentOS ~]# rpm -qa|grep -i 'cron'
cronie-1.4.11-17.el7.x86_64
crontabs-1.11-6.20121102git.el7.noarch
cronie-anacron-1.4.11-17.el7.x86_64
[root@CentOS ~]# rpm -ql crontabs-1.11-6.20121102git.el7.noarch
/etc/cron.daily
/etc/cron.hourly
/etc/cron.monthly
/etc/cron.weekly
/etc/crontab
/etc/sysconfig/run-parts
/usr/bin/run-parts
/usr/share/man/man4/crontabs.4.gz
/usr/share/man/man4/run-parts.4.gz

/etc/cron.daily//etc/cron.hourly//etc/cron.monthly//etc/cron.weekly/目录将在后面anacron章节说明!

3.2 权限控制

为了限制普通用户使用crontab命令来设置定时任务,可以利用/etc/cron.allow/etc/cron.deny来进行权限控制:

  • /etc/cron.allow: 白名单,只有写入这个文件中的用户才能使用crontab命令,每个用户一行
  • /etc/cron.deny: 黑名单,如果用户被存在于这个文件中,则他不能使用crontab命令

默认情况下,CentOS中的cronie程序包会创建空的/etc/cron.deny,即如果你想禁止哪个用户使用crontab命令,就把他的用户名写入此文件。当两个文件都存在时,以白名单为准。如果以上两个文件均不存在,则只有root用户可以使用crontab命令。一般系统中只有黑名单文件,因为每个用户所执行的定时任务都与他自身的用户权限有关。

1. 注意s标志位
[root@CentOS ~]# ls -al /usr/bin/crontab
-rwsr-xr-x 1 root root 57576 Aug  3  2017 /usr/bin/crontab

2. 此目录只有root用户有写权限
[root@CentOS ~]# ls -ald /var/spool/cron/
drwx------. 2 root root 31 May 15 15:57 /var/spool/cron/

注意crontab命令的权限有SUID标志,当普通用户运行crontab时将临时(run-time)获取与此程序属主(即root)等同的权限,程序结束时失效,所以普通用户能够在/var/spool/cron/目录下创建包含定时任务的配置文件!

SGID可以阅读 http://www.madmalls.com/blog/post/property-management-on-linux/#41-suid

cron执行的每一个定时任务都会记录到/var/log/cron日志文件中,一般用来查看Linux系统是否被植入了木马。

3.3 定时任务的设置格式

/etc/crontab配置文件和/etc/cron.d/*目录下的配置文件中设置定时任务的格式见下图:

cron

每一个定时任务在配置文件中保存为一行,各字段从左至右依次表示分钟小时日期月份周几(0和7都代表星期天)用户名要执行的命令或脚本,每个字段的取值见上图。注意: 月份和周几可以使用三个英文字母缩写

/var/spool/cron/*目录下用户使用crontab -e命令生成的配置文件中,设置定时任务的格式见下图(注意: 少了一个用户名的字段):

linux-cron-jobs-crontab

详细用法请阅读man 5 crontab

(1) 特殊字符

各字段值除了使用单个数字或缩写外,还可以使用以下字符表示特殊的含义:

  • *: 表示该字段任何时刻都符合
  • ,: 表示分割时段,如5 1,3 * * * commond表示每天的1:05和3:05执行后面的命令
  • -: 表示一个时间段,如0 1-5 * * * commond表示每天的1点至5点的0分都执行后面的命令
  • /: 表示每隔多久时间,如23 0-20/2 * * *表示从0点到20点每隔2小时的23分钟时执行后面的命令,即0:23、2:23 ... 18:23、20:23

(2) 特殊单词

前5个字段可以用一个特殊的单词来替代,它们的含义如下:

  • @reboot: 表示仅在系统启动时执行一次
  • @yearly: 表示每年1月1号0点0分只执行一次,等同于0 0 1 1 *
  • @annually: 等同于@yearly
  • @monthly: 表示每月1号0点0分执行,等同于0 0 1 * *
  • @weekly: 表示每周的星期天0点0分执行,等同于0 0 * * 0
  • @daily: 表示每天的0点0分执行,等同于0 0 * * *
  • @midnight: 等同于@daily
  • @hourly: 表示每小时0分执行,等同于0 * * * *

(3) 示例

1. 每周星期天的04:05执行脚本
5 4 * * sun /usr/local/sbin/backup.sh
或者:
5 4 * * 0 /usr/local/sbin/backup.sh
或者
5 4 * * 7 /usr/local/sbin/backup.sh

2. 每2个月的1号的00:00和12:00执行脚本
0 0,12 1 */2 * /usr/local/sbin/backup.sh

3. 每月的8号至14号的04:00执行脚本
0 4 8-14 * * /usr/local/sbin/backup.sh

4. 每5分钟执行脚本
*/5 * * * * /usr/local/sbin/backup.sh

5. 每月的1号和15号,还包括星期三,的00:00执行脚本。注意:如果同时指定每月的日期和周几,是都包含的意思。不要错误的理解为"每月的1号和15号且这两天必须是星期三"的意思
0 0 1,15 * 3 /usr/local/sbin/backup.sh

6. 每个星期天的00:00执行脚本
@weekly /usr/local/sbin/backup.sh

7. 每个周一至周五的下午3点的每一分钟都执行一次脚本,共60次,这是错误的写法
* 15 * * 1-5 /usr/local/sbin/backup.sh

更多示例可以访问 crontab.guru ,或者网页版帮你生成cron命令 Crontab Generator

3.4 查看cron定时任务是否执行

[root@CentOS ~]# tail -f /var/log/cron

3.5 crontab命令管理用户级定时任务

(1) 添加定时任务

[root@CentOS ~]# crontab -e

默认使用vi编辑器(可以修改EDITOR环境变量来更换其它编辑器),每一行表示一个定时任务。可以使用#添加注释。

(2) 查看定时任务列表

[root@CentOS ~]# crontab -l

为了防止用户不小心清空任务列表,可以先备份:

[wangy@CentOS ~]$ crontab -l > $HOME/cron.data

然后通过此文件重新导入定时任务列表:

[wangy@CentOS ~]$ crontab -r         # 不小心清空了任务列表
[wangy@CentOS ~]$ crontab -l
no crontab for wangy
[wangy@CentOS ~]$ crontab cron.data  # 重新导入
[wangy@CentOS ~]$ crontab -l
*/1 * * * * /usr/bin/whoami

(3) 清空所有定时任务列表

[root@CentOS ~]# crontab -r

(4) 删除指定定时任务

使用crontab -e,再删除指定行即可

注意: crontab命令还可以指定-u选项,后面跟其它用户名,这样就可以管理其它用户的定时任务

[root@CentOS ~]# crontab -u wangy -e
[root@CentOS ~]# crontab -u wangy -l
[root@CentOS ~]# crontab -u wangy -r

3.6 /etc/crontab设置系统级定时任务

crontab -e是针对使用者的cron来设计的,要添加系统级定时任务(比如定时重启系统),直接编辑/etc/crontab配置文件即可。

[root@CentOS ~]# ls -al /etc/crontab
-rw-r--r--. 1 root root 451 Jun 10  2014 /etc/crontab
[root@CentOS ~]# cat /etc/crontab 
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# 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

需要说明的是,SHELL表示使用哪个shell,默认是bash,比如你也可以使用fishPATH表示如果定时任务中的命令或脚本没使用绝对路径时,将到这些位置去查找;MAILTO表示执行完定时任务后给谁发送邮件。

定时任务的设定格式多了一个执行命令或脚本的用户身份字段,比如系统预设的定时任务就是以root的身份来执行的,不能省略用户名,否则是语法错误,该任务将不会被执行!

[root@CentOS ~]# vi /etc/crontab
# 每周六的03:00查找有SUID或SGID特殊权限位的文件,并把结果输出到/tmp/uidgid.files中
0 3 * * 6 root find / -perm /6000 > /tmp/uidgid.files

3.7 总结

(1) 添加注释

为每一行的定时任务前面添加注释信息,说明它的功能、运行时间

[root@CentOS ~]# crontab -l
# At 22:00 on every day-of-week from Monday through Friday.
0 22 * * 1-5 /usr/local/sbin/backup.sh

# At minute 23 past every 2nd hour from 0 through 20.
23 0-20/2 * * * /usr/bin/free -m

(2) 使用绝对路径

任务中的命令或脚本等文件,建议使用绝对路径

0 0 23 * * * /usr/bin/find /var/log/csp -mtime +7 -exec rm {} \;

(3) 注意环境变量

先手动测试一次执行任务是否成功,如果手动执行没有问题,但cron却没正确执行,那么请检查环境变量

1. 手动没问题但cron不执行,可以直接引入环境变量
0 */2 * * * . /etc/profile; /bin/sh /usr/local/sbin/backup.sh

2. 或者在脚本中引入环境变量
[root@CentOS ~]# cat /usr/local/sbin/backup.sh

内容如下
#!/bin/sh
source /etc/profile
export HOST='localhost'
export USER='root'
export PASSWORD='passw0rd'
export DB='aossdb'
/usr/bin/mysqldump -h$HOST -u$USER -p$PASSWORD $DB > $HOME/backup.sql

(4) 要对%进行转义

%有特殊含义,表示换行,所以像要定时执行date '+%Y-%m-%d'时,要对%进行转义

1. 如果不对%转义,cron执行任务时报错,可以查看/var/log/cron
[root@CentOS ~]# crontab -l
*/1 * * * * /usr/bin/date '+%Y-%m-%d'

[root@CentOS ~]# grep 'unexpected' /var/log/cron
May 16 11:24:01 CentOS CROND[1680]: (root) CMDOUT (/bin/sh: -c: line 0: unexpected EOF while looking for matching `'')
May 16 11:24:01 CentOS CROND[1680]: (root) CMDOUT (/bin/sh: -c: line 1: syntax error: unexpected end of file)

2. 对%转义后,cron可以正确执行
[root@CentOS ~]# crontab -l
*/1 * * * * /usr/bin/date '+\%Y-\%m-\%d'

[root@CentOS ~]# tail -f /var/log/cron
May 16 11:26:01 CentOS CROND[1702]: (root) CMD (/usr/bin/date '+%Y-%m-%d')
May 16 11:26:01 CentOS CROND[1700]: (root) CMDOUT (2018-05-16)

(5) 清理不必要的日志

每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户,这样日积月累,日志信息会非常大,可能会影响系统的正常运行,因此,将每条任务进行重定向处理非常重要。 例如,可以在crontab文件中设置如下形式,忽略日志输出(也不给用户发送邮件):

59 23 * * * /usr/local/csp-agent/log_clear.sh > /dev/null 2>&1

4. anacron

atcrontab都是定时执行任务计划,并假定系统在那个时刻是运行的。假如不巧应该执行任务计划的时刻系统是关机的,那么之后系统开机了,这个任务将不会执行,也就没有达到预期的效果。比如,一般服务器在凌晨进行数据库备份,如果周末断电了,这个任务计划将不会执行,而备份又很重要,anacron定期执行,系统重新开机后,它会分析当前时间和/var/spool/anacron/*目录下的文件记录的上次运行anacron的时间,如果发现两者有差异,它就会主动帮你执行那些时间到了却没有执行的任务计划。

Step1: crond守护进程每分钟会读取/etc/cron.d/*目录下的配置文件,其中0hourly的内容跟/etc/crontab很像,这个定时任务是root用户在每小时的01分钟时去执行run-parts /etc/cron.hourly。而run-parts其实是一个shell脚本,它会在大约5分钟内的某时刻执行/etc/cron.hourly/目录下的所有脚本

[root@CentOS ~]# 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

[root@CentOS ~]# type run-parts
run-parts is /usr/bin/run-parts
[root@CentOS ~]# file /usr/bin/run-parts
/usr/bin/run-parts: Bourne-Again shell script, ASCII text executable
[root@CentOS ~]# cat /usr/bin/run-parts

Step2: 执行/etc/cron.hourly/0anacron脚本,脚本很简单,第一部分判断/var/spool/anacron/cron.daily记录的时间与当前时间是否一致,如果一致说明没有因系统关机导致漏掉的任务计划,直接退出脚本。如果时间不一致,执行/usr/sbin/anacron -s

[root@CentOS ~]# ls -l /etc/cron.hourly/
total 4
-rwxr-xr-x 1 root root 392 Aug  3  2017 0anacron
[root@CentOS ~]# 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

# 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

Step3: anacron -s会顺序执行漏掉的任务计划,首先读取它的配置文件/etc/anacrontab

[root@CentOS ~]# 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

[root@CentOS ~]# more /var/spool/anacron/*
::::::::::::::
/var/spool/anacron/cron.daily
::::::::::::::
20180516
::::::::::::::
/var/spool/anacron/cron.monthly
::::::::::::::
20180418
::::::::::::::
/var/spool/anacron/cron.weekly
::::::::::::::
20180516

[root@CentOS ~]# ls -l /etc/cron.daily /etc/cron.monthly /etc/cron.weekly
/etc/cron.daily:
total 16
-rwxr-xr-x. 1 root root 2239 Jun 10  2014 certwatch
-rwx------  1 root root  219 Aug  2  2017 logrotate
-rwxr-xr-x. 1 root root  618 Mar 18  2014 man-db.cron
-rwx------. 1 root root  208 Nov  5  2016 mlocate

/etc/cron.monthly:
total 0

/etc/cron.weekly:
total 0

1 5 cron.daily nice run-parts /etc/cron.daily中第一个字段表示如果当前时间与/var/spool/anacron/cron.daily记录的时间相差超过1天(包含1天),就延迟5分钟 + START_HOURS_RANGE设置的小时数后,执行/etc/cron.daily目录下的命令或脚本。其它两行类似,只不过是按超过7天或1个月就执行相应目录下的命令或脚本。

如果你将每个星期天要执行的任务计划放在/etc/crontab文件中的话,只要那个时刻系统没有运行,这个任务就过期了,开机后也不会重新被执行。但如果把要执行的命令或脚本放在/etc/cron.weekly/目录下的话,那么该任务会被定期,且在一周内被执行一次,如果你关机时间超过一周,在重新开机后的数小时内,anacron会主动执行这个任务。

所以,你会发现/etc/crontab配置文件和/etc/cron.d/目录下都没有关于mlocate(更新整个系统文件的索引数据库)的定时任务,但是系统每天都在更新/var/lib/mlocate/mlocate.db索引数据库,原因就在于anacron会执行/etc/cron.daily/mlocate

注意: 如果你的任务不是要在精确的时间点执行,可以把要执行的命令或脚本(不是crontab格式的配置文件哦)放到/etc/cron.hourly/etc/cron.daily/etc/cron.daily/etc/cron.monthly目录下,也可以达到按每小时、每天、每周、每月各执行一次的目的!

分类: Linux
标签: anacron at batch cron crontab
未经允许不得转载: LIFE & SHARE - 王颜公子 » at / cron - Linux定时任务计划

分享

作者

作者头像

Madman

如果博文内容有误或其它任何问题,欢迎留言评论,我会尽快回复; 或者通过QQ、微信等联系我

0 条评论

暂时还没有评论.

发表评论前请先登录