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个单位间隔
"-"        时间范围
","         分隔的时段


Linux基础:crontab 与 环境变量,以及应该注意的问题_profile


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候,就能够读到用户的环境变量参数啦


刚才搜到非常好的一篇文章:http://bbs.chinaunix.net/thread-2291457-1-1.html

Linux基础:crontab 与 环境变量,以及应该注意的问题_profile_02


    不知道大家是否想过这样一个问题:当我们并没有联机,也就是没有通过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无法正常执行。

  • 周与日月不可同时并存。 要么指定周, 要么指定日月