crontab
2012-06-01 11:25:27 阿炯

cron来源于希腊单词chronos(意为“时间”),是linux系统下一个自动执行指定任务的程序。例如想在每天晚间创建某些文件或文件夹的备份,就可以用cron来自动执行。

基本格式 :
*  *  *  *  *  command 
分 时 日 月 周 命令 
第1列表示分钟0~59 每分钟用*或者 */1表示 
第2列表示小时0~23(0表示0点) 
第3列表示日期1~31 
第4列表示月份1~12 
第5列标识号星期0~7(0和7都代表星期天) 
第6列要运行的命令,多条命令用分号隔开,用括号括起来;run-parts定义后面是一个目录,后面必须写目录路径,代表运行此目录里的所有脚本

可以使用的特殊符号有
* (星号)  代表所有时间都接受:每分钟,每小时,每天,每月,每周
, (逗号)  代表同一个分类可以有多少个值,即分隔时间
- (减号)  代表在这个时段内执行,即时间段
/n  代表每n个时间就执行一次

用途
提交、编辑、列出或除去 cron 作业。 

语法
crontab [ -e [UserName] | -l [UserName] | -r [UserName] | -v [UserName] | File ]

crontab命令的语法格式如下: 
crontab [-u user] file 
crontab [-u user]{-l -r -e}
第一种格式用于安装一个新的crontab 文件,安装所指的文件,如果使用“-”符号作为文件名,那就意味着使用标准输入作为安装来源。 
-u 如果使用该选项,也就是指定了是哪个具体用户的crontab 文件将被修改。如果不指定该选项,crontab 将默认是操作者本人的crontab,也就是执行该crontab 命令的用户的crontab 文件将被修改。但是请注意,如果使用了su命令再使用crontab 命令很可能就会出现混乱的情况。所以如果是使用了su命令,最好使用-u选项来指定究竟是哪个用户的crontab文件。 
-l 在标准输出上显示当前的crontab。 
-r 删除当前的crontab文件。 
-e 使用VISUAL或者EDITOR环境变量所指的编辑器编辑当前的crontab文件。当结束编辑离开时,编辑后的文件将自动安装。 

crontab -l:查看自己的时间任务
crontab -l -u root:查看root用户的时间任务
crontab -e -u root:编辑root用户的时间任务
crontab -r:删除当前用户所有时间任务
crontab -i:删除前要求确认
/etc/cron.allow:允许使用crond的普通用户名,有此文件不用考虑cron.deny
/etc/cron.deny:拒绝使用crond的普通用户名


描述
这个 crontab 命令提交、编辑、列出或除去 cron 作业。一个 cron 作业是一个命令,其运行是由 cron 守护程序在规则的调度间隔执行的。要提交一个 cron 作业,指定 crontab 命令用 -e 标志。crontab 命令调用一个编辑会话,允许创建一个 crontab 文件。在这个文件中,为每个 cron 创建条目。每个条目必须是一种 cron 守护程序可接受的格式。要得到创建条目的信息,参阅 crontab 文件条目格式。

当创建完条目和退出文件后,crontab 命令将它复制到 /var/spool/cron/crontabs 目录,并把它放到一个文件中,此文件的名称是当前的用户名。如果以用户名命名的文件已存在于 crontabs 目录中,crontab 命令会覆盖它。同样的,可以通过指定文件参数创建 crontab 文件。如果此文件已经存在,格式必须是 cron 守护程序所需要的。如果文件不存在,crontab 命令就调用编辑器。如果 EDITOR 环境变量存在,此命令就调用它指定的编辑器。否则 crontab 命令调用 vi 编辑器。

要列出 crontab 文件的内容,就指定 crontab 命令并采用 -l 标志。要除去存在的文件,采用 -r 标志。可选的 UserName 参数可被 crontab 文件的所有者或者 root 用户来使用,为指定的用户编辑、列出、除去或验证 cron 作业的状态。如果 UserName 是无效的,就会产生错误消息并退出程序。如果可选的 UserName 参数没有被指定,这个 crontab 标志对于 root 用户和当前用户可用。

安全性
只有 root 用户和 crontab 文件的所有者可以在 -e、-l、-r 和 -v 标志后面使用 UserName 以编辑、列出、除去或验证指定用户的 crontab 文件。

cron 守护程序
这个 cron 守护程序运行的命令和 crontab 文件条目是相对应的。如果不重新定向 cron 作业的输出为标准输出或标准错误,cron 守护程序就会通过电子邮件告知您任何命令输出或错误。如果在 crontab 文件中指定了不正确的 cron 作业,这个 cron 守护程序不运行这个作业。cron 守护程序只在 cron 守护程序被初始化时检查 crontab 文件,当用 crontab 命令改变 crontab 文件时,指示变化的消息被发送到 cron 守护程序。这消除了在规则的调度间隔检查新的或改变的文件的开销。

关于/etc/crontab
# m h dom mon dow user command
17 * * * * root    cd / && run-parts --report /etc/cron.hourly //每小时执行/etc/cron.hourly内的脚本
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) //每天执行/etc/cron.daily内的脚本
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) //每星期执行/etc/cron.weekly内的脚本
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) //每月去执行/etc/cron.monthly内的脚本

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

控制使用 crontab 命令
/var/adm/cron/cron.allow 和 /var/adm/cron/cron.deny 文件控制哪一个用户可以使用 crontab 命令。root 用户可以创建、编辑或删除这些文件。这些文件中的条目是用户登录名,每行一个名称。如果登录标识和多个的登录名称相关联,这个 crontab 命令采用第一个在 /etc/passwd 文件中的登录名称,而不管当前实际使用哪一个登录名称。而且要允许用户启动 cron 作业,应该使用 chuser 命令将 /etc/security/user 文件中的守护程序属性设置为 TRUE。以下关于 cron.allow 文件的一个示例:
root
freeoa

如果 cron.allow 文件存在,只有在文件中出现其登录名称的用户可以使用 crontab 命令。root 用户的登录名必须出现在 cron.allow 文件中,如果这个文件存在的话。系统管理员可以明确的停止一个用户,通过使用 crontab 命令,同时在 cron.deny 文件中列出用户的登录名。如果只有 cron.deny 文件存在,任一名称没有出现在这个文件中的用户可以使用 crontab 命令。

如果以下一个条件成立,用户将不能使用 crontab 命令:
cron.allow 文件和 cron.deny 文件不存在(只允许 root 用户)。
cron.allow 文件存在,但用户的登录名并不列在其中。
cron.deny 文件存在,并且用户的登录名列在其中。
如果 cron.allow 和 cron.deny 文件都不存在,只有被 root 用户授权的人可以用 crontab 命令提交一个作业。

crontab 文件条目格式
一个 crontab 文件包含每个 cron 作业的条目。条目由换行字符分开。每个 crontab 文件条目包括 6 个字段,它们被空格或制表符以以下格式分开:
minute  hour  day_of_month  month  weekday  command
这些字段接收以下值:
minute
0 到 59
hour
0 到 23
day_of_month
1 到 31
month
1 到 12
weekday
0 到 6(星期日到星期六)
command
shell 命令

minute分钟,取值范围0-59
hour小时,取值范围0-23
day of month日,取值范围1-31
month月,取值范围1-12,或者使用英文缩写jan,feb,mar,apr ...
day of week星期,取值范围0-6,0或7表示星期日,或者使用英文缩写sun,mon,tue,wed,thu,fri,sat
user-name执行该定时任务的用户
command具体执行的命令,可以是一个简单的命令,也可以是一个脚本,或者是一个目录。如果是一个目录,则表示执行目录中的所有脚本,目录的前面必须加上run-parts。


必须为每个字段指定一个值。除了 command 字段,这些字段可以包含以下内容:
指定范围内的一个数。要在 5 月运行一个命令,在 month 字段指定 5。
两个被破折号分开的数目表明了包含的范围。要从星期二到星期五运行 cron 作业,把 2-5 放到 weekday 字段中。
由逗号隔开的数字列表。要在一月第一天和最后一天的运行命令,在 day_of_month 字段中可指定 1,31。
由两个被破折号分开的数字组成的组合表明了包含的范围,可与由逗号格开的数字列表一起使用。 要在一月的第 10 天到第 16 天和最后一天首次运行命令,应该在 day_of_month 字段中指定 1,10-16,31。以上两点也可用在组合中。
*(星号),意味着所有的允许值。要每个小时运行一个作业,在小时字段指定一个星号。

总结如下:
1)星号(*)表示取值范围内的所有值。例如,*在hour的位置,表示每小时执行一次。

2)连字符(-)表示一个范围。例如,8-12表示8、9、10、11、12。

3)逗号(,)表示分割指定的数值。例如:3,5-7,9表示3,5,6,7,9。

4)正斜杠(/)表示步进值。例如,分钟的位置为*/5,表示每五分钟执行一次。

除了root用户以外的所有用户定义的crontab计划任务都存放在/var/spool/cron目录,通过crontab -e命令编辑,格式与/etc/crontab相同,可以不用指定user-name。cron服务会每分钟检查一次/etc/crontab、/etc/cron.d/和/var/spool/cron/中的所有文件,并依此执行。

时程表的格式如下 : 
f1 f2 f3 f4 f5 program 
其中 f1 是表示分钟,f2 表示小时,f3 表示一个月份中的第几日,f4 表示月份,f5 表示一个星期中的第几天。program 表示要执 行的程序。 
当 f1 为 * 时表示每分钟都要执行 program,f2 为 * 时表示每小时都要执行程序,其馀类推 
当 f1 为 a-b 时表示从第 a 分钟到第 b 分钟这段时间内要执行,f2 为 a-b 时表示从第 a 到第 b 小时都要执行,其馀类推 
当 f1 为 */n 时表示每 n 分钟个时间间隔执行一次,f2 为 */n 表示每 n 小时个时间间隔执行一次,其馀类推 
当 f1 为 a, b, c,... 时表示第 a, b, c,... 分钟要执行,f2 为 a, b, c,... 时表示第 a, b, c...个小时要执行,其余类推 
使用者也可以将所有的设定先存放在档案 file 中,用 crontab file 的方式来设定时程表。 

注:当程序在你所指定的时间执行后,系统会寄一封信给你,显示该程序执行的内容,若是你不希望收到这样的信,请在每一行空一格之 后加上 > /dev/null 2>&1 即可 

注:任一字符前如有一个反斜杠符号(包括 %)会引起字符被字面上的处理。天的规范是由两个字段(月的天和星期的天)组成的。如果指定两者都为元素的一个列表,这两个字段均被包含在其中。例如,如下条目:
0 0 1,15 * 1 command
将在每个月的第一天和第十五天运行 command,还有每个星期一。要仅在一个字段中指定天,另一字段应包含 * 。

在crontab文件中如何输入需要执行的命令和时间。该文件中每行都包括六个域,其中前五个域是指定命令被执行的时间,最后一个域是要被执行的命令。每个域之间使用空格或者制表符分隔。格式如下: 
minute hour day-of-month month-of-year day-of-week commands 

第一项是分钟,第二项是小时,第三项是一个月的第几天,第四项是一年的第几个月,第五项是一周的星期几,第六项是要执行的命令。这些项都不能为空,必须填入。如果用户不需要指定其中的几项,那么可以使用*代替。因为*是统配符,可以代替任何字符,所以就可以认为是任何时间,也就是该项被忽略了。在下表中给出了每项的合法范围。
 
表:指定时间的合法范围 
时间 合法值
minute 00-59
hour 00-23
day-of-month 01-31
month-of-year 01-12
day-of-week 0-6 (0 is sunday) 

这样用户就可以往crontab 文件中写入无限多的行以完成无限多的命令。命令域中可以写入所有可以在命令行写入的命令和符号,其他所有时间域都支持列举,也就是域中可以写入很多的时间值,只要满足这些时间值中的任何一个都执行命令,每两个时间值中间使用逗号分隔。 

除了数字还有几个个特殊的符号就是"*"、"/"和"-"、",",*代表所有的取值范围内的数字,"/"代表每的意思,"/5"表示每5个单位,"-"代表从某个数字到某个数字,","分开几个离散的数字。 

指定命令
这个 cron 守护程序运行命名于所选日期和时间的第六个字段中的字段。如果包含一个 %(百分号)在第六字段,cron 守护程序像命令调用一样处理所有的任务,并使所有的后续任务在标准输入上可用,除非转义百分号 (\%)。空行和第一个非空字符是编号标记(#)将被忽略。如果命令含有反斜杠 (\) 的参数,反斜杠前应加另一个反斜杠。

注意:shell 只运行该命令字段的第一行。所有其他的行作为标准的输入对于命令可用。

编辑cron配置文件/etc/crontab

cron服务每分钟不仅要读一次 /var/spool/cron 内的所有文件,还需要读一次 /etc/crontab,因此我们配置这个文件也能运用cron服务做一些事情。用crontab配置是针对某个用户的,而编辑/etc/crontab是针对系统的任务。

cron 守护程序从 HOME 目录中启动一个子 shell。如果调度一个命令运行,这时您尚未登录,并且希望在 .profile 文件中的命令运行,这个命令必须明确的读取您的 .profile 文件。cron 守护程序为每个 shell 提供了一个缺省的环境,定义了 HOME, LOGNAME, SHELL (=/usr/bin/sh) 和 PATH (=/usr/bin),大致内容如下:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/


该文件是存放系统执行的定时计划,其中前四行用于设置cron服务运行的环境变量:SHELL、PATH、HOME分别指定了cron服务运行时的SHELL环境变量、PATH环境变量和HOME环境变量,这里不再赘述。MAILTO则表示cron运行的任务输出以电子邮件的形式发送到指定用户,如果该变量的值为空,则不会发送邮件。余下几行的内容说明了系统定时任务的具体书写格式。


命令行选项
-e UserName
编辑用户的 crontab 文件的副本,或者,如果一个有效的 UserName 的 crontab 文件不存在则创建一个空的文件进行编辑。当编辑完成后,文件被到 crontab 目录作为用户的 crontab 文件。
-l UserName
列出用户的 crontab 文件。
-r UserName
从 crontab 目录除去用户的 crontab 文件。
-v UserName
列出用户 cron 作业的状态。

大致如下:
crontab file [-u user]-用指定的文件替代目前的crontab。 
crontab-[-u user]-用标准输入替代目前的crontab. 
crontab-1[user]-列出用户目前的crontab. 
crontab-e[user]-编辑用户目前的crontab. 
crontab-d[user]-删除用户目前的crontab. 
crontab-c dir- 指定crontab的目录。 

下面列出一些不常见的操作指令:

root用户编辑用户freeoa的定时任务
# crontab -u freeoa -e
为用户freeoa指定定时任务文件
# crontab -u freeoa freeoacron


安全审计事件
如果正确地配置和启用了审计子系统,那么 crontab 命令就会在每次运行时生成以下审计记录(事件):
事件 信息
CRON_JobRemove 列出哪一个用户除去了 cron 作业和除去的时间。
CRON_JobAdd 列出哪一个用户添加了 cron 作业和添加的时间。

退出状态
该命令返回以下退出值:
0
成功完成。

>0

发生错误。

文件
/var/adm/cron/FIFO
指定的管道,当用 crontab 或 at 命令提交新作业时,它将消息发送到 cron 守护程序。

/var/spool/cron/crontabs
指定 crontab 缓冲池区域。

/var/adm/cron/cron.allow
指定用户列表,这些用户被允许访问 crontab 命令。

/var/adm/cron/cron.deny
指定用户列表,这些用户不被允许访问 crontab 命令。

示例
要将名为 mycronjobs 的文件复制到 /var/spool/cron/crontabs 目录中,输入以下内容: 
crontab mycronjobs
文件将复制为: 
/var/spool/cron/crontabs/<username>
其中 <username> 是您当前的用户名。

要每小时将时间写入控制台(以小时的形式),请输入: 
0 * * * * echo The hour is `date`.>/dev/console

要在每个星期一、星期三和星期五的 6:30 a.m. 运行 calendar 命令,请输入: 
30 6 * * 1,3,5 /usr/bin/calendar

要在一年中每天 6:30 运行 calendar 命令,请输入: 
30 6 * * * /usr/bin/calendar

要在八月每天午夜运行名为 maintenance 的脚本,请输入: 
0 0 * 8 * /u/harry/bin/maintenance

0 16 * 12 5 /usr/sbin/wall%HAPPY HOLIDAY!%Remember to turn in your time card.

30 15 13 Jun Mon * root tar czf /usr/backups/daily/etc.tar.gz /etc >> /dev/null 2>&1
如果你想以用户joey的身份每小时的第15分钟运行某个程序,可以使用: 
15 * * * * joey /usr/bin/somecommand >> /dev/null 2>&1
其中的星号(*)是通配符,表示cron将忽略这个字段。

如果你想每两小时就运行某个程序,可以在小时字段里使用 */2。它将会在2点,4点,6点……22点,24点运行。具体语句如下: 
0 */2 * * * joey /usr/bin/somecommand >> /dev/null 2>&1
cron语句中还可以使用逗号(,)来指定多个时间。例如你想在每小时的15分和30分运行某个程序,可以在分钟字段使用15,30: 
15,30 * * * * joey /usr/bin/somecommand >> /dev/null 2>&1

如果你想在每月的第一周(即1号到7号)每天的指定时间运行某个程序,可以在日期字段使用1-7: 
15,30 */2 1-7 * * joey /usr/bin/somecommand >> /dev/null 2>&1

这条语句将在每月的第1-7日每两小时的15分和30分(02:15,02:30……22: 15,22:30等)运行 /usr/bin/somecommand 命令。

如果你想在每天的16:18执行一个脚本集合,可以把所有要执行的脚本放到一个目录中(如 /home/username/cron),可以使用: 
18 16 * * * root run-parts /home/username/cron >> /dev/null 2>&1

如果你想保存某个程序的输出结果, 可以把 >> /dev/null 2>&1 替换为 >> /home/user/somecommand.log 2>&1。 

30 21 * * * /usr/local/etc/rc.d/lighttpd restart 
上面的例子表示每晚的21:30重启apache。 
45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart 
上面的例子表示每月1、10、22日的4 : 45重启apache。 
10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart 
上面的例子表示每周六、周日的1 : 10重启apache。 
0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart 
上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启apache。 
0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart 
上面的例子表示每星期六的11 : 00 pm重启apache。 
* */1 * * * /usr/local/etc/rc.d/lighttpd restart 
每一小时重启apache 
* 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart 
晚上11点到早上7点之间,每隔一小时重启apache 
0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart 
每月的4号与每周一到周三的11点重启apache 
0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart 
一月一号的4点重启apache 
#每天早上7点执行一次 /bin/ls : 
0 7 * * * /bin/ls 
在 12 月内, 每天的早上 6 点到 12 点中,每隔3个小时执行一次 /usr/bin/backup : 
0 6-12/3 * 12 * /usr/bin/backup 
周一到周五每天下午 5:00 寄一封信给 alex@domain.name : 
0 17 * * 1-5 mail -s "hi" alex@domain.name 
每月每天的午夜 0 点 20 分, 2 点 20 分, 4 点 20 分....执行 echo "haha" 
20 0-23/2 * * * echo "haha" 
例子2 : 
#每天早上6点10分 
10 6 * * * date 
#每两个小时 
0 */2 * * * date 
#晚上11点到早上8点之间每两个小时,早上8点 
0 23-7/2,8 * * * date 
#每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点 
0 11 4 * mon-wed date 
#1月份日早上4点 
0 4 1 jan * date 

每天早上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

5,15,25,35,45,55 16,17,18 * * * command
在每周一,三,五的下午3:00系统进入维护状态,重新启动系统。那么在crontab 文件中就应该写入如下字段: 
00 15 * * 1,3,5 shutdown -r +5
然后将该文件存盘为foxy.cron,再键入crontab foxy.cron安装该文件。每小时的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)
每年的一月和四月,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

每月每天每小时的第 0 分钟执行一次 /bin/ls : 
0 * * * * /bin/ls 
在 12 月内, 每天的早上 6 点到 12 点中,每隔 20 分钟执行一次 /usr/bin/backup : 
*/20 6-12 * 12 * /usr/bin/backup
周一到周五每天下午 5:00 寄一封信给 alex@domain.name : 
0 17 * * 1-5 mail -s "hi" alex@domain.name < /tmp/maildata
每月每天的午夜 0 点 20 分, 2 点 20 分, 4 点 20 分....执行 echo "haha"
20 0-23/2 * * * echo "haha"

1、下面的计划任务会一直运行
* * * * * [command]

2、下面的计划任务会在每个小时的0分时运行(就是每小时执行一次)
0 * * * * [command]

3、下面依旧是一个每小时运行一次的计划任务。不过是在每个小时的一刻钟时运行的(1:15,2:15.。。)
 15 * * * * [command]

4、下面的计划任务每天执行一次,在2:30分
30 2 * * * [command]

5、下面的计划任务是在每个月2号的午夜执行(比如:2010年2月2日00:00)
0 0 2 * * [command]

6、下面的计划任务会在每周一的每个小时0分钟时执行一次
0 * * * 1 [command]

7、下面的会每小时运行3次,在0分,10分,和20分时
0,10,20 * * * * [command]

8、下面是用除号“/”表示每多少运行一次。
*/5 * * * * [command] 每5分钟运行一次

00 */2 * * * [command] 每2小时运行一次 (* */2 * * * [command]  这种写法是错误的!)

9、还可以用“-”表示一个范围,如下表示5到10点的每个整点运行一次
0 5-10 * * * [command]

注意:当程式在你所指定的时间执行后,系统会寄一封信给你,显示该程式执行的内容,若是你不希望收到这样的信,请在每一行空一格之后加上 > /dev/null 2>&1 即可。
该文章最后由 阿炯 于 2021-01-31 10:26:44 更新,目前是第 2 版。