centos7 下的默认的定时任务由 cron (crond) 这个系统服务来控制的,我们常用的crontab 就是相对应的方便我们管理配置定时任务的客户端工具。crond服务会默认每分钟去检测是否有需要执行的定时任务,所以crond不能守护秒级定时任务。

crond

服务状态

centos7最小化安装也会附带,并且默认为开机自启动,可以通过systemctl管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装
yum install -y cronie

# 查看状态
systemctl status crond

# 启动
systemctl start crond

# 停用
systemclt stop crond

# 关闭开机自启

systemctl disable crond

配置文件

在/etc目录下有好几个crond相关的配置文件或目录,分别代表:

  • cron.daily    是每天执行一次的 job

  • cron.weekly  是每个星期执行一次的 job

  • cron.monthly 是每月执行一次的 job

  • cron.hourly   是每个小时执行一次的 job

  • cron.d       是系统自动定期需要做的任务

  • cron.deny    文件就是用于控制不让哪些用户使用 crontab 的功能

  • crontab      是设定定时任务执行文件

另外通过crontab编辑的定时任务,保存到了/var/spool/cron目录下。

这些配置文件其实很少用到,至少我本人还没有碰到场景去操作这些文件,因此仅做了解,重点还是在crontab。

日志

crond日志保存在/var/log/cron

crontab

参数

-u user:用来设定某个用户的 crontab 服务,例如,“-u ixdba” 表示设定 ixdba 用户的 crontab 服务,此参数一般有 root 用户来运行。

file:file 是命令文件的名字, 表示将 file 做为 crontab 的任务列表文件并载入 crontab。如果在命令行中没有指定这个文件,crontab 命令将接受标准输入(键盘)上键入的命令,并将它们载入 crontab。

-e:编辑某个用户的 crontab 文件内容。如果不指定用户,则表示编辑当前用户的 crontab 文件。

-l:显示某个用户的 crontab 文件内容,如果不指定用户,则表示显示当前用户的 crontab 文件内容。

-r:从 / var/spool/cron 目录中删除某个用户的 crontab 文件,如果不指定用户,则默认删除当前用户的 crontab 文件。

-i:在删除用户的 crontab 文件时给确认提示。

规则

查看/etc/crontab,这里面其实已经介绍了最基本的规则,忘记的时候可以看这个文件。

1
2
3
4
5
6
7
8
9
10
# 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
# | | | | |
# * * * * * command to be executed
分 时 日 月 周 需要执行的命令

在以上各个字段中,还可以使用以下特殊字符:

星号(*):代表所有可能的值,例如 month 字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。这里有个容易错的点,如果写成类似* */1 * * *并不是一小时执行一次,而是一分钟。

逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”

中杠(-):可以用整数之间的中杠表示一个整数范围,例如 “2-6” 表示“2,3,4,5,6”

正斜线(/):可以用正斜线指定时间的间隔频率,例如 “0-23/2” 表示每两小时执行一次。同时正斜线可以和星号一起使用,例如 */10,如果用在 minute 字段,表示每十分钟执行一次。

crontab 规范

  1. 加上# 注释说明一下这条定时任务的作用,有些定时任务比较复杂,或者是通过执行脚本方式运行,时间久了特别容易忘记这条任务的作用,不方便维护。
  2. 在末尾加上>/dev/null 2>&1,如果定时任务规范结尾不加 >/dev/null 2>&1,很容易导致硬盘inode空间被占满,从而系统服务不正常。这点存疑,本人经常没加,好像
  3. 执行的命令(若使用脚本),在前面加上/bin/sh(它是/bin/bash的软链接),这样脚本就可以不加执行权限了。
  4. 执行的命令(若使用脚本),指定脚本得指定其绝对路径。 00 02 * * 5 /bin/sh /tmp/a.sh

示例

有个很棒的网站可以验证我们写的crontab规则
https://www.matools.com/crontab

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# 每天,每30分钟执行一次  mycrontab 脚本
*/30 * * * root /usr/local/mycrontab.sh

# 每天凌晨三点,执行脚本
# 由于第一个的分钟没有设置,所以每天凌晨3点的每分钟都执行一次脚本
* 3 * * * root /usr/local/mycrontab.sh

# 这样就是每天凌晨三点整执行一次脚本
00 3 * * * root /usr/local/mycrontab.sh

# 每天11点到13点之间,每10分钟执行一次脚本
*/10 11-13 * * * root /usr/local/mycrontab.sh

# 每小时的10-30分钟,每分钟执行一次脚本,共执行20次
10-30 * * * * root /usr/local/mycrontab.sh

# 每小时的10,30分钟,分别执行一次脚本,共执行2次
10,30 * * * * * root /usr/local/mycrontab.sh

# 每天早上6点
0 6 * * * echo "Good morning." >> /tmp/test.txt //注意单纯echo,从屏幕上看不到任何输出,因为cron把任何输出都email到root的信箱了。

# 每两个小时
0 */2 * * * echo "Have a break now." >> /tmp/test.txt

# 晚上11点到早上8点之间每两个小时和早上八点
0 23-7/2,8 * * * echo "Have a good dream" >> /tmp/test.txt

# 每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
0 11 4 * 1-3 command line

# 1月1日早上4点
0 4 1 1 * command line SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root //如果出现错误,或者有数据输出,数据作为邮件发给这个帐号 HOME=/

# 每小时执行/etc/cron.hourly内的脚本
01 * * * * root run-parts /etc/cron.hourly

# 每天执行/etc/cron.daily内的脚本
02 4 * * * root run-parts /etc/cron.daily

# 每星期执行/etc/cron.weekly内的脚本
22 4 * * 0 root run-parts /etc/cron.weekly

# 每月去执行/etc/cron.monthly内的脚本
42 4 1 * * root run-parts /etc/cron.monthly

# 注意: "run-parts"这个参数了,如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是文件夹名。  

# 每天的下午4点、5点、6点的5 min、15 min、25 min、35 min、45 min、55 min时执行命令。
5,15,25,35,45,55 16,17,18 * * * command

# 每周一,三,五的下午3:00系统进入维护状态,重新启动系统。
00 15 * * 1,3,5 shutdown -r +5

# 每小时的10分,40分执行用户目录下的innd/bbslin这个指令:
10,40 * * * * innd/bbslink

# 每小时的1分执行用户目录下的bin/account这个指令:
1 * * * * bin/account

# 每天早晨三点二十分执行用户目录下如下所示的两个指令(每个指令以;分隔):
20 3 * * * (/bin/rm -f expire.ls logins.bad;bin/expire$#@62;expire.1st)  

# 每年的一月和四月,4号到9号的3点12分和3点55分执行/bin/rm -f expire.1st这个指令,并把结果添加在mm.txt这个文件之后(mm.txt文件位于用户自己的目录位置)。
12,55 3 4-9 1,4 * /bin/rm -f expire.1st$#@62;$#@62;mm.txt

# 每月1、 10、22日的4 : 45重启nginx。
45 4 1,10,22 * * /etc/init.d/nginx restart

# 每周六、周日的1 : 10重启nginx。
10 1 * * 6,0 /etc/init.d/nginx restart

# 每天18 : 00至23 : 00之间每隔30分钟重启nginx。
0,30 18-23 * * * /etc/init.d/nginx restart

# 每星期六的11 : 00 pm重启nginx。
0 23 * * 6 /etc/init.d/nginx restart

# 每一小时重启nginx
* */1 * * * /etc/init.d/nginx restart

# 晚上11点到早上7点之间,每 隔一小时重启nginx
* 23-7/1 * * * /etc/init.d/nginx restart

# 每月的4号与每周一到周三 的11点重启nginx
0 11 4 * mon-wed /etc/init.d/nginx restart

# 一月一号的4点重启nginx
0 4 1 jan * /etc/init.d/nginx restart

# 每半小时同步一下时间
*/30 * * * * /usr/sbin/ntpdate 210.72.145.20