Linux 定时任务 | crontab 命令详解

Crontab 介绍


Crontab 简介
  • Crontab 是一个用于设置周期性被执行的任务的工具
  • 被周期性执行的任务我们称为Cron Job
  • 周期性执行的任务列表我们成为Cron Table
Crontab的基本组成
                                 系统服务                         配置工具
    ---------                    ------                         --------
    |配置文件|    ---------->     |crond|        <------------   |crontab|
    --------                     ------                         --------
 文件方式设置定时任务       每分钟都会从配置文件刷新定时任务       用于调整定时任务
Crontab 任务分类

Linux 下的任务调度分为两类:系统任务调度用户任务调度

系统任务调度

系统周期性所要执行的工作,比如写缓存数据到硬盘、日志清理等。在 /etc 目录下有一个 crontab 文件,这个就是系统任务调度的配置文件。

通过直接编辑文件 /etc/crontab 可以设置系统级别的cron table。

[root@peipei3514 ~]# 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

用户任务调度

用户定期要执行的工作,比如用户数据备份、定时邮件提醒等。用户可以使用 crontab 工具来定制自己的计划任务。所有用户定义的 crontab 文件都被保存在 /var/spool/cron 目录中,其文件名与用户名一致。使用者权限文件如下:

  • /etc/cron.deny 该文件中所列用户不允许使用 crontab 命令;
  • /etc/cron.allow 该文件中所列用户允许使用 crontab 命令,在CentOS7.2中不存在该文件。

If the cron.allow file exists, a user must be listed in it to be allowed to use cron If the cron.allow file does not exist but the cron.deny file does exist, then a user must not be listed in the cron.deny file in order to use cron. If neither of these files exists, only the super user is allowed to use cron.

安装并检查 Crontab 服务


#####检查 cron 服务

  • 检查 Crontab 工具是否安装:crontab -l,无错误则正常安装;
  • 检查 crond 服务是否启动:service crond statussystemctl status crond

注:Windows在运行中输入services.msc打开服务管理

安装 cron
  • yum install vixie-cron
  • yum install crontabs

命令详解


crond
[root@peipei3514 ~]# crond -h
Usage:
 crond [options]

Options:
 -h         print this message
 -i         deamon runs without inotify support
 -m   off, or specify prefered client for sending mails
 -n         run in foreground
 -p         permit any crontab
 -P         use PATH="/usr/bin:/bin"
 -c         enable clustering support
 -s         log into syslog instead of sending mails
 -x   print debug information

Debugging flags are: ext,sch,proc,pars,load,misc,test,bit

通过以上帮助信息,我们可以知道 crond 是执行任务计划的一个守护进程。在使用 crontab 之前我们可以根据帮助信息来设置相关选项,一般情况下我们都使用默认值。

Crontab

命令 crontab 用来设置、移除、列出服务 crond 表格,crond 服务的作用类似 atd,区别的地方在于 crond 可以设置任务多次执行。相对来说比 atd 更常用。

[root@peipei3514 ~]# crontab --help
crontab:无效选项 -- -
crontab: usage error: unrecognized option
Usage:
 crontab [options] file
 crontab [options]
 crontab -n [hostname]

Options:
 -u   define user
 -e         edit user's crontab
 -l         list user's crontab
 -r         delete user's crontab
 -i         prompt before deleting
 -n   set host in cluster to run users' crontabs
 -c         get host in cluster to run users' crontabs
 -s         selinux context
 -x   enable debugging

Default operation is replace, per 1003.2
[root@peipei3514 ~]# man crontab
CRONTAB(1)                                                                                                  User Commands                                                                                                  CRONTAB(1)

NAME
       crontab - maintains crontab files for individual users

SYNOPSIS
       crontab [-u user] file
       crontab [-u user] [-l | -r | -e] [-i] [-s]
       crontab -n [ hostname ]
       crontab -c

DESCRIPTION
       Crontab  is  the program used to install a crontab table file, remove or list the existing tables used to serve the cron(8) daemon.  Each user can have their own crontab, and though these are files in /var/spool/, they are
       not intended to be edited directly.  For SELinux in MLS mode, you can define more crontabs for each range.  For more information, see selinux(8).

       In this version of Cron it is possible to use a network-mounted shared /var/spool/cron across a cluster of hosts and specify that only one of the hosts should run the crontab jobs in the particular  directory  at  any  one
       time.  You may also use crontab(1) from any of these hosts to edit the same shared set of crontab files, and to set and query which host should run the crontab jobs.

选项 -e 表示编辑用户的 cron table。编辑时系统会选定默认编辑器,在笔者的环境中是 vim

使用 crontab -e 的方式编辑时,会在 /tmp 下面生成一个临时文件,保存后 crond 会将内容写入到 /var/spool/cron 下面一个和用户名同名的文件中,crond 会在保存时做语法检查。这也是推荐的设置定时任务的用法。

# 每隔3分钟测试10.0.1.252的连通性,并将结果追加输出到/root/252.log中
[root@peipei3514 ~]# crontab -e
*/3 * * * * /usr/bin/ping -c1 10.0.1.252 &>> /root/252.log

# 保存后会有crontab: installing new crontab字样出现。
# 注意六个部分都不能为空,命令最好写绝对路径,编辑普通用户的定时任务时,要注意命令的执行权限。
Crontab 使用示例
  • 查看某用户的计划任务列表:crontab [-u user] -l
  • 修改某用户的计划任务:crontab -e

注:crontab [-u user] …. 编辑某个用户的 crontab 任务

Crontab日志

/var/log/cron 文件保存着 cron 的任务执行记录。

[root@peipei3514 ~]# tail -f /var/log/cron
Crontab常见错误
  • Crontab 任务无法访问环境变量
# 在.bash_profile中export一个APPDIR
[root@peipei3514 ~]# vim .bash_profile
APPDIR=/etc
export APPDIR

# 保存并退出
[root@peipei3514 ~]# source .bash_profile
[root@peipei3514 ~]# echo APPDIR
/etc

# 在crontab中打印APPDIR这个环境变量
[root@peipei3514 ~]# crontab -e
*/1 * * * * echo $APPDIR >> /tmp/appdir.log

# 保存退出
[root@peipei3514 ~]# tail -f /tmp/appdir.log
# 显示空行

# 因此crontab任务无法访问环境APPDIR变量
  • 命令行双引号中使用%时,未加反斜线\

    在 crontab 中 % 是有特殊含义的,表示换行的意思。如果要用的话必须进行转义,如经常用的 date ‘+%Y%m%d’在 crontab 里是不会执行的,应该换成 date ‘+\%Y\%m\%d’

  • 第三和第五个域之间执行的是 “或” 操作:四月的第一个星期日早晨1时59分运行a.sh

# 日期和星期是或操作,下面则表示1号-7号和四月中的星期日那天都会执行
59 1 1-7 4 0 /root/a.sh
# 利用shell命令判断是否是周日来执行脚本,注:这里%要用\转义
59 1 1-7 4 * test `date +\%w` -eq 0 && /root/a.sh
# 注:test的用法
[root@peipei3514 ~]# test 1 = 0 // 不能写成 test 1=0,否则结果为0,test把1=0当成字符串
[root@peipei3514 ~]# echo $?
1
# 或使用
[root@peipei3514 ~]# test 1 -eq 0
  • 分钟设置无用:两个小时运行一次
# 错误的设置,下面0时每一分钟都可以执行
 * 0,2,4,6,8,10,12,14,16,18,20,22 * * * date
# 正确设置
0 */2 * * * date
# 先满足1-20约束,再满足每隔2分钟执行,即1 3 5 7 9 11 .. 19分执行date
1-20/2 * * * * date 
Crontab补充

Crontab 中最小只能设置到每分钟执行一个命令,如果想没半分钟执行某个命令怎么做到?

通过 shell 脚本的 sleep 命令配合 Crontab 即可完成这一功能

# 例如
date && sleep 30s && date

# 利用sleep休眠30s来延迟执行另一个cmd
[root@peipei3514 ~]# crontab -e
*/1 * * * * date >> /tmp/date.log
*/1 * * * * sleep 30s; date >> /tmp/date.log

特别说明


通过 /etc/crontab 文件,我们可以清楚地看到每个字段的含义及取值范围,此处不再进行赘述。

特殊字符的用法
特殊字符 含义
*(星号) 代表所有可能的值,只要其他值满足都执行,表示任何时候都匹配
,(逗号) 用逗号隔开表示该字段取值。例如:”A,B,C” 表示A或者B或者C时执行命令
-(减号) 两个可取值的整数之前的取值范围。例如:”A-B”表示A到B之间时执行命令
/n(斜杠) 时间间隔频率。例如:”*/A”表示每隔A分钟(小时等)执行一次命令
特殊说明
  • 系统任务调度我们可以通过 /etc/crontab 文件直接配置。用户任务调度我们一般通过 crontab 命令来进行配置,用户任务调度的配置保存 /var/spool/cron/ 目录下,并以用户名称命名。新创建的 cron job,不会马上执行,至少要过2分钟才执行。如果重启 crond 则马上执行。
  • 当 crontab 突然失效时,可以尝试 /etc/init.d/crond restart 解决问题。或者查看日志看某个 job 有没有执行h或者报错 tail -f /var/log/cron
  • 运行 crontab -r需要特别谨慎。它从 Crontab 目录(/var/spool/cron)中删除用户的 crontab 文件。删除了该用户的所有 crontab。

使用示例


  • 每晚的21:30重启apache
30 21 * * * service httpd restart
  • 每月1、10、22日的4:45重启apache
45 4 1,10,22 * * service httpd restart
  • 每月1到10日的4:45重启apache
45 4 1-10 * * service httpd restart
  • 每隔两分钟重启apache服务
*/2 * * * * service httpd restart
1-59/2 * * * * service httpd restart
  • 晚上11点到早上7点之间,每隔一小时重启apache
#注:分钟不能为*,否则意思为晚上11点到早上7点之间,任何一分钟都可以重启apache
0 23-7/1 * * * service httpd restart 
  • 每天18:00至23:00之间每隔30分钟重启apache
0,30 18-23 * * * service httpd restart
0-59/30 18-23 * * * service httpd restart

####定时任务不执行的问题


使用crontab时经常会遇到的一个问题是,在命令行下能够正常执行的命令或脚本,设置了定时任务时却不能正常执行。造成这种情况的原因一般是因为crond为命令或脚本设置了与登录shell不同的环境变量。

[root@peipei3514 ~]# head -3 /etc/crontab 
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
[root@peipei3514 ~]#
[root@peipei3514 ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@peipei3514 ~]#

这里 crond 的 PATH 和 shell 中的值不同,PATH环境变量定义了 shell 执行命令时搜索命令的路径。

对于系统级别的定时任务,这些任务更加重要,大部分 Linux 系统在 /etc 中包含了一系列与 cron 有关的子目录:/etc/cron.{hourly,daily,weekly,monthly},目录中的文件定义了每小时、每天、每周、每月需要运行的脚本,运行这些任务的精确时间在文件/etc/crontab中指定。如:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

对于24小时开机的服务器来说,这些任务的定期运行,保证了服务器的稳定性。但注意到这些任务的执行一般都在凌晨,对于经常需要关机的Linux计算机(如笔记本)来说,很可能在需要运行 cron 的时候处于关机状态,cron 得不到运行,时间长了会导致系统变慢。对于这样的系统,Linux引入了另一个工具 anacron 来负责执行系统定时任务

anacron的目的并不是完全替代 cron,是作为 cron 的一个补充。anacron 的任务定义在文件/etc/anacrontab中:

# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7       25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly

与cron是作为守护进程运行的不同,anacron是作为普通进程运行并终止的。对于定义的每个任务,anacron在系统启动后将会检查应当运行的任务,判断上一次运行到现在的时间是否超过了预定天数(/etc/anacrontab中任务行第一列),如果大于预定天数,则会延迟一个时间(/etc/anacrontab中任务行第二列)之后运行该任务。这样就保证了任务的执行。关于anacron的更多内容,请查阅相关文档。

你可能感兴趣的:(Linux)