Crontab 实例

发表时间 ·

Linux 设置周期性定时任务的常用系统工具是crontab,本文列举一些实用的例子。

实例

这里是一些常用的例子:

描述 cron 语法 例子
一小时之内
每分钟执行 * * * * * 0:01,0:02,0:03,……23:59
每2分钟执行 */2 * * * * 0:00,0:02,0:04,……23:58
每小时的2分执行 2 * * * * 0:02,1:02,2:02,3:02,……,23:02
每半小时执行 */30 * * * * 0:00,0:30,1:00,1:30,2:00,……,23:30
分钟是50分的倍数时执行 */50 * * * * 0:00,0:50,1:00,1:50,2:00,2:50,……
每17分钟执行 精细控制 0:00,0:17,0:34,0:51,1:08,1:25,1:42,……
一天之内
每天整点执行 0 * * * *
@hourly
0:00,2:00,3:00,……23:00
每天 12点5分 执行 5 12 * * * 12:05
每天 10点到18点 整点执行 0 10-18 * * * 10:00,11:00,12:00,……,18:00
每天 10点和18点 半点执行 30 10,18 * * * 10:30,18:30
从0点开始,每隔4小时 半点执行 30 */4 * * * 0:30,4:30,8:30,12:30,……
从1点开始,每隔4小时 半点执行 30 1-23/4 * * * 1:30,5:30,9:30,13:30,……
一周之内
每周六中午12点执行 0 12 * * 6
0 12 * * sat
每周六 12:00
每周二、四、六中午12点执行 0 12 * * 2-6/2 每周二、四、六 12:00
周末中午12点执行 0 12 * * sat,sun 每周六、日 12:00
每周日的凌晨0点执行 0 0 * * 0
@weekly
每周日 00:00
每周一、二 的 8点和12点执行 0 8,12 * * 1,2 每周一8:00,12:00,每周二8:00,12:00
一月之内
每月1日的凌晨0点执行 0 0 1 * *
@monthly
每月1日 00:00
每月25日的17点执行 0 17 25 * * 每月25日 17:00
每月的第一个周日执行 精细控制 一节 每月第一个周日
一年之内
每单数月份的25日的17点执行 0 17 25 */2 * 1月25日 17:00,3月25日 17:00

crontab 的形式

系统中有两个crontab:

系统级别

系统级别的 crontab 有两种形式: /etc/crontab 文件和 /etc/cron.d 目录下的文件,只有管理员能修改。和下面用户级别的 crontab 不同的是,这两套文件随系统自动存在,而不像 用户级别 的 crontab 一样需要安装。系统级别的 crontab 中的命令前带有用户名,相比之下,更为安全、更常用的是用户级别的 crontab:

用户级别

每个用户默认是没有crontab的,初次执行 crontab 命令时,系统将为这位用户安装 crontab 文件,然后可以使用 crontab -e 编辑 或者 crontab -l 来显示 crontab 文件内容。

crontab 文件中合法的语句只有两类:

  • 环境变量
  • 定时任务

crontab 文件环境变量

在定时命令前设置环境变量,以保证命令的正确执行。格式为 name=value

SHELL

比如 crontab 默认使用的 shell 是 /bin/sh ,如果想设为 bash,需要像下面这样设置:

SHELL=/bin/bash

PATH

crontab 默认的 PATH/usr/bin:/bin ,而不是用户登录后所看到的 PATH 变量,所以如果你不愿意使用绝对路径调用命令,而且命令也不在前面这两个 PATH 中,那么需要事先修改 PATH 变量:

PATH=/your/specific/path

容易出错的是,crontab 中不能像其他shell文件一样做变量替换,所以在 crontab 中下面的写法将达不到目的:

PATH=/your/specific/path:$PATH   # 错误示范

一个例外是,bash 中可以使用波浪线(~)表示用户的主目录(在 /etc/passwd 中规定的):

SHELL=/bin/bash
PATH=~/your/specific/path

HOME

命令被调起的起始路径,也就是 HOME 变量,是用户自己的主目录(在 /etc/passwd 中规定的)

MAILTO

当定时任务执行后,系统将给相关用户发站内邮件,如果不希望发出邮件,需要事先将 MAIL 命令定义为空值:

MAILTO=""

注意这里空值必须用引号表示,而不能只写一个等号

MAILTO=   #错误示范

crontab 时间语法

定时任务中有 6 个字段:

分钟  小时  日期  月份  星期  命令

前五个字段表示时间条件,可能的取值为:

  • *

星号表示:每个、不要求、无所谓、随便、无论、任意值、全部值、所有值、总是、从第一个可能的值到最后一个可能的值,对于小时字段来说, * 等效于 0-23;对于星期字段来说, * 等效于 0-6;对于月份字段来说, * 等效于 1-12

  • -

连字符表示范围(闭区间):比如 1-4 等效于 1,2,3,4

  • ,

逗号表示:列表,可以列出所有希望的值,比如 1,2,3,4

  • -,-组合

逗号和连字符组合,比较容易理解:比如: 8-12, 14-18

  • /

斜杠 表示 “从第一个值开始,每*个”,比如小时中的 */4 表示从0点开始的每4小时, 1-7/4 等效于 1,5

  • 名称

月份和星期字段还可以使用名称的头三个字母来增强可读性(大小写均可),比如: jan,wed

  • 预设周期

@yearly 命令于每年1月1日(无论星期几)的凌晨0点执行,等效 0 0 1 1 *
@monthly命令于1日(无论几月、星期几)的凌晨0点执行, 等效 0 0 1 * *
@weekly 命令于星期日的凌晨0点执行,等效 0 0 * * 0
@daily命令于每日的凌晨0点执行,等效 0 0 * * *
@hourly命令于每小时的0分执行,等效 0 * * * *

  • 日期和星期

如果日期和星期都有定义(非*号的值),那么将取 逻辑,只要满足任意一个条件即可执行。

crontab 命令格式

第六个字段是执行的命令,命令中的百分号 (%)会被认为是换行符,百分号以前的部分是执行的命令,以后的部分会被当做标准输入。

如果命令中必须包含百分号,则需要用反斜杠(\)转义,不然百分号将不起作用。比如正常情况下 date 命令的执行格式是:

$ date "+%Y%m%d"

到了 crontab 里就要写成:

25 8 * * * date "+\%Y\%m\%d"

crontab 不工作的原因

如果 crontab 不工作,可以到 /var/log/syslog 中查看原因。一般会有如下可能:

PATH 变量错误

上节 提到, PATH 默认是最小集: /usr/bin:/bin ,和用户自己定义 shell 里的 PATH 变量不同,所以即使用户自己在 shell 中可以正确执行,也不说明 cron 一定能找到需要执行的命令。

解决方案:在命令之前指定 PATH 变量

SHELL 的选择

上节 提到,SHELL 默认是 sh,所以如果一些命令只能在bash下执行,则需要预先设置 SHELL 变量

解决方案:在命令之前指定 SHELL 变量

邮件服务

上节 提到,执行命令后需要发出邮件,一些系统中未预先安装邮件命令。如果从 /var/log/syslog 中看到是和邮件相关的报错,可以尝试下面的方法:

解决方案:安装邮件的相关工具:

# sudo apt install mailutils

精细控制

crontab 的设计意图是精准的指定“(年,月,日,时,分)”的时间点坐标。

run this command at this time on this date. 在指定的日期,指定的时间点执行。

因为各种时间点坐标的进位周期各不相同(60分、24小时、30天、12月),所以一些只关注周期而忽略时间点坐标的需求,只靠原生的 cron 语法就不能达到目的了。需要 test 命令或者 cron 语法组合完成,比如:

配合 test 使用
  • 每月第二个周六
0 4 8-14 * * test $(date +\%u) -eq 6 && echo "第二个周六"

解释:test 命令用来检验参数是否为 true,当日期在每月的8日到14日之间时,每天执行 test 表达式,当 $(date +\%u) 结果等于 6 时,就能断定当天是当月的第二个周六。

  • 每隔17分钟

每分钟检查当前的分钟数是否能被17整除


相关文章

  除非特别说明,本站文章都来自原创,并采用 署名协议 CC-BY 授权。欢迎转载,请保留原文链接