Linux中的crontab命令的简单介绍及其用法

2020-03-16

在开始讲解之前

在开始讲解之前先请大家看一个视频,以便对crontab有一个基本的概念.

看完这个视频相信一部分读者已经得到了收获,也可以继续看我慢慢讲解吧.

什么是crontab以及crontab能做什么

crontab呢其实就是Linux操作系统中用来设置定时任务的一个工具,通过crontab我们可以在Linux操作系统中设置定时任务,也就是可以使得特定的任务在特定的时间得以执行,而且是周期式的,比如说,通过crontab可以设定每天的凌晨2点进行服务器的缓存更新和备份,毕竟这个时候网站的访客也比较少,所以不会有什么影响,可以设置crontab每天晚上9点整自动地将当天网站服务器的访问记录access.log发送到指定的地方供分析和审计,或者设置在每周的周几的多少点多少分,清理一次临时文件目录/tmp/*,这些通过crontab来实现,可以说都是非常方便的.

要怎么做

要开始学习crontab的用法可以首先运行

man crontab

打开crontab的文档页面,这是比较全的文档所以可以不用一下子全看完,首先说的是

maintain crontab files for individual users

也就说crontab是可以分别维护每一个用户设定的定时任务计划的,各个用户的工作安排是互不干扰的,比较Linux是学习Unix的,而Unix是一个多用户操作系统,然后有两个命令

crontab -u <用户名> -l # 需要sudo权限
crontab -l # 如果权限不够

crontab -e

其中-u选项加参数指定的是具体的用户名,这很好理解因为每个用户都有自己单独的一份crontab设置,然后-l就是list的意思,就是列出给定用户(如果有-u选项)或者当前用户(没有-u选项)的crontab设置.所谓crontab设置的内容无非就是在什么时候执行什么任务,就这么简单,只不过这个时间周期的表达式可以非常的简洁和灵活,我们稍后会介绍.

然后-e选项其实就是编辑(edit)当前用户的crontab设置的意思啦,很简单.

编辑自己的crontable

运行

crontab -e

命令(不需要加任何参数)会进入当前用户的crontable(日程表)编辑界面,建议在这之前将EDITOR环境变量设置成自己熟悉的文本编辑器,比如说

export EDITOR=`which vim` # 设置使用vim来打开crontable
export EDITOR=`which nano` # 设置使用nano来打开crontable
export EDITOR=`which emacs` # 设置使用emacs来打开crontable

推荐还是使用vim来编辑,vim很容易学.尽量不要自己编辑crontab的配置文件,除非是在写自动化地脚本程序.

crontab -e首先会创建一个临时文件/tmp/crontab.xxxxxxx来供你编辑crontable.

crontab的格式

在自己真的开始编辑crontab之前呢,可以运行

man 5 crontab # 中间的数字5不能少,man 5是语法手册的意思

来查看crontab的语法和范例,一般来说是这样的

* * * * * command

有5个位置被空格分隔开来,然后最右边的是要执行的命令,命令和前面的位置也是空格分隔开来,前面这5个位置其实就是用来设置时间的,怎么说呢?请看下面的示意图

* * * * * command_to_run 一周的周几,范围0到6 一年的哪月,范围1到12 一个月的第几天,范围1到31 一天的第几个小时,范围0到23 一个小时的第几分钟,范围0到59

有几点可能需要单独地说明一下,这五个描述时间的位置呢其实也是可以取星号*的,含义待会我会说,然后第五个位置,取0代表周天,取7也可以代表周天,1到6就是周一到周六,第四个位置1到12代表每一年的第1个月到第12个月,第三个位置呢,就是一个月的第一天,第二个位置取0代表凌晨12点,也就是24小时制的小时,第一个位置也是24小时制的分钟了,取0代表整点.

由上面这张示意图我们可以看到,crontab的记录是一行一行的,示意图里面给出的是其中的一行,一行记录(一条记录)有五个位置用于描述时间,一个单独的位置用于描述命令,这总共六个位置由空白符(制表符或者空格)分隔开,总体上看,一条crontab记录大致是符合以下这样的模式:

t1  t2  t3  t4  t5  s

其中t1到t5的相对位置和示意图当中的是一样的,s就代表要执行的命.要明白crontab记录的语法,如果成功地从解释器的角度来理解,那会清晰很多.

那么,假设现在crontab的解析程序读取到了

t1  t2  t3  t4  t5 s

这条记录,它要如何处理呢?

首先,当然解释器是可以有很多种解析crontab记录的方式的,我们下面演示其中比较好理解的一种,也是比较简单的一种,首先这个,简单crontab记录解释器(一下简称解释器)可以从右到左地扫描这么一条crontab记录.

t1  t2  t3  t4  t5  s
                    ^

解释器最先读到s,现在它知道了,要执行的命令是s(不是字面意义上的s,这里s是个符号,我们用它指代具体的命令,比如说s可以是"echo hello"这样的命令),那么仅仅知道要执行的是s还是不能完全定义一条crontab记录:要什么时候指向s呢?继续向做扫描吧,crontab解释器这样想.

t1  t2  t3  t4  t5  s
                ^

现在解释器的字符扫描指针刚扫描完了t5,如果t5是星号*,那么解释器就指定了,哦,原来一周的每一天,都要执行s啊,如果t5不是星号*,而是一个具体的数字,那么解释器就会看做是在具体的每周的星期几来执行s,可是,对于这两种情况来说,仅仅知道要在一周的周几执行或者说一周的每一天都执行,还是不确定啊,要执行s的那天,具体又是什么时候执行呢?带着疑问,解释器啊又继续往左边扫描,期待以此来接近答案.

t1  t2  t3  t4  t5  s
            ^

t4呢就是指一年的哪个月执行s,一年有12个月,所以t4的取值范围或者是星号*,表示一年的每个月都执行,或者是具体的数字(或者数字和符号组合),表示具体的某个月,或者其他规则.因为知道一年的哪个月来执行s还是不够的,所以又继续往左扫描:

t1  t2  t3  t4  t5  s
        ^

t3的意思是每个月的第多少天执行s,因为每个月最多有31天,所以t3可以取星号*或者1到31或者是1到31和符号的组合来描述一个月到底第几天或者哪些天来执行s,同样地,知道一个月的哪几天或者哪天执行s还是有很多不确定,继续往左扫描:

t1  t2  t3  t4  t5  s
    ^

t2的意思是每天的多少时或者在第几个和第几个小时执行s,0代表凌晨12点,其他数字1到23对应1到23点,也就是凌晨1点一直到晚上11点,是的,知道了在哪个小时来执行s还是不确定,继续:

t1  t2  t3  t4  t5  s
^

到这个时候,我相信,不管是我们讨论的这个简单crontab解释器,还是屏幕前的你,都已经知道,并且确定,将会在什么时候执行s.t1的意思是在每个小时的多少分钟和第几分钟执行s.

具体的案例

现在运行

man 5 crontab

打开crontab的语法介绍页面,按Control+D翻到文末的案例介绍,如图所示

Crontab Examples

现在我们尝试用刚才简单crontab解释器的解释方法来解释其中的每一个例子:

第一个是

5 0 * * * $HOME/bin/daily.job >> $HOME/tmp/out 2>&1

命令太长可以不看,但是我们知道时间设定是

5 0 * * *

首先(看箭头)

5 0 * * *
        ^

表示在每周的每一天都执行,然后(一直看着箭头所指位置)

5 0 * * *
      ^

表示在每一年的每一个月都执行,那每个月的哪天执行呢?

5 0 * * *
    ^

每个月的每一天都执行,每一天的哪个小时执行呢?

5 0 * * *
  ^

每一条的凌晨12点执行,凌晨12点的第几分钟执行呢?

5 0 * * *
^

凌晨12点的第5分钟执行,秒级的精度在crontab中暂时无法设置的,所以确定到第几分钟,就可以认为这一条crontab记录的时间设置已经确定了.

也就是说

5 0 * * *

表示要在每年的每个月的每天的00:05执行给定的命令.

这个太简单了,我们看一个难一点的

0  22  *  *  1-5
             ^

这里出现了一个新的符号,1-5也就是表示1,2,3,4,5,那么结合所处的位置来看呢,很简单,就是每年的1月到5月这5个月都要执行,这五个月的什么时候呢?

0  22  *  *  1-5
          ^

在这5个月中,每周的每一天都执行,还不够具体

0  22  *  *  1-5
       ^

在这5个月中,每个月的每一天,不管这个月有多少条,都执行,哪一天的什么时候执行呢?

0  22  *  *  1-5
^

每天的22:00执行.

现在综合一下:每年的第1个月到第5个月这5个月,的每周的每一天,并且每月的每一天的,的22:00执行相应的命令.

最后一个例子,我也写累了,就快写完了

23  0-23/2  *  *  * 

最右边的大家都懂了,现在只要理解每一天的什么时候执行就可以了

23  0-23/2  *  *  * 
    ^

0-23代表0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23这些个小时,/2表示间隔的意思,间隔2个小时,什么意思呢?从0时开始,0加2等于2,也就是下一次是在第2小时,以此类推,也就是0,2,4,6,8,10,12,14,16,18,20,22这些个小时执行,并且

23  0-23/2  *  *  * 
^

在这些个小时的23分执行,也就是,在每一年的每一月的每一天的

00:23, 02:23, 04:23, 06:23, 08:23, 10:23, 12:23, 14:23, 16:23, 18:23, 20:23 和 22:23 执行相应的命令.

至此,希望您已经知道如何在crontab中按照自己的意愿设定crontab记录了.

总结

在这篇文章中,我们介绍了Linux中的定时任务功能,具体是通过crontab命令来设置,我们知道crontab能针对每一个用户单独地设置和保存定时任务,我们最后讲解了crontab记录的语法:先是从解释器的角度理解,最后结合实际案例加深理解.

感谢花时间阅读到这来.

参考文献

[1] (37) Linux/Mac Tutorial: Cron Jobs - How to Schedule Commands with crontab - YouTube

[2] crontab.guru - the cron schedule expression editor

技术交流linuxcrontab

修复CloudCone VPS无法自动同步时间的问题

使用Hugo Shortcode和svg标签构建自定义图形!