cron 计划任务
在Linux中,cron是默认的计划任务调度服务,我们可以使用crontab命令对其进行管理。cron服务默认随Linux开机启动,而且运行非常稳定。我们可以通过cron让程序按照一定逻辑定时执行,像定时爬虫采集,定时生成报告邮件,定时数据库备份等都可以用cron来进行调度。这篇笔记以Ubuntu16.04为例介绍cron服务的管理和crontab命令的使用。
cron存在的问题
补充:然而,cron也有巨大的缺陷。
最大的缺陷就是cron是通过cron表达式来编写计划任务调度规则的,而且crontab命令也没有一个能输出之后几次调度时间的命令选项,这让复杂的计划任务逻辑定义成为灾难。尽管cron表达式不复杂,但和图形界面比起来,缺点就是你写完是完全无法确定自己写的对不对的,计划任务调度的通常都是十分重要的系统部分,但计划任务和真实时间相关,我们又没法及时测试,这就像开发时不给数据库不让测试组测试,让你改一个直接上生产环境的系统bug。
另一个问题是cron对于大量任务调度规则的管理系统几乎没有,我们只能编辑一个crontab配置文件,调度规则全写在一个配置文件中,如果有几十个计划任务规则还好,几百个就很难维护了。即使把任务按用户划分,也缺乏统一管理功能,是极其难用的(要浪费许多时间用复杂的Linux命令实现)。
还有个问题,就是cron对于所要调度的程序也是完全没有管理的。说白了,cron就是定时执行一个命令,我们通常把一个任务写成一份shell脚本,用cron去调用。然而,一大堆shell脚本经过几波人的维护,甚至还有互相调用的状况,这时基本就没人敢改动升级了。
此外,cron对于远程计划任务部署、单独的计划任务开启停止等管理功能几乎没有,这些计划任务可能是业务逻辑的一部分,一切对它们的改动却要手动通过ssh进服务器,修改crontab配置文件,重启cron服务,这简直麻烦的无法想象。
最后一个问题,就是服务器迁移的问题,如果我们配置了大量cron计划任务的服务器现在必须迁移到另一台新服务器上,这个就很不方便了。
cron服务管理
systemctl status cron
Ubuntu下,cron服务名字就是cron,我们可以使用systemd相关命令进行管理。当cron配置文件修改后,我们需要重启cron服务以使配置文件生效。
crontab的使用
我们一般用到的crontab命令其实很简单,这里只介绍两个最基本的用法,它们基本能实现我们全部的需求。
编辑该用户的crontab配置文件:
crontab -e
查看该用户的crontab配置文件:
crontab -l
cron服务是可以根据用户进行配置的。
Linux的cron表达式
Linux下的cron表达式由5位组成,构成如下:
分 时 日 月 星期
除此之外,还有一些特殊意义的字符:
*:代表任意值,:指定枚举值-:指定范围/:指定步长
例子
上面介绍的规则很简单,我们看几个例子就明白了。
# 每小时第15分执行命令
15 * * * * <命令>
# 每小时第15分和第45分执行命令
15,45 * * * * <命令>
# 每天10:30执行命令
30 10 * * * <命令>
# 每天8-10时的第30分执行命令
30 8-10 * * * <命令>
# 每隔两天的7:30执行命令
30 7 */2 * * <命令>
上面例子其实就比较复杂了,完全超出了我们可能遇到的情况。我们遇到的一般都是每小时、每天X时,每月X日X时执行调度任务。
另外要注意的是,如果执行的命令有输出内容,我们可以将其重定向以自己记录日志,Ubuntu16.04下默认不会记录,而是直接将其丢弃。例子:
*/5 * * * * /home/ubuntu/xx.sh > /home/ubuntu/log/xx.log 2>&1
注:2>&1是个固定写法,表示把标准错误(stderr)也输出到标准输出(stdout)的文件描述符。
另外,cron服务的运行日志在/var/log/syslog下(它不包含上面提到的标准输出内容),这个系统日志文件大家都比较熟,这里就不过多说明了。
配置文件注释
crontab配置文件中用#开头的行表示注释,建议对每个计划任务添加注释说明,便于后期维护。
Linux crontab表达式与Quartz表达式
有两个概念很容易弄混:
- Linux的crontab表达式我们一般称为“crontab表达式”或“cron表达式”。
- Quartz是OpenSymphony开发的定时任务调度框架(Java),Quartz也有一个代表定时计划的表达式,我们一般叫它“quartz表达式”或“cron表达式”。
quartz表达式由6-7位构成的,crontab表达式由5位构成,两者语法相近,但quartz表达式更严谨,更精确。
注:quartz读作[kwɔ:rts],翻译为石英,也可以指计时用的石英振荡器、基于石英的钟表
补充一些注意点
- 编辑crontab时要注意用户的对应关系,比如指定脚本路径,如果使用
~代表家目录,而crontab使用root用户执行,因为用户对不上很容易出错,最好写完整路径,例如bash /home/ubuntu/xxx/xxx.sh - crontab执行命令时没有环境变量存在,例如用到
ifconfig命令,在crontab中就无法执行,一种解决方案是执行时手动添加环境变量,另一种解决方案是使用命令的完整路径,例如/sbin/ifconfig