Linux crontab
crontab命令用于设置周期性被执行的指令。该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行。
可以使用crontab定时处理离线任务,比如每天凌晨2点更新数据等,经常用于系统任务调度。
cron是linux的一个定时任务执行工具,而crondtab是周期性执行命令,crond则是定时任务的守护进程。

crontab服务管理

查看服务是否启动

  1. /etc systemctl status crond
  2. crond.service - Command Scheduler
  3. Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
  4. Active: active (running) since Wed 2019-08-14 19:32:11 CST; 10 months 28 days ago
  5. Main PID: 456 (crond)
  6. CGroup: /system.slice/crond.service
  7. └─456 /usr/sbin/crond -n
  8. Jul 12 21:20:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  9. Jul 12 21:30:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  10. Jul 12 21:40:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  11. Jul 12 21:50:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  12. Jul 12 22:00:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  13. Jul 12 22:10:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  14. Jul 12 22:20:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  15. Jul 12 22:30:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  16. Jul 12 22:40:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  17. Jul 12 22:50:01 fcant-hadoop001 crond[456]: /usr/sbin/sendmail: error while loading shared libraries: libmysqlc...ctory
  18. Hint: Some lines were ellipsized, use -l to show in full.

image.png

  1. 如果没有启动,执行
  2. systemctl start crond
  3. systemctl enable crond
  4. service crond start # 启动服务
  5. service crond stop # 关闭服务
  6. service crond restart # 重启服务
  7. service crond reload # 重新载入配置
  8. service crond status # 查看crontab服务状态
  9. # 可以使用下面的命令加入开机启动
  10. chkconfig --level 345 crond on

crontab命令

语法 : crontab 参数
常用参数 :

  1. crontab -u #指定用户的cron信息
  2. crontab -l #列出当前用户下的cron服务的信息
  3. crontab -u user -l #列出指定用户的cron服务的信息
  4. crontab -r #删除cron服务
  5. crontab -e #编辑cron服务
  6. crontab -r -u user #删除指定用户的定时任务

操作:

编辑cron服务

➜  /etc crontab -e
crontab: installing new crontab

image.png

查看当前用户下任务内容

➜  /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

image.png

删除任务

➜  /etc crontab -r
➜  /etc crontab -l
no crontab for root

image.png

查看某个用户下的任务内容

➜  /etc crontab -u root -l
no crontab for root

image.png
删除某个用户下的定时任务

➜  /etc crontab -u root -r
no crontab for root
➜  /etc crontab -u root -l
no crontab for root

image.png

系统任务

系统的任务调度配置文件在/etc/crontab下

➜  /etc ll /etc/crontab
-rw-r--r-- 1 root root 0 Sep 17  2019 /etc/crontab

image.png
可以直接在/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是每天执行一次的job
  • cron.weekly是每个星期执行一次的job
  • cron.monthly是每月执行一次的job
  • cron.hourly是每个小时执行一次的job
  • cron.d是系统自动定期需要做的任务
  • crontab是设定定时任务执行文件
  • cron.deny文件就是用于控制不让哪些用户使用Crontab的功能

每个用户都有自己的crontab配置文件,使用crontab -e命令进行编辑。保存后系统会自动存放与/var/spool/cron/目录中,文件以用户名命名。
Linux的crontab服务每隔一分钟去读取一次/var/spool/cron/etc/crontab/etc/cron.d下面所有的内容。

定时任务规则

首先来看下任务的格式(如图):
image.png
时间的一些特殊符号:
image.png

使用案例

#每晚的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 &