Crontab学习日志

Crontab是Linux下一个强大的计划任务工具.

基本上Linux发行版上都会默认安装的工具.

检测安装

可以通过使用

1
2
3
crontab -l
# OR
service crond status

来检测是否安装.

如果没有,你可以先好好凝视一下你的服务器或者虚拟机,也许它是假的:).

接着使用yum install crontabs(Cent OS)进行安装.

7.7的更新: 在新版的CentOS6|7上crontab使用了新的程序包. 可以使用rpm进行查看

1
2
[root@WWW ~]$ rpm -q cronie
cronie-1.4.11-14.el7_2.1.x86_64

另外还可以看到有一个叫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
2
3
4
5
crontab [-u | user] [-l | -r | -e] [-i]
-l: 列出所有任务
-e: 编辑任务
-r: 移除所有任务
-i: 同-r一起使用, 使用交互式模式让用户有选择的进行移除.(和大部分的交互效果一样)

在cron任务中, %是有特殊的意义 所以是要进行转义的. 另外在cron中, 如果想要获得秒级的运行就要使用这样的形式:

1
* * * * * for min in 0 1 2; do echo "exec."; sleep 20; done

其实这里使用到的sleep指令不仅仅是执行秒的睡眠, 还可以进行分钟和小时, 甚至天的. 只要加上单位就行

配置文件

作为我们修改的对象,只有知道怎么书写任务,才可以更好的使用, 接下来就来看一下Crontab的配置文件的组成.

1
2
3
4
5
6
* * * * * [user-name] COMMAND
| | | | |__星期0~7(0/7均表示周日)
| | | |____月份1~12
| | |______日期1~31
| |________小时0~23
|__________分钟0~59

为更好地理解这些参数,请看下面的一些实例

1
2
3
4
5
6
7
8
9
10
11
12
# 每天晚上21:30重启服务器
30 21 * * * service httpd restart
# 每月1, 10, 22日的21:30重启服务器
30 21 1,10,22 * * service httpd restart
# 每月1到10日4:45重启Apache
45 4 1-10 * * service httpd restart
# 每隔2分钟打印一个日志
*/2 * * * * tail -n 5 /var/log/pptpd.log
# 每奇数分钟打印一个日志
1-59/2 * * * * tail -n 5 /var/log/pptpd.log
# 每天晚11:00到第二天早上7点, 每隔一小时重启Apache
0 23-7/1 * * * service httpd restart

简单的小结一下:

* 表示任何时候都匹配(Universal 通配符 /摊手)
可以用”A,B,C”表示 A || B || C
使用”A-B”表示 range(A,B)
用”*/A”表示每A分钟(小时..等)执行一次

每一条任务都是有用户依托的,因此在跟踪运行时会发现类似这样的记录:

1
2
3
4
5
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)
Apr 27 00:48:01 localhost crond[619]: (*system*) RELOAD (/etc/cron.d/sysstat)
Apr 27 00:48:01 localhost crond[619]: (tester) ORPHAN (no passwd entry)
Apr 27 00:48:01 localhost CROND[21556]: (root) CMD (/usr/local/sa/agent/secu-tcs-agent-mon-safe.sh /usr/local/sa/agent > /dev/null 2>&1)
Apr 27 00:48:01 localhost CROND[21557]: (root) CMD (/usr/local/qcloud/stargate/admin/start.sh > /dev/null 2>&1 &)

可以看到有tester.root的任务在执行.

Crontab的常见异常和错误

Crontab的常见错误有以下几点:

  • 环境变量
  • CLI双引号中使用%时, 未加反斜线 \
  • 第三和第五个域之间执行的是或操作
  • 分钟设置误用

一个一个来说明一下.

首先,我们来做个小实验,在当前用户的.bash_profile内加上下面的内容:

1
2
APPDIR=/etc
export APPDIR

接着使用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.