Cron定时任务(转载)

  一直写定时任务的时候,都是直接用crontab命令,但是对cron定时任务这个东西有时候会混淆,所有就好好总结一下。

一、cron

crond:计划任务的守护进程

1)以前经典的sysvinit方式使用/etc/rc.d/init.d或者/etc/init.d 启动,现在的systemd方式,安装了system服务启动的文件/lib/systemd/system/crond.service,进程启动方式为systemctl start crond.service,启动后会立即返回,因此不需要在启动的时候加&参数

2)cron进程会搜索/var/spool/cron目录下以/etc/passwd中的账户名命名的定时任务文件,搜索到定时任务后会加载到内存。cron也会搜索/etc/anacrontab目录与/etc/cron.d目录下定时任务文件。cron会检查所有找到的定时任务并检查每一条定时任务看有没有当前时间执行的。当执行命令时,任何的输出都会以邮件的方式通知crontab的所属者,或者通过crontab的环境变量里的MAILTO指定特定的邮件接收者,执行的定时任务的任何输出也可以发送给系统日志通过-s选项

3)一共有两种方式检测到crontabs的变化,第一种方式是检查文件的修改时间modtimes,第二种方式是使用inotify检测。使用inotify的方式的话,在进程启动的时候就开始inotify日志文件/var/log/cron

4)当使用第一种方式检查文件的修改时间时,cron会每分钟检查一次modtime,任何的改变都会重新加载。当你改变了定时任务的时候,不需要重启crond。modtime这种方式被用在inotify没有被初始化时。

与cron相关的目录和文件:

/etc/crontab:系统定时任务,只能root用户使用,格式与crontab也不一样。
/var/spool/cron 目录 :通过crontab命令添加的定时任务会以添加的账号命名放在此目录下
/etc/cron.d:这个目录里包含不同的用户的定时任务
/etc/cron.deny:禁止使用cron的用户列表文件
/etc/cron.allow:允许使用cron的用户列表文件
/etc/cron.daily:存放每天执行一次的脚本
/etc/cron.hourly:存放每个小时执行一个的脚本
/etc/cron.monthly:存放每个月执行一次的脚本
/etc/cron.weekly:存放每个星期执行一个的脚本

二、使用crontab

crontab是cron的一个工具

  1. crontab参数的使用

crontab -u:指定用户进行操作,如crontab -u lile -e 那么编辑的就是lile用户的crontab文件
crontab -l:输出当前crontab添加的定时任务
crontab -r:删除定时任务(慎用,或者做备份,删除就没了,存放的文件位置为/var/spool/cron目录下,以所属者命名)
crontab -e:编辑,添加定时任务
crontab -i:与-r参数一起使用,crontab -ri 的话会询问是否删除

1)root账号通过crontab -e添加一条定时任务

然后在/var/spool/cron目录下可以看到以root命名的定时任务文件

2)用户lile通过crontab -l添加一条定时任务

然后在/var/spool/cron目录下可以看到以lile命名的定时任务文件

3)/var/log/cron日志:记录cron执行定时任务的日志,哪个时间执行了什么任务

  1. crontab的白名单与黑名单

crontab定时任务可以对不同的用户进行设置是否允许使用定时任务。实现方式通过/etc/cron.allow与/etc/cron.deny。如果cron.allow文件存在,那么用户必须存在此文件才能使用crontab;如果cron.allow不存在,cron.deny存在,那么用户必须不存在cron.deny才能执行crontab。如果这两个文件都不存在,那么只有超级用户才能执行crontab。其他更加严格的认证方式可以通过/etc/security/access.conf来限制。

1)只有cron.deny时,默认都能使用crontab,只有在cron.deny文件存在的禁止使用

把lile用户添加到cron.deny,那么久禁止lile使用crontab了

2)当cron.deny与cron.allow都存在时,那么允许使用的用户必须添加在cron.allow里,要不然一样不能使用crontab(除了root)

3)当cron.deny与cron.allow都不存在时,那么只有root能使用

  1. crontab的格式
field          allowed values
-----          --------------
minute         0-59
hour           0-23
day of month   1-31
month          1-12 (or names, see below)
day of week    0-7 (0 or 7 is Sunday, or use names)

例1:每天的十点五分执行脚本/home/lile/a.sh

5 10 * * *  sh /home/lile/a.sh

例2:每天的10点到12点的5分,25分,35分打印test

5,25,35 10-12 * * * echo "test"

三. 具体定时功能使用

Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:

Seconds Minutes Hours DayofMonth Month DayofWeek Year或
Seconds Minutes Hours DayofMonth Month DayofWeek
  1. 每一个域可出现的字符如下:
Seconds:可出现", - * /"四个字符,有效范围为0-59的整数
Minutes:可出现", - * /"四个字符,有效范围为0-59的整数
Hours:可出现", - * /"四个字符,有效范围为0-23的整数
DayofMonth:可出现", - * / ? L W C"八个字符,有效范围为0-31的整数
Month:可出现", - * /"四个字符,有效范围为1-12的整数或JAN-DEc
DayofWeek:可出现", - * / ? L C #"八个字符,有效范围为1-7的整数或SUN-SAT两个范围。1表示星期天,2表示星期一, 依次类推
Year:可出现", - * /"四个字符,有效范围为1970-2099年
  1. 每一个域都使用数字,但还可以出现如下特殊字符,它们的含义是:
(1)*:表示匹配该域的任意值,假如在Minutes域使用*, 即表示每分钟都会触发事件。

(2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。

(3)-:表示范围,例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次

(4)/:表示起始时间开始触发,然后每隔固定时间触发一次,例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.

(5),:表示列出枚举值值。例如:在Minutes域使用5,20,则意味着在第5和第20分钟分别触发一次。

(6)L:表示最后,只能出现在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。

(7)W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份

(8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个非周六周末的日期。

(9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。
  1. 举几个例子:
0 0 2 1 * ? * 表示在每月的1日的凌晨2点调度任务
0 15 10 ? * MON-FRI 表示周一到周五每天上午10:15执行作业
0 15 10 ? * 6L 2002-2006 表示2002-2006年的每个月的最后一个星期五上午10:15执行作
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
0 0 12 ? * WED 表示每个星期三中午12点
"0 0 12 * * ?" 每天中午12点触发
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每月15日上午10:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发

四、cron的发送邮件功能

crond的sendmail功能:

  1. 安装sendmail
yum -y install sendmail sendmail-cf m4 
  1. 测试sendmail,报错

解决办法:

vim /etc/postfix/main.cf
inet_interfaces = localhost
改为
inet_interfaces = all

3.查看日志,cat /var/log/maillog

解决办法:

vim /etc/hosts,再后面添加主机名
127.0.0.1  localhost localhost.localdomain localhost4 localhost4.localdomain4 iZj6c5dly2y6k9y0thzjoqZ
::1        localhost localhost.localdomain localhost6 localhost6.localdomain6 iZj6c5dly2y6k9y0thzjoqZ
  1. 测试

使用root用户crontab -e添加一条定时任务

28 16 * * * echo "test mail"

查看日志 cat /var/log/cron,可以看到这个定时任务执行了

然后查看是否发送了邮件给指定的用户,/var/spool/mail/root,可以看到邮件发过来了

  1. 问题处理
    通常会将这个发送邮件功能给关闭,因为当机器的定时任务多的时候会使得/var/spool/mail产生大量的文件,导致磁盘空间不足和inode用完,在添加定时任务的时候,最后每条后面添加一条 >/dev/null 2>&1

    28 16 * * * echo "test mail" >/dev/null 2>&1

    或者,在开始的时候添加MAILTO=""

    MAILTO=""
    28 16 * * * echo "test mail"

参考链接1:https://www.cnblogs.com/lemon-le/p/8476626.html
参考链接2:https://blog.csdn.net/aa15237104245/article/details/93748631

发表评论

邮箱地址不会被公开。 必填项已用*标注