Crontab 实例

2019-12-08
标签: LINUX

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

实例

这里是一些常用的例子:

一小时之内

描述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,

一天之内

描述cron 语法例子
每天整点执行0 * * * *
@hourly
0:00,2:00,3:00,……23:00
每小时的15分执行15 * * * *0:15,2:15,3:15,……23:15
每天 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,……

一周之内

描述cron 语法例子
每周六中午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

一月之内

描述cron 语法例子
每月1日的凌晨0点执行0 0 1 * *
@monthly
每月1日 00:00
每月25日的17点执行0 17 25 * *每月25日 17:00
每月的第一个周日执行精细控制 一节每月第一个周日

一年之内

描述cron 语法例子
每单数月份的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=    #错误示范

一个完整的例子

HOME=/home/yourname\
PATH=/home/yourname/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\
SHELL=/bin/bash\
MAILTO=""

1 * * * * command

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 中看到是和邮件相关的报错,可以尝试下面的方法:

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

# apt install mailutils

精细控制

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

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

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

配合 test 使用

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

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

  • 每隔17分钟

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

定时监控的例子

请看这篇: 监控 Jenkins agent 是否存活的脚本

如果您对本站内容有疑问或者寻求合作,欢迎 联系邮箱邮箱已到剪贴板

标签: LINUX

欢迎转载本文,惟请保留 原文出处 ,且不得用于商业用途。
本站 是个人网站,若无特别说明,所刊文章均为原创,并采用 署名协议 CC-BY-NC 授权。