crontab与crond
crontab是Unix和Linux用于设置需要周期性被执行的指令,是Linux服务器很常用的技术,很多任务都会设置在crontab循环执行,如果不使用crontab,那么任务就是常驻程序,这对你的程序要求比较高,一个要求你的程序是24X7小时不宕机,一个是要求你的调度程序比较可靠,实际工作中,90%的程序都没有必要花这么多时间和精力去解决上面的两个问题的,只需要写好自己的业务逻辑,通过crond这个工业级程序去调度就行了,crond的可靠性,健壮性,大家应该心里有数。
crond: 控制周期性任务计划调度的后台进程,daemon。
crontab: 提供给用户控制任务计划的命令,创建、删除、编辑任务计划等。该命令从标准输入设备读取指令,并将其存放于“crontab”文件中(/var/spool/cron/以用户命名的文件),以供之后读取和执行。
每一个用户都可以有自己的crontab文件,但在一个用户较多的系统中,我们通常会限制。为了安全问题,可以限制能够使用 crontab 的用户: /etc/cron.allow, /etc/cron.deny
crond工作原理
当用户使用crontab命令新建任务计划之后,该项 jobs 就会被 /var/spool/cron/ 目录下,而且以用户账号来创建一个文件,每一项任务计划为一行。
crond 检测的时间周期是 “分钟”, 每分钟会读取一次 /etc/crontab, 以及 /var/spool/cron 里面的记录并执行。
crond 执行的每一项任务计划,都会被记录到 /var/log/cron 这个日志文件。
cron服务
cron是一个linux下 的定时执行工具,可以在无需人工干预的情况下运行作业。
service crond start //启动服务
service crond stop //关闭服务
service crond restart //重启服务
service crond reload //重新载入配置
service crond status //查看服务状态
crontab语法
Usage:
crontab [options] file
crontab [options]
crontab -n [hostname]
Options:
-u <user> define user. 只有user才能进行这个任务,亦即帮其他使用者创建/移除crontab工作排程。
-e edit user's crontab. 编辑
-l list user's crontab. 查阅
-r delete user's crontab. 移除所有的 crontab 的工作内容,若仅要移除一项,请用 -e 去编辑, 注意!!
-i prompt before deleting
-n <host> set host in cluster to run users' crontabs
-c get host in cluster to run users' crontabs
-s selinux context
-x <mask> enable debugging
cron的配置文件
/var/spool/cron/ 这个目录下存放的是每个用户包括root的crontab任务,每个任务以创建者的名字命名,比如root建的crontab任务对应的文件就是/var/spool/cron/root。一般一个用户最多只有一个crontab文件。
/etc/crontab
这个文件负责安排由系统管理员制定的维护系统以及其他任务的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
MAILTO=root:是说,当 /etc/crontab 这个档案中的例行性命令发生错误时,会将错误讯息或者是屏幕显示的讯息传给谁?由于 root 并无法再用户端收信,因此,可以将这个 e-mail 改成自己的账号,好随时了解系统的状态!
特殊符号
- *: 星号操作符表示所有允许的值。如果在分钟字段中有星号,则表示任务将每分钟执行一次。
- -: 连字符操作符允许您指定一个值范围。如果您在Day of the week字段中设置了1-5,任务将在每个工作日(从周一到周五)运行。范围是包含的,这意味着第一个值和最后一个值都包含在范围中。
- ,: 逗号操作符允许您定义一个用于重复的值列表。例如,如果Hour字段中有1,3,5,任务将在1 am、3 am和5 am运行。列表可以包含单个值和范围,1-5、7、8、10-15
- /: 斜杠操作符允许您指定可以与范围一起使用的步骤值。例如,如果分钟字段中有1-10/2,这意味着在范围1-10中每两分钟执行一次操作,与指定1、3、5、7、9相同。您也可以使用星号操作符,而不是一组值。要指定每20分钟运行一次的作业,可以使用" */20 "。
系统级crontab文件的语法与用户级crontab略有不同。它包含一个附加的强制用户字段,指定哪个用户将运行cron作业。
记忆:分时日月周
"" 代表所有的取值范围内的数字,任何时刻都接受。特别要注意哦!
"/n" 表示每n个单位间隔
"-" 时间范围
"," 分隔的时段
表达式验证网站:https://tooltt.com/crontab/
注:该网站按小时计算的不大准
/etc/cron.d/
这个目录用来存放任何要执行的crontab文件或脚本
crontab -e 与 /etc/crontab 文件
crontab -e是针对使用者的 cron 来设计的,如果是系统的例行性任务时,就要编辑 /etc/crontab 这个文件。
大家可能分不清用crontab -e编辑和直接编辑/etc/crontab有什么不一样?这就是我要特别提醒大家的地方:
- crontab -e是用来编辑某个用户的计划任务。即,可以不指定用户。
- /etc/crontab这个里面的计划任务是系统中的计划任务。需指定用户
CentOS提供的 run-parts 这个脚本,可以把某个目录下所有的"可执行文件"拿出来执行。
假设你创建了一个目录,让系统以root用户,每2分钟把此目录下所有的可以执行的文件执行一次:
*/2 * * * * root run-parts /home/dir
以相应的用户非交互式设置
# (crontab -l 2>/dev/null || true; echo "*/5 * * * * /home/test.sh >> /home/test.log 2>&1") | crontab -
$ (crontab -l 2>/dev/null || true; echo "*/5 * * * * /home/test.sh >> /home/test.log 2>&1") | crontab -
将"*/5 * * * * /home/test.sh >> /home/test.log 2>&1"追加到当前任务的后面
crontab 与 环境变量
手动在CentOS中执行sh脚本,一切正常;将该sh加入crontab中任务计划调度之后,会有报错。crond没有初始化用户的环境变量。
案例:
[转]记一次诡异的python脚本中编码报错,crontab执行报错,但手动执行正常
不知道大家是否想过这样一个问题:当我们并没有联机,也就是没有通过ssh或其他工具登录到Linux服务器上,我们创建的计划任务还可以执行么?它会以谁的身份去运行呢? 它的环境变量是否和我们直接在命令行下是相同的呢?
不要假定cron知道所需要的特殊环境,它其实并不知道。bash 的用户环境,是当用户在登录的时候,bash 读取多个配置文件(/etc/profile, ~/.bash_profile, ~/.bashrc ...),从而为我们设定了很多环境变量。但是,cron 不同,它并不知道用户的环境,所以你要保证在shelll脚本中提供所有必要的路径和环境变量,除了一些自动设置的全局变量。所以注意如下3点:
1)脚本中涉及文件路径时写绝对路径;
2)脚本执行要用到java或其他环境变量时,通过source命令引入环境变量,如:
$ cat test.sh
#!/bin/bash
source /etc/profile # 引入 profile环境变量
export RUN_CONF=/home/123/jboss.conf
/usr/local/jboss/bin/run.sh -c mev &
3)当手动执行脚本OK,但是crontab死活不执行时。这时必须大胆怀疑是环境变量惹的祸,并可以尝试在crontab中直接引入环境变量解决问题。
* * * * * ./etc/profile; /usr/bin/python3 /home/test.py >>/home/test.log 2>&1
或
* * * * * source /etc/profile && /usr/bin/python3 /home/test.py >>/home/test.log 2>&1
其他注意事项
- 新创建的cron job,不会马上执行,至少要过2分钟才执行。如果重启cron则马上执行。
- **每条 JOB 执行完毕之后,系统会自动将输出发送邮件给当前系统用户。**日积月累,非常的多,甚至会撑爆整个系统。所以每条 JOB 命令后面进行重定向处理是非常必要的: >/dev/null 2>&1 。前提是对 Job 中的命令需要正常输出已经作了一定的处理, 比如追加到某个特定日志文件。
- **当crontab突然失效时,可以尝试/etc/init.d/crond restart解决问题。**或者查看日志看某个job有没有执行/报错tail -f /var/log/cron。
- **千万别乱运行crontab -r。**它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。删除了该用户的所有crontab都没了。
- **在crontab中%是有特殊含义的,表示换行的意思。**如果要用的话必须进行转义%,如经常用的date ‘+%Y%m%d’在crontab里是不会执行的,应该换成date ‘+%Y%m%d’`。
- 工作中遇到比较多的是root密码过期,导致它的cronjob无法正常执行。
- 周与日月****不可同时并存。 要么指定周, 要么指定日月
案例
- 晚上11点到早上8点之间每两个小时和早上八点
0 23-7/2,8 * * * echo "123" >> /tmp/test.txt
按逗号分开来看
①23-7/2:23点到隔天7点,每2小时执行一次
②8:8点
- 每天,0点,7分到59分之间每2分钟执行一次
7/2 0 * * * echo "123" >> /tmp/test.txt
按/来看
①7:即7-,从第7分开始到59分。
②2:每2分钟执行一次
- 每天,13分到59分每5分钟执行一次
13/5 * * * * echo "123" >> /tmp/test.txt
- 每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
0 11 4 * 1-3 command(s)
- 1月1日早上4点
0 4 1 1 * command(s) SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root
如果出现错误,或者有数据输出,数据作为邮件发给这个帐号 HOME=/
- 每周一,三,五的下午3:00系统进入维护状态,重新启动系统。
00 15 * * 1,3,5 shutdown -r +5
crontab环境变量
crontab 有自己的环境变量配置,在 /etc/crontab 文件中,并不会自动加载当前用户的环境变量,所以在执行命令之前,应该先配置好环境变量。
crontab如何支持秒级任务
使用sleep
每15秒执行一次command(s)
* * * * * command(s)
* * * * * sleep 15 command(s)
* * * * * sleep 30 command(s)
* * * * * sleep 45 command(s)
直接sleep相对应的秒数就好了,例如15秒,那么就要写4行,分别是整点,15秒,30秒,45秒。记得这个秒数要能被60整除。
shell脚本方式实现
1、编写脚本
vim /var/crontab/test.sh
#!/bin/bash
step=1 #间隔的秒数,不能大于60
for (( i = 0; i < 60; i=(i+step) )); do
#要定时执行的命令
$(command(s))
#等待时间
sleep $step
done
exit 0
2、设置定时任务每分钟执行脚本
crontab -e
* * * * * /var/crontab/test.sh
原理:在shell使用for语句实现循环指定秒数执行。
参考:
https://blog.51cto.com/skypegnu1/1428632
http://bbs.chinaunix.net/thread-2291457-1-1.html
https://www.jianshu.com/p/446758d924df