0x01.cron是什么
cron该词来源于希腊语chronos(χρόνος),原意是时间。是一款类Unix的操作系统下的基于时间的任务管理工具。用户可以通过cron在固定时间、间隔下,运行指定任务(可以是命令和脚本)。
cron的操作由crontab
(cron 表)文件驱动,该文件是一个配置文件,用于指定按给定计划定期运行的shell命令。crontab
文件存储在保存作业列表和cron守护程序的其他指令的位置。 用户可以拥有自己的个人crontab文件,并且通常有一个系统范围的crontab
文件(通常在/etc
或/etc
的子目录中),只有系统管理员才能编辑。
要新添加一个定时任务,需要编辑crontab文件(即cron表),在其中添加相关任务即可,定时任务的编写规则见第三条。
0x02.crontab命令语法
代码语言:javascript复制crontab [ -u user ] { -l | -r | -e }
说明:
-u user
参数可以设定某一个用户的cron表,前提是必须要有相关权限(比如root权限),才能够设定其他人的crontab文件。如果不使用-u user
的话,就是表示设定自己的crontab文件-e
:执行文字编辑器来设定时程表,内定的文字编辑器是vi-r
:删除目前的cron表中的所有任务-l
:列出目前cron表中的所有任务
综上,简单总结基本的常用命令:
直接编辑crontab文件:
代码语言:javascript复制crontab
# 这个命令执行完之后,直接接受控制台中的输入流作为任务命令
用编辑器编辑crontab文件:
代码语言:javascript复制crontab -e
删除当前所有的任务规则:
代码语言:javascript复制crontab -r
列出目前所有的定时任务:
代码语言:javascript复制crontab -l
其中,可以在crontab之后加上-u user
的参数来操作指定用户对应的crontab文件,前提是必须要有相关权限(比如root权限)。否则就是操作自己的crontab文件。
0x03.crontab任务规则
1、标准规则
简单理解就是执行时间
命令
的形式。
其中时间是由五个域组成,分别为分钟、小时、天、月份、星期,每个域可以放置单一或多个数值,同时每个域之间都有空格来进行区分,如下所示:
代码语言:javascript复制┌──────────── 分钟 (0 - 59)
│ ┌──────────── 小时 (0 - 23)
│ │ ┌──────────── 天 (1 - 31)
│ │ │ ┌──────────── 月份 (1 - 12)
│ │ │ │ ┌──────────── 星期中的某天 (0 - 6) (从周日开始算到周六)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
* * * * * [用户名] <要执行的命令>
在用户层次的crontab文件中,用户名
是可以省略的参数,而系统层次的crontabs文件的任务经常会指定一个或以上的用户进行执行,因此需要增加用户名
字段。
注:
- 在某些系统里,星期日也可以为7
- 不很直观的用法:如果日期和星期同时被设定,那么当其中的一个条件被满足时,指令便会被执行。而不是同时满足
- 为方便个人记忆,前5个域可称之为分时日月周
表示时间的每个域里除了可以是具体数值,还可以是表达式或者是多个数值:
- 逗号(
,
)列举出多个数值,例如:1,3,4,7 * * * * echo hello world
表示在每小时的1、3、4、7分时,打印"hello world"。 - 连词符(
-
)表示一个数值范围,例如:1-6 * * * * echo hello world
,表示每小时的1到6分钟内,每分钟都会打印"hello world"。 - 星号(
*
)代表任何可能的值。例如:在“小时域”里的星号等同于“每一个小时”。 - 百分号(
%
) 表示“每"。例如:* * * * * echo hello world
表示,每10分钟打印一回"hello world"。 表格说明: 域 是否必填 允许的值 分钟 是 0–59 小时 是 0–23 天 是 1–31 月份 是 1–12、JAN–DEC 星期中的某天 是 0–6 、SUN–SAT
2、非标准规则
仅由某些cron程序的扩展版本支持,标准版本并不支持。以下这部分是在维基百科英文版本部分就着谷歌大概翻译出来的,如果有误,请以维基百科词条中的原文内容为准,词条链接在文末。
L
:“L”代表“最后”。 当在星期字段中使用时,它允许指定诸如给定月份的“最后一个星期五”(“5L
”)之类的构造。 在day-of-month
字段中,它表示该月的最后一天。W
:'W' 字符允许用于日期字段。 此字符用于指定离给定日期最近的工作日(周一至周五)。 例如,如果将“15W
”指定为day-of-month
字段的值,则其含义为:“距该月的15日最近的工作日”。 因此,如果15号是星期六,触发器会在14号星期五触发。 如果15日是星期日,触发器会在16日星期一触发。 如果15号是星期二,那么它会在15号星期二触发。 但是,如果将“1W
”指定为月份中的某天的值,并且第1天是星期六,则触发器会在第3天的星期一触发,因为它不会“跳过”一个月的天数边界。 仅当月中的某一天是一天,而不是天范围或天列表时,才可以指定“W”字符#
:'#' 允许用于星期字段,并且后面必须跟一个1到5之间的数字。 它允许指定诸如给定月份的“第二个星期五”之类的结构。 例如,在星期
字段中输入5#3
对应于每个月的第三个星期五?
:用于代替“*``**”以将月中的某天或一周中的某天留空/
:用于表示跳过某些给定的数。例如,*/3
在小时域中等于0,3,6,9,12,15,18,21
等被3整除的数;H
:'H'表示替换了“散列”值。 因此不是一个固定的数字,例如表示每小时后的20分钟,表示该任务在一个未指定但不变的时间执行一次。 这允许随着时间的推移分散任务,而不是让所有任务同时开始并争夺资源。
0x04.其他
1、定时任务生效时间
需要注意的是,添加定时任务之后crontab需要等待几分钟才会生效,若要使立即生效需要重启cron服务:
代码语言:javascript复制service cron restart
2、定时任务不生效
如果crontab定时任务不生效,可以排查以下几点:
1、Linux的时间与互联网时间不一致,而crontab中写的互联网时间
2、定时执行的.sh文件无执行权限
3、crontab进程未启动,crontab进程会每分钟去扫描/etc/crontab中的定时任务,故修改后无需重启该进程(重启只会让定时配置马上生效)
4、crontab进程配置文件中未指定具体执行用户
3、环境变量相关问题
在crontab文件中定义多个调度任务时,需要特别注意的一个问题就是环境变量的设置,因为我们手动执行某个脚本时,是在当前shell环境下进行的,程序能找到环境变量;而系统自动执行任务调度时,除了默认的环境,是不会加载任何其他环境变量的。因此就需要在crontab文件中指定任务运行所需的所有环境变量。
不要假定cron知道所需要的特殊环境,它其实并不知道。所以用户要保证在shell脚本中提供所有必要的路径和环境变量,除了一些自动设置的全局变量。以下三点需要注意:
脚本中涉及文件路径时写绝对路径;
脚本执行要用到环境变量时,通过source命令显式引入,例如:
代码语言:javascript复制#!/bin/sh
source /etc/profile
当手动执行脚本没问题,但是crontab不执行时,可以尝试在crontab中直接引入环境变量解决问题,例如:
代码语言:javascript复制* * * * * . /etc/profile; /xx/xx/test.sh
参考资料:
Linux crontab 命令 | 菜鸟教程 (runoob.com)
cron - Wikipedia
Cron - 维基百科,自由的百科全书 (wikipedia.org)
OpenWrt任务定时cron_hzlarm的博客-CSDN博客_openwrt 定时任务