参考文章:
Linux下的crontab定时执行任务命令详解
Linux中的定时任务crontab
- 在LINUX中,周期执行的任务一般由cron这个守护进程来处理[ps -ef|grep cron]。cron读取一个或多个配置文件,这些配置文件中包含了命令行及其调用时间。
- cron的配置文件称为“crontab”,是“cron table”的简写。
一. cron服务
cron是一个linux下 的定时执行工具,可以在无需人工干预的情况下运行作业。
service crond start //启动服务
service crond stop //关闭服务
service crond restart //重启服务
service crond reload //重新载入配置
service crond status //查看服务状态
二. cron在3个地方查找配置文件
①/var/spool/cron/ 这个目录下存放的是每个用户包括root的crontab任务,每个任务以创建者的名字命名,比如tom建的crontab任务对应的文件就是/var/spool/cron/tom。一般一个用户最多只有一个crontab文件。
②/etc/crontab 这个文件负责安排由系统管理员制定的维护系统以及其他任务的crontab
③/etc/cron.d/ 这个目录用来存放任何要执行的crontab文件或脚本。
三. 权限
crontab权限问题到/var/adm/cron/下一看,文件cron.allow和cron.deny是否存在
用法如下:
1、如果两个文件都不存在,则只有root用户才能使用crontab命令。
2、如果cron.allow存在但cron.deny不存在,则只有列在cron.allow文件里的用户才能使用crontab命令,如果root用户也不在里面,则root用户也不能使用crontab。
3、如果cron.allow不存在, cron.deny存在,则只有列在cron.deny文件里面的用户不能使用crontab命令,其它用户都能使用。
4、如果两个文件都存在,则列在cron.allow文件中而且没有列在cron.deny中的用户可以使用crontab,如果两个文件中都有同一个用户,
以cron.allow文件里面是否有该用户为准,如果cron.allow中有该用户,则可以使用crontab命令。
四. cron的具体使用
- 使用命令crontab -e即可编辑crontab,在里面添加需要的定时任务。用户的定时任务文件为 /var/spool/cron/用户名 ,crontab -e命令将相当于vim /var/spool/cron/用户名。
1. 如何写crontab
- crontab中每一行代表一个任务,每个任务由周期和任务名组成。如下形式
59 23 10 5 2014 /home/root/tesh.sh
#分 时 日 月 年 |<-------命令串------->|
表示2014年5月10日23点59分,执行/home/root下的tesh.sh脚本。
- 时间周期中可以使用一些辅助字符,如:
* 表示任何时刻都可以
, 若有多个时刻,用逗号分隔
- 表示一个时刻到另一时刻之间的时间段
/n 表示每过n个时间单位 - 比如,*/10 3-6 10,11 * * /home/root/tesh.sh 就表示 每年每月的10号和11号,3点到6点之间,每过10分钟执行一次tesh.sh
- Cron表达式是一个字符串,字符串以4或5个空格隔开,分为5或7个域,每一个域代表一个含义,Cron有如下两种语法格式:
Minutes Hours DayofMonth Month DayofWeek Year或
Minutes Hours DayofMonth Month DayofWeek
每一个域可出现的字符如下:
Minutes:可出现", - * /"四个字符,有效范围为0-59的整数
Hours:可出现", - * /"四个字符,有效范围为0-23的整数
DayofMonth:可出现", - * / ? L W C"八个字符,有效范围为1-31的整数
Month:可出现", - * /"四个字符,有效范围为1-12的整数或JAN-DEc
DayofWeek:可出现", - * / ? L C #"四个字符,有效范围为1-7的整数或SUN-SAT两个范围。1表示星期天,2表示星期一, 依次类推
Year:可出现", - * /"四个字符,有效范围为1970-2099年
- 每一个域都使用数字,但还可以出现如下特殊字符,它们的含义是:
①*:表示匹配该域的任意值,假如在Minutes域使用*, 即表示每分钟都会触发事件。
②?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。
③-:表示范围,例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次
④/:表示起始时间开始触发,然后每隔固定时间触发一次,例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.
⑤,:表示列出枚举值值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。
⑥L:表示最后,只能出现在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。
⑦W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份
⑧LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
⑨#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。
2. crontab注释
- 在crontab中,#代表了注释,注释的存在,能够简化crontab的一些复杂操作。
- 比如,如果有一个任务test.sh,每天都需要执行,每过10分钟执行一次,我们可以写成 */10 * * * * tesh.sh。现在有新要求,每天1点到1点10分不能执行,其余时间照旧。
一种写法就是:将它拆成多条crontab,比如每天2点到0点执行,每天0点到1点执行,每天1点10分到2点执行。三条语句。这种方法的问题就是,如果再来新的要求呢,比如在此基础之上,每天8点到8点10分不能执行,这又怎么处理,写更多的crontab任务吗?
另一种比较好的解决方案是:写一个run.sh脚本,每10分钟执行一次,首先判断当前时间是否是在1点到1点10分之间,如果不是,就执行tesh.sh,如果是,可以sleep10分钟。
第三种非常好的方案就是利用注释。我们可以在1点时,将tesh.sh任务给注释掉,在1点10分,将tesh.sh任务的注释消除。要实现这种想法,需要使用sed命令。可以在crontab里面这样写:
#每隔10分钟执行一次
*/10 * * * * tesh.sh
#每天1点钟,将命令注释掉
0 1 * * * sudo sed -i 's\%\(\*\/10 \* \* \* \* tesh.sh\)\%#\1\%' /var/spool/cron/用户名
#每天1点零10分,将被注释的命令恢复
10 1 * * * sudo sed -i 's\%\(^##*\)\(\*\/10 \* \* \* \* tesh.sh\)\%\2\%' /var/spool/cron/用户名
- sed -i表示直接修改文件内容,之后的动作必须用单引号括上,单引号之后的是文件。单引号内部s表示替换,s之后的%是分隔符,代替默认的/分隔符,括弧表示将括号里面的内容保存下来,标记为1,#表示把注释扩展到下一个换行符以前,\1表示选取括号中的内容。
- 这里出现了众多的反斜杠,都是用来做转义的,否则会被解析。
- %前面的反斜杠是用来转义crontab的,crontab中会将%解析成换行符。括弧和*前的反斜杠是因为sed会解析它们。
- 如果不是在crontab中,这个命令可以写成 sed -i 's%\*\/10\*\*\*\*tesh.sh\*\/10\*\*\*\*tesh.sh%#\1%' file
3. crontab的调试方式
- 如果crontab不执行,我们可以使用 sudo vim /var/spool/mail/用户名查看系统发给用户的mail,可以通过时间点,来找出执行失败的原因。