linux atd and crond
Linux atd and crond
你也许想让你的linux系统在每天下午5:00提醒你去跑步,或者最近你听说十天后商场降价促销,你想写在自己的日程表上避免忘记,或者因为你总是在电脑前coding,每年都会忘记女朋友的生日,当然,更linuxic的应用场景是,日常的备份工作,日志分析工作,这些都是需要根据特定时间进行执行的,而atd和crond就是为此而生的
atd和crond到底是什么
在系统启动过程中会开启一些进程,用于提供系统服务(或称其为daemon进程),例如:http服务,ftp服务,数据库服务等等,而atd和crond只是其中众多系统服务中的两个罢了,它们一直在系统的后台运行,你可以这样看,atd和crond不停的查看任务时间表(就是记录任务何时该执行的一个文件),到时间了它们就让任务在后台运行起来,用一句话来说,atd和crond是用于定时执行任务的daemon进程
**注:**atd和crond是daemon进程,被它们管理的作业叫作例行性程序,为了避免同编程领域定义的例程(封装了实现细节的函数)混淆,本文中一概用“定时任务”或“任务”一词来描述被管理的作业,并且我们将被atd和crond管理称为“被托管”
Differences between atd and crond
atd在指定的时刻执行一次任务,crond每到指定的时间就执行任务,也就是说atd适合管理临时,偶然性的任务,而crond适合管理间隔一定周期就要执行一次的任务
如何将任务告知atd和crond
不知你用过数据库没有,数据库软件通常都会提供客户端程序和服务端程序(其实不仅仅是数据库,很多软件都采用client/server的架构,这样有利于软件解耦),假设MySQL有mysql-client和mysql-server,其中mysql-server负责数据库的管理以及数据读写,而mysql-client是提供给用户跟数据库交互的,通常用来发送各种sql语句给mysql-server。我们将视野拉回来,你可以将mysql-server想成daemon process(其实它就是),所以显然我们现在需要的是一个类似与mysql-client的东西,能够将我们的任务告知daemon process(atd和crond),这个类似的东西分别是at和crontab程序,你可以将你的任务通过这两个程序分别发送给atd和crond,至于任务的描述,显然没有sql语句那么复杂,一般包含“什么时候执行什么任务”就可以了,具体的使用见后面的介绍
启动atd服务
**注:**一般情况,系统开机已经启动了atd
查看atd是否已经启动:
$ service atd status # 如果返回 atd is running说明atd已经启动
启动atd:
$ service atd start # 或者/etc/init.d/atd start
设置atd是开机时自动启动的:
$ chkconfig atd on
at的使用
新建一个任务:
$ at TIME # 运行该命令后进入下面的交互模式,输入要被执行的命令即可
at>
TIME的格式,[HH:MM | HH:MM YYYY-MM-DD | HH:MM[am|pm] [Month] [Date] | [now|HH:MM[am|pm]] + number [minutes|hours|days|weeks]]
查看当前用户的所有任务:
$ at -l # 或者使用atq命令,返回任务号和时间
查看某个任务的具体内容:
$ at -c number # 任务号对应的任务的内容
移除某个任务:
$ at -d number # 或者用atrm命令
注:
1. at的工作原理是,将任务以文本文件的形式写到了/var/spool/at目录中,每个任务对应一个文件,之后atd会读取执行该任务
2. 任务中用到的命令以及文件路径都要使用绝对路径,这样做是为了避免与执行at命令时所在目录中的文件名冲突
3. 在任务中任何输出到stdout或stderror的命令(例:echo)都会被自动重定向到用户在系统中的mail中(/var/spool/mail/username),如果你想要输出到终端,需要:`echo "hello world" > /dev/tty1`重定向到相应的终端设备
4. 如果任务中没有任何内容会输出到stdout(或stderror),系统是不会向用户mail发送消息的,如果想要强制发送消息到mail,需要:`at -m TIME`
at的增强版:batch
试想这样一种情况,定时任务到时间要运行了,但是此时系统上面已经有较多的程序在运行,也就是说CPU正在奋力的在不同的程序之间切换,我们知道当系统中运行太多程序时,可能使得CPU忙于频繁的切换而实际运行程序的时间减少,也就是说如果我们的定时任务可以在系统运行太多程序时延迟执行可能效果会更好,batch
命令就是为此而生的,它的使用跟at
没有差别,并且它也是使用atq
和atrm
来管理任务的
对使用at的控制
因为at涉及到一些安全问题,所以控制对at的使用十分有必要,控制的机制是通过白名单和黑名单机制实现的
-
白名单,/etc/at.allow,该文件中记录了可以使用at命令的用户名,如果该文件存在则通过该文件控制at的使用,被记录的用户名可以使用at,没被记录的不能使用at,如果该文件不存在,则以黑名单为准
-
黑名单,/etc/at.deny,该文件中记录了不能使用at命令的用户名,如果该文件也不存在(只有白名单不存在时才查找该文件),则只有root有权使用at,如果该文件存在,则被记录的用户不能使用at命令,不被记录的则可以使用at
-
值得注意的是,默认系统仅提供了文件at.deny且该文件是空的,也就是说所有用户都可以使用at命令
启动crond
查看是否已经启动(一般没这个必要,系统上很多任务依赖它的):
$ service crond status # 返回crond is running说明已经启动
启动crond:
$ service crond start
设置开机启动crond:
$ chkconfig crond on
cron名称由来
在古希腊神话中有位时间之神,叫作chronos,而cron就是由此而来的,至于cron发送任务的程序叫作crontab,这是因为cron任务是以用户为单位进行管理的,所以记录cron任务的格式就像一张table
crontab的使用
编辑用户任务表
$ crontab -e # 进入crontab的交互模式进行用户任务表的编辑,任务描述使用特定的格式,下一小节作介绍
查看用户任务表
$ crontab -l
移除用户有所任务
$ crontab -r # 注意不是删除一个任务而是所有任务,删除一个任务请用编辑功能
root用户可以编辑操纵其他用户的任务表
# crontab -u username [-l|-e|-r]
注:
1. crontab发送的任务被记录在/var/spool/cron/username中,不同于at的是,这里并不是每个任务对应一个任务文件,而是每个用户对应一个文件,该用户发送的所有任务都写入这个文件中,此后crond每隔一段时间查看一次该文件
2. cron任务具有日志记录功能,日志位置在/var/log/cron
cron任务的描述格式
每个任务占一行,行有分为若干列
mintue(0~59) hour(0~23) day(1~31) month(1~12) week(0~7) command-string
其中用于描述时间的列,可以使用一些具有特殊含义的字符
* 表示任意值
, 用于分隔一列中的多个值
- 用于表示时间段
/ 用于表示时间间隔
对于上面的字符直接理解起来有点困难,还是看几个例子吧
12 13 * * 2 command-string # 表示每周二的13:12执行命令
12 11,13 * * 2 command-string # 表示每周二的11:12和13:12都会执行命令
20 11-13 * * 2 command-string # 表示每周二的11:00到13:00每隔20分钟执行一个任务
*/10 * * * * command-string # 表示每隔10分钟执行一次任务
**注:**描述week时,使用0或7都可以表示星期天,week和day-month不可共存
系统中的cron任务
前面使用crontab是用于管理用户自己的定时任务,然而系统中有很多任务是定时的,而这些任务并不是用户通过crontab进行管理的,对于你来说好像这些系统的定时任务随系统一直在运行的,由系统对它们进行管理(这种从设计思想上区分系统任务和用户任务是很重要的,把属于谁的任务交到谁的手中则更加重要),我们知道cron任务都是被托管于crond服务的,也就是说系统任务也应该描述在某处等待crond去读取而且描述的格式应该跟/var/spool/cron/username类似,事实正是如此,描述系统cron任务的文件在/etc/crontab,它的格式同用户任务描述类似,之所以说是类似,因为有若干不同点:
1. 在文件顶部定义了一些变量,有SHELL,PATH,MAILTO,HOME
2. 任务描述需要指定任务将以哪个用户的身份运行(前面使用crontab指定的任务当然是以运行crontab用户身份运行),紧跟在时间列后面写入用户名即可
3. 你即可以直接将任务要执行的命令写入任务描述的最后一列,也可以将命令以可执行文件的形式写入目录(系统默认存放目录为/etc/cron.*)后使用run-parts载入(执行目录中的所有可执行文件),具体的做法如下:
01 * * * * root run-parts /etc/cron.hourly
对使用crontab的控制
跟上面提到对at的控制类似的,只是白名单为/etc/cron.allow,黑名单为/etc/cron.deny
anacron是什么
试想这样一个情形,你有一个任务将在今天23:59执行,但是你在22:00已经关机去睡觉了,那么该任务在今天23:59的这次执行是不是就被忽略了呢?如果没有anacron的话确实如此,anacron的存在就是为了确保命令在指定的时间间隔内一定执行,不论系统在此期间关机与否,它的存在不是为了取代cron的(但你可以将它想成跟cron系统任务类似的东西)仅仅是一个补充,而是确保cron的某些定时任务一定得以执行
工作原理,anacron也是使用文件描述要运行的anacron任务的,该文件为/etc/anacrontab,我系统中默认任务描述内容为:
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
可以看出anacron任务是以天为间隔(period)的,第二字段指定了anacron任务到达执行时间后可以延迟执行的分钟数,第三字段job-identifier是任务的id,该id用作记录任务最近一次执行时间的文件的文件名(该文件的位置在/var/spool/anacron/your-job-identifier,不同于at和cron的地方在于,后两者都在/var/spool/中记录任务描述内容,而anacron记录的是任务最近执行的timestamp),记录anacron任务最近执行的时间 ,是anacron确保任务定期(即便关机)执行的关键所在,anacron通过查看/etc/anacrontab和/var/spool/anacron/your-job-identifier判断anacron任务是否从最后一次执行后有遗漏执行的情况,如果有遗漏则执行anacron任务,最后一个字段是任务要执行的命令,该字段使用了nice命令以确保命令执行占有低优先级,避免对系统资源的争夺
anacron与acron的关系
从上面的/etc/anacrontab文件最后一个字段看到,系统默认的anacron任务就是执行放置在/etc/cron.*目录中的任务,之前说过我们应该将期望系统按照某个时间间隔执行的cron任务(以可执行文件的形式)放在这些目录下面,然后在/etc/crontab的最后一列通过命令run-parts加入这些任务,因为放在这些目录中的任务一般是系统任务,系统任务可不希望在关机期间有遗漏执行的情况发生,所以这类任务托管给anacron更为合适,这正是你在/etc/anacrontab文件中看到的,它将系统的daily,weekly,monthly类任务都管理起来,但如果/etc/crontab也同时管理这些任务的话,会发生什么情况呢?任务的重复执行,因为cron任务的执行并不会更新有anacron管理的时间记录文件,所以我的系统默认/etc/crontab是没有加载已经被托管与anacron的任务
从上面对anacron的描述中你应该已经感觉到anacron自己会定期的执行(不然怎么及时的查看被遗漏执行的任务),我们知道周期性定期执行一个任务需要使用crond来托管,确实是这样,anacron是托管于crond中的一个系统任务,在我的系统上通过 ls /etc/cron*/*anacron*
可以找到脚本/etc/cron.hourly/0anacron,其中最终要的内容是调用 /usr/sbin/anacron -s
命令(对于anacron命令稍后再作解释),这样anacron daemon就开始查看有无任务被遗漏,重复如此,每小时调用一次anacron命令
anacron软件架构
如同前面的软件一样anacron也是client/server架构,只是这两个家伙都叫作anacron
安装anacron软件(基于RedHat)
$ yum install anacron
查看anacron服务端运行状态
$ service anacron status
开启anacron服务
$ service anacron start
确保anacron服务开机启动
$ chkconfig anacron on
通过客户端命令可以给服务段anacron发送指令
$ anacron -s [job-identifier...] # hey,服务端的老兄看看有没有什么定时任务被遗漏执行了
$ anacron -f [job-identifier...] # 老兄甭管任务有没有执行,现在都执行一遍
$ anacron -n [job-identifier...] # 老兄那些没有被执行的任务立马给我跑起来,不要延时
$ anacron -u [job-identifier...] # 老兄我没让你执行任务,你把记录任务最近执行时间的文件内容更新为当前时间
at,cron,anacron该用谁
根据具体的应用场景选择不同的命令很重要,不要手里拿着锤子看什么都像钉子
-
at,非周期性的用户任务,任务描述文件位置/etc/spool/at/task-file
-
crontab,周期性的用户任务,任务描述文件位置/etc/spool/cron/username,任务运行日志/var/log/cron
-
对于周期性的系统任务需要编辑/etc/crontab文件,即可直接写入命令,也可通过run-parts载入/etc/cron.*中的可执行文件
-
对于周期性并且希望关机也不错过执行的任务需要编辑/etc/anacrontab文件,即可直接写入命令,也可通过run-parts载入/etc/cron.*中的可执行文件,但要注意不要与/etc/crontab有重复
linux中已有的定时任务
-
更新locate数据库
locate数据库是用于记录系统中文件路径信息的(位于/var/lib/mlocate),当使用locate命令时会用到该数据库,因为系统中添加移除文件是很常见的事情,所以定期对文件信息进行收集是很必要的,updatedb可以进行文件信息的收集并更新数据库,系统默认将任务updatedb托管于crond
-
更新whatis数据库
whatis数据库是用于存放man page信息的,当使用whatis命令时会用到该数据库,因为man page信息的增减使得定期更新该数据库变得很有必要,系统默认将更新wahtis数据库的任务托管于crond
-
更新rpm和yum软件安装记录
rpm和yum都是用于软件安装的工具,它们记录了软件安装的信息,所以卸载,更新软件时很方便,但是如果软件的文件变动了,而rpm和yum不知到的话就很麻烦了,所以系统默认将收集并更系软件安装信息的任务托管给crond
-
临时目录中文件的删除
很多软件都会在临时目录/tmp中创建临时文件,如果从来不清理该目录的话,磁盘空间会被该目录耗光的,这种任务交给crond再合适不过
-
log rotate
系统中的日志文夹太大的话,会影响到日志读写的性能,所以定期将日志写入新文件中是个迫切的需求,该功能可以有log rotate完成,系统默认将该任务托管于crond
-
日志分析
系统需要定期分析日志文件(logwatch可以胜任)并将结果发送给root,默认logwatch托管于crond