Linux crontab
crontab命令用于设置周期性被执行的指令。该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行。
可以使用crontab定时处理离线任务,比如每天凌晨2点更新数据等,经常用于系统任务调度。
cron是linux的一个定时任务执行工具,而crondtab是周期性执行命令,crond则是定时任务的守护进程。
crontab服务管理
查看服务是否启动
➜ /etc systemctl status crond
● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2019-08-14 19:32:11 CST; 10 months 28 days ago
Main PID: 456 (crond)
CGroup: /system.slice/crond.service
└─456 /usr/sbin/crond -n
Jul 12 21:20:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 21:30:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 21:40:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 21:50:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 22:00:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 22:10:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 22:20:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 22:30:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 22:40:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Jul 12 22:50:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
Hint: Some lines were ellipsized, use -l to show in full.
如果没有启动,执行
systemctl start crond
systemctl enable crond
service crond start # 启动服务
service crond stop # 关闭服务
service crond restart # 重启服务
service crond reload # 重新载入配置
service crond status # 查看crontab服务状态
# 可以使用下面的命令加入开机启动
chkconfig --level 345 crond on
crontab命令
语法 : crontab 参数
常用参数 :
crontab -u #指定用户的cron信息
crontab -l #列出当前用户下的cron服务的信息
crontab -u user -l #列出指定用户的cron服务的信息
crontab -r #删除cron服务
crontab -e #编辑cron服务
crontab -r -u user #删除指定用户的定时任务
编辑cron服务
➜ /etc crontab -e
crontab: installing new crontab
查看当前用户下任务内容
➜ /etc crontab -l
22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc22 22 22 * * mkdir fc
删除任务
➜ /etc crontab -r
➜ /etc crontab -l
no crontab for root
查看某个用户下的任务内容
➜ /etc crontab -u root -l
no crontab for root
删除某个用户下的定时任务
➜ /etc crontab -u root -r
no crontab for root
➜ /etc crontab -u root -l
no crontab for root
系统任务
系统的任务调度配置文件在/etc/crontab下
➜ /etc ll /etc/crontab
-rw-r--r-- 1 root root 0 Sep 17 2019 /etc/crontab
可以直接在/etc/crontab下添加系统任务(不建议)
➜ cat /etc/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
定时任务相关的目录
➜ ll cr
cron.d/
cron.deny/
cron.monthly/
cron.weekly/
cron.daily/
cron.hourly/
crontab
crypttab
cron.daily
是每天执行一次的jobcron.weekly
是每个星期执行一次的jobcron.monthly
是每月执行一次的jobcron.hourly
是每个小时执行一次的jobcron.d
是系统自动定期需要做的任务crontab
是设定定时任务执行文件cron.deny
文件就是用于控制不让哪些用户使用Crontab的功能
每个用户都有自己的crontab
配置文件,使用crontab -e
命令进行编辑。保存后系统会自动存放与/var/spool/cron/
目录中,文件以用户名命名。
Linux的crontab
服务每隔一分钟去读取一次/var/spool/cron
,/etc/crontab
,/etc/cron.d
下面所有的内容。
定时任务规则
使用案例
#每晚的20:30重加载nginx
30 20 * * * /usr/local/nginx/sbin/nginx -s reload
#每月1、10、15日的5:30重加载nginx
30 5 1,10,15 * * /usr/local/nginx/sbin/nginx -s reload
#每天20: 00至22 : 00之间每隔30分钟重加载nginx
0,30 20-22 * * * /usr/local/nginx/sbin/nginx -s reload
每星期六的10 : 00 pm 重加载nginx
0 22* * 6 /usr/local/nginx/sbin/nginx -s reload
#每一小时重加载一次nginx
0 */1 * * * /usr/local/nginx/sbin/nginx -s reload
查看定时任务操作日志
tail -f /var/log/cron
crontab创建任务会遇到的问题
不要假定cron知道所需要的特殊环境,它其实并不知道。所以要保证在shelll脚本中提供所有必要的路径和环境变量,除了一些自动设置的全局变量。需要注意以下几点:
1)脚本中涉及文件路径时写全局路径;
2)脚本执行要用到java或其他环境变量时,通过source
命令引入环境变量,如:
cat start.sh
#!/bin/sh
source /etc/profile
export RUN_CONF=/home/d139/conf/platform/cbp/cbp_jboss.conf
/usr/local/jboss-4.0.5/bin/run.sh -c mev &
3)当手动执行脚本OK,但是crontab死活不执行时。这时必须大胆怀疑是环境变量的问题,并可以尝试在crontab中直接引入环境变量解决问题。如:
0 * * * * . /etc/profile;/bin/sh /var/www/java/audit_no_count/bin/restart_audit.sh
crontab创建任务时其他应该注意的问题
1)新创建的cron job,不会马上执行,至少要过2分钟才执行。如果重启cron则马上执行。
2)每条 JOB 执行完毕之后,系统会自动将输出发送邮件给当前系统用户。日积月累,非常的多,甚至会撑爆整个系统。所以每条 JOB 命令后面进行重定向处理是非常必要的: >/dev/null 2>&1 。前提是对 Job 中的命令需要正常输出已经作了一定的处理, 比如追加到某个特定日志文件。
3)当crontab突然失效时,可以尝试/etc/init.d/crond restart解决问题。或者查看日志看某个job有没有执行/报错 tail -f /var/log/cron
。
4)千万别乱运行 crontab -r
。它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。删除了该用户的所有crontab都没了。
5)在crontab中%是有特殊含义的,表示换行的意思。如果要用的话必须进行转义\%,如经常用的date ‘+%Y%m%d’在crontab里是不会执行的,应该换成date ‘+\%Y\%m\%d’。
定制执行任务命令的注意事项
输入输出重定向
在没有配置输出重定向的时候,定时任务会见错误输出到下面的文件:/var/log/mail/{$user}
,这是很不好的,往往需要把不同的脚本输出到不同的日志文件,方便查看脚本的执行情况,这个时候需要使用输出重定向。
58 23 * * * sh /home/work/update.sh >> /home/work/log/update.log 2>&1
Linux中使用0-3
作为文件描述符来表示标准流。
名称 | 类型 | 文件描述符 | 操作 |
---|---|---|---|
stdin 标准输入 | standard input | 0 | < ,<< |
stdout 标准输出 | standard output | 1 | > ,>> |
stderr 标准错误输出 | standard error output | 2 | 2> ,2>> |
在上面的定时任务脚本中,update.sh
后面的>>
表示将输出追加到update.log
文件中,2>&1
表示标准错误输出重定向等同于标准输出。
忽略输入nohup
有时候还会看到在定时任务脚本前面有一个nohup
的命令,该命令用于指定后面的脚本忽略输入。
58 23 * * * nohup sh /home/work/update.sh >> /home/work/log/update.log 2>&1
后台执行&
无论是在控制台直接执行,还是在定时任务脚本中,在某一条命令的最后面加上&
符号,表示当前命令在后台运行,不占用控制台。
58 23 * * * nohup sh /home/work/update.sh >> /home/work/log/update.log 2>&1 &
这里需要注意,如果执行的命令有等待输入的交互,把这个命令使用&
放在后台运行时,它会一直等待输入,但是有没有输入,就卡住不动了。
时间处理
再回顾上面的更新任务,它是将每一天的运行结果都重定向到update.log
文件,如果输出比较多,就需要每一天输出的不同的文件,可以通过在输出目录中指定日期用来分割。如下:
58 23 * * * nohup sh /home/work/update.sh >> /home/work/log/`update_"date +\%Y\%m\%d".log` 2>&1 &
# 或者下面的形式
58 23 * * * nohup sh /home/work/update.sh >> "/home/work/log/update_"date +\%Y\%m\%d".log" 2>&1 &
这里使用date
函数,需要注意的是,crontab里面的脚本命令和直接在命令行运行的脚本可能是不一样的,尤其是date
函数中的%
需要转义。
可以直接在命令行运行下面命令:
sh /home/work/update.sh >> /home/work/log/update_`date +"%Y%m%d".log` 2>&1 &
达到和定时任务里面相同的效果,都是输出到update_20201120.log
的文件。
但是如果直接在crontab中这样配置,则无法识别,不会执行该定时任务。下面的crontab任务是不会执行的,date函数将会报错。
58 23 * * * nohup sh /home/work/update.sh >> /home/work/log/`update_"date +%Y%m%d".log` 2>&1 &