Crontab是Linux下一个强大的计划任务工具.
基本上Linux发行版上都会默认安装的工具.
检测安装
可以通过使用
1 | crontab -l |
来检测是否安装.
如果没有,你可以先好好凝视一下你的服务器或者虚拟机,也许它是假的:).
接着使用yum install crontabs
(Cent OS)进行安装.
7.7的更新: 在新版的CentOS6|7上crontab使用了新的程序包. 可以使用rpm进行查看
1 | [root@WWW ~]$ rpm -q cronie |
另外还可以看到有一个叫cronie-anacron-1.4.11-14.el7_2.1.x86_64
的程序包.
这个anacron
是什么呢?
这里我们把整个周期性任务计划相关的程序包来进行一下小结:
cronie
: 主程序包, 提供了crond
守护进程和相关的辅助工具.cronie-anacron
:cronie
的补充程序, 用于监控cronie
任务执行情况, 比如当指定时间执行的任务未能正常运行, 则anacron
会再随后进行任务的启动crontabs
: 包含CentOS提供的系统维护的任务
因此要确保crontab
正常运行, 就要先保证crond
正常在运行.
小试牛刀
先来感受一下定时任务的便利吧:
1 | crontab -e |
进入编辑界面,在最后添加一行之后, 保存退出.
1 | */1 * * * * date >> /tmp/date.log |
接着你可以使用tail -f /tmp/date.log
, 这时候就会发现每分钟这个文件就会得到更新 显示当期的时间
简述
crontab 的核心在于crond这个进程, 这个系统服务每分钟都会从配置文件中刷新任务.
有时间到了后crond就会启动这个任务.
而crontab这个就是用户操作,用来调整定时任务的工具了, 最后, 配置文件负责以文件的形式设置定时任务.
用户的cron
: 每个用户都有一个专门的cron
任务文件: /var/spool/cron/USERNAME
crontab
的使用方法:
1 | crontab [-u | user] [-l | -r | -e] [-i] |
在cron任务中, %
是有特殊的意义 所以是要进行转义的. 另外在cron
中, 如果想要获得秒级的运行就要使用这样的形式:
1 | * * * * * for min in 0 1 2; do echo "exec."; sleep 20; done |
其实这里使用到的sleep
指令不仅仅是执行秒的睡眠, 还可以进行分钟和小时, 甚至天的. 只要加上单位就行
配置文件
作为我们修改的对象,只有知道怎么书写任务,才可以更好的使用, 接下来就来看一下Crontab的配置文件的组成.
1 | * * * * * [user-name] COMMAND |
为更好地理解这些参数,请看下面的一些实例
1 | # 每天晚上21:30重启服务器 |
简单的小结一下:
* 表示任何时候都匹配(Universal 通配符 /摊手)
可以用”A,B,C”表示 A || B || C
使用”A-B”表示 range(A,B)
用”*/A”表示每A分钟(小时..等)执行一次
每一条任务都是有用户依托的,因此在跟踪运行时会发现类似这样的记录:
1 | Apr 27 00:47:01 localhost CROND[21437]: (root) CMD (/usr/local/sa/agent/secu-tcs-agent-mon-safe.sh /usr/local/sa/agent > /dev/null 2>&1) |
可以看到有tester.root的任务在执行.
Crontab的常见异常和错误
Crontab的常见错误有以下几点:
- 环境变量
- CLI双引号中使用%时, 未加反斜线 \
- 第三和第五个域之间执行的是或操作
- 分钟设置误用
一个一个来说明一下.
首先,我们来做个小实验,在当前用户的.bash_profile内加上下面的内容:
1 | APPDIR=/etc |
接着使用source .bash_profile
使得立即生效,在CLI下试试echo $APPDIR
,会输出/etc
说明没有问题.
但是当我们在crontab中加上这样的定时任务后*/1 * * * * echo $APPDIR>/tmp/appdir.log
.
会发现这个文件中只有空行,并没有获得$APPDIR
这个环境变量值.
所以,在进行任务设置时要小心这个不能识别的问题.
对于第二和第三个,一起看一下:
首先回顾一下之前的参数说明第三和第五个他们是有关系的(星期和日),所以这里他们在实际运行时是采取的或的操作,(这个先存疑,使用在线工具测试是正常的,但教学来源表明这是或的操作)已解决,采取的或操作.
即:
1 | 59 1 1-7 4 0 /root/a.sh |
这个任务表示什么?
如果你觉得是四月的第一个星期日的1:59分执行bash脚本,那就错了.
他执行的次数远比原来多.这是因为他会在每月的1-7日以及周日执行,大约会执行11次.
所以,应该这么写:
1 | 59 1 1-7 4 * test `date -\%w -eq 0 && /root/a.sh` |
这样经过验证的结果就是正确的.
另外,在这个任务中我们使用了反斜线\
,在CLI下这个操作是不需要的,但在计划任务里是需要的
分钟数设置时的易错点: 如果想要执行每两小时的任务,也许你会这么写:* 0,2,4,6,8,10,12,14,16,18,20,22 * * * COMMAND
,但事实上,这样是错误的,因为他意味这在这些时的每分钟都会执行一次.
正确的方式应该要把分钟数设置成0,也就是这个样子的:0 */2 * * * COMMAND
.
如果想让Crontab执行秒级的任务,就要借助Shell的sleep方法, 也就是像这样: date && sleep 0.5s && date
.