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 这个日志文件。
crontab 命令语法crontab [-u username] [-l|-e|-r]
选项与参数:
-u :只有 root 才能进行这个任务,亦即帮其他使用者创建/移除 crontab 工作排程;
-e :编辑 crontab 的工作内容
-l :查阅 crontab 的工作内容
-r :移除所有的 crontab 的工作内容,若仅要移除一项,请用 -e 去编辑, 注意!!
示例1:每天 4:10 同步系统时间[root@localhost ~]# crontab -e
# 此时会进入 vi 的编辑画面让您编辑工作!注意到,每项工作都是一行。
#分 时 日 月 周 command |<==============任务的完整命令行
10 4 * * * /usr/sbin/ntpdate 202.118.1.130 &> /dev/null
示例2:每分钟执行一次# Execute every minute
* * * * * /bin/execute/this/script.sh
以下是可以用于指定时间的特殊符号:
"*" 代表所有的取值范围内的数字,任何时刻都接受。特别要注意哦!"*/n" 表示每n个单位间隔"-" 时间范围"," 分隔的时段
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 /etc/cron.min
crontab 与 环境变量
问题描述:
手动在CentOS中执行sh脚本,一切正常;将该sh加入crontab中任务计划调度之后,完全没有执行到的感觉啊!
查看crontab执行记录日志,# cat /var/log/cron ,日志中并没有执行的记录,说明计划任务并没有被调度执行。
重新编辑计划任务,# crontab -e,把错误输出重定向,40 10 * * * /home/job.sh
2>> /tmp/log,然后查看日志记录,# cat /tmp/log , 有报错信息。
google一把,总结如下:
crontab的定时任务不能执行成功,但是手动执行脚本能成功。说明不是脚本本身的问题,推断可能是crond没有初始化用户的环境变量。
解决办法:
在执行脚本之前,首先执行用户的profile,就OK了。修改脚本,添加如下内容:########
. /etc/profile
########
Ok, 这样,crontab在执行脚本的时s候,就能够读到用户的环境变量参数啦
不知道大家是否想过这样一个问题:当我们并没有联机,也就是没有通过ssh或其他工具登录到Linux服务器上,我们创建的计划任务还可以执行么? 它会以谁的身份去运行呢? 它的环境变量是否和我们直接在命令行下是相同的呢?
不要假定cron知道所需要的特殊环境,它其实并不知道。bash 的用户环境,是当用户在登录的时候,bash 读取多个配置文件(/etc/profile, ~/.bash_profile, ~/.bashrc ...),从而为我们设定了很多环境变量。
但是,cron 不同,它并不知道用户的环境,所以你要保证在shell脚本中提供所有必要的路径和环境变量,除了一些自动设置的全局变量。
那么,问题来了: crontab 任务没有反应!!! 单独在命令行执行就没有问题,放到crontab中就不行!!! 典型的问题。 根据前辈们的经验,这分明就是crontab的环境变量跟用户的环境变量不同导致的。
所以注意如下3点:脚本中涉及文件路径时全部写绝对路径;
脚本执行要用到java或其他环境变量时,通过source命令引入环境变量,如:$ cat start_cbp.sh
#!/bin/bash
source /etc/profile # 引入 profile环境变量
export RUN_CONF=/home/d139/conf/platform/cbp/cbp_jboss.conf
/usr/local/jboss-4.0.5/bin/run.sh -c mev &
当手动执行脚本OK,但是crontab死活不执行时。这时必须大胆怀疑是环境变量惹的祸,并可以尝试在crontab中直接引入环境变量解决问题。如:0 * * * * . /etc/profile; /bin/sh /var/www/java/audit_no_count/bin/restart_audit.sh
应该注意的问题新创建的cron job,可能不会马上执行,至少要过2分钟才执行。如果需要,请重启crond这个服务。
每条 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无法正常执行。
周与日月不可同时并存。 要么指定周, 要么指定日月