- 第16章 例行性工作(crontab)
- 再设置一下开机时就启动这个服务,免得每次重新启动都得再来一次!
- 上面这行信息在说明,第 4 个 at 工作将在 2009/03/14 的 15:38 进行!
- 而执行 at 会进入所谓的 at shell 环境,让你执行多重命令。
- !/bin/sh <==就是通过 bash shell 。
- atrun uid=0 gid=0
- mail root 0
- 你可以看到命令执行的目录 (/root),还有多个环境变量与实际的命令内容。
- 你瞧瞧! at 还可以在一个工作内输入多个命令!
- 上面说的是在 2009/03/17 的 23:00 有一项工作,该项工作命令执行者为
- root,而且,该项工作的工作号码 (jobnumber) 为 5 号喔!
- 没有任何信息,表示该工作被删除了!
- 此时会进入 vi 的编辑界面让你编辑工作。注意到,每项工作都是一行。
- 分 时 日 月 周 |<==============命令串========================>|
- 注意,若仅想要删除一项工作而已的话,必须要用 crontab -e 去编辑
- 如果想要全部的工作都删除,才使用 crontab -r 。
- run-parts
- 16.4 可唤醒停机期间的工作任务
- 刚好是每天、每周、每月有调度的工作目录!查看一下每天的任务
- 所以其实也仅是执行 anacron -u 的命令,因此我们得来谈谈这个程序!
- 天数单位为天;延迟时间单位为分钟;工作名称定义可自定义;
- 命令串则通常与 crontab 的设置相同!
- 上面则是三个工作名称的时间记录文件以及记录的时间戳
- 详细的 chkconfig 说明我们会在后续章节提到,注意看 3, 5
- 的选项,都是 on 。那就是有启动啦!开机时才会执行的意思。
第16章 例行性工作(crontab)
学习了基础篇也一阵子了,你会发现到为什么系统经常会主动进行一些任务?这些任务到底是谁在设置工作的?如果你想要让自己设计的备份程序可以自动在系统下面执行,而不需要手动来启动它,又该如何处置?这些例行的工作可能又分为“单一”工作与“循环”工作,在系统内又是哪些服务在负责?如果你想要在家人的生日前一天就发出一封信件提醒自己不要忘记,可以办得到吗?学习完本章后,这些问题就可以迎刃而解了。
16.1 什么是例行性工作
每个人或多或少都有一些约会或者是工作,有的工作是例行性的,例如每年一次的加薪、每月一次的工作报告、每天需要的打卡等;有的工作则是临时发生的,例如刚好总公司有高官来访,需要你准备演讲器材等。用在生活上面,例如每年家人的生日、每天的起床时间等,还有突发性的计算机大降价(真希望天天都有)等。
像上面这些例行性工作,通常你得要记录在日历上面才能避免忘记。不过,由于我们经常在计算机前面的缘故,如果计算机系统能够主动通知我们的话,那么不就轻松多了!这个时候Linux的例行性工作调度就可以派上场了,在不考虑硬件与我们服务器的连接状态下,我们的Linux可以帮你提醒很多任务,例如:每一天早上8:00要服务器连接上音响,并启动音乐来唤你起床;而中午12:00希望Linux 可以发一封信到你的邮件信箱,提醒你可以去吃午餐了;另外,在每年你家人生日的前一天,先发封信提醒你,以免忘记这么重要的一天。
那么Linux的例行性工作是如何进行调度的呢?所谓的调度就是将这些工作安排执行的流程。咱们的Linux调度就是通过crontab与at来实现的。这两个有什么异同?就让我们来瞧瞧先!
16.1.1 Linux 工作调度的种类:at,cron
从上面的说明当中,我们可以很清楚地发现两种工作调度的方式:
一种是例行性的,就是每隔一定的周期要来办的事项;
一种是突发性的,就是这次做完以后就没有的那一种(如计算机大降价。)
那么在Linux下面如何实现这两个功能呢?那就得使用at与crontab这两个命令了。
at:at是个可以处理仅执行一次就结束调度的命令,不过要执行at时,必须要有atd这个服务(第18章)的支持才行。在某些新版的distributions中,atd可能默认并没有启动,那么at这个命令就会失效,不过我们的CentOS默认是启动的。
crontab:crontab这个命令所设置的工作将会循环一直进行下去。可循环的时间为分钟、小时、每周、每月或每年等。crontab除了可以使用命令执行外,也可编辑/etc/crontab来支持。至于让crontab可以生效的服务则是crond这个服务。
下面我们先来谈一谈Linux的系统到底在做什么事情,怎么有这么多的工作调度在进行呢?然后再回来谈一谈at与crontab这两个好命令。
16.1.2 Linux 上常见的例行性工作
如果你曾经使用过Linux一阵子了,那么你大概会发现到Linux会主动帮我们进行一些工作呢!例如自动进行在线更新(on-line update)、自动进行 updatedb(第 7 章谈到的 locate 命令)更新文件名数据库、自动进行日志文件分析(所以root经常会收到标题为logwatch的信件)等。这是由于系统要正常运行的话,某些在后台的工作必须要定时进行的缘故。基本上Linux系统常见的例行性任务有:
进行日志文件的轮替(log rotate)
Linux 会主动将系统所发生的各种信息都记录下来,这就是日志文件(第 19 章)。由于系统会一直记录日志信息,所以日志文件将会越来越大。我们知道大型文件不但占容量,还会造成读写性能的困扰,因此适时将日志文件数据挪一挪,让旧的数据与新的数据分别存放,则比较可以有效地记录日志信息。这就是 log rotate 的任务!这也是系统必要的例行任务。
日志文件分析logwatch的任务
如果系统发生了软件问题、硬件错误等,绝大部分的错误信息都会被记录到日志文件中,因此系统管理员的重要任务之一就是分析日志文件。但你不可能手动通过 vim 等软件去检视日志文件,因为数据太复杂了!我们的 CentOS 提供了一个程序“logwatch”来主动分析日志信息,所以你会发现,你的root老是会收到标题为logwatch的信件,那是正常的。你最好也能够看看该信件的内容。
新建locate的数据库
在第 7 章我们谈到 locate 命令时,我们知道该命令是通过已经存在的文件名数据库来进行系统中文件名的查询。我们的文件名数据库是放置到/var/lib/mlocate/中。问题是,这个数据库怎么会自动更新啊?这就是系统的例行性工作所产生的效果。系统会主动进行updatedb。
whatis数据库的建立
与 locate 数据库类似的,whatis 也是个数据库,这个 whatis 是与 man page 有关的一个查询命令,不过要使用whatis命令时,必须要拥有whatis数据库,而这个数据库也是通过系统的例行性工作调度来自动执行的。
RPM软件日志文件的新建
RPM(第23章)是一种软件管理的机制。由于系统可能会经常更改软件,包括软件的新安装、非经常性更新等,都会造成软件文件名的区别。为了方便未来跟踪,系统也帮我们将文件名做个排序的记录呢!有时候系统也会通过调度来帮助RPM数据库的重新生成。
删除临时文件
某些软件在运行中会产生一些临时文件,但是当这个软件关闭时,这些临时文件可能并不会主动被删除。有些临时文件则有时间性,如果超过一段时间后,这个临时文件就没有用了,此时删除这些临时文件就是一件重要的工作,否则磁盘空间会被耗光。系统通过例行性工作调度执行名为tmpwatch的命令来删除这些临时文件呢!
与网络服务有关的分析行为
如果你有安装类似WWW服务器软件(一个名为apache的软件),那么你的Linux系统通常就会主动分析该软件的日志文件,同时某些认证的网络信息是否过期的问题,我们的 Linux系统也会很亲和地帮你进行自动检查!
其实你的系统会进行的例行性工作与你安装的软件多少有关,如果你安装过多的软件,某些服务功能的软件都会附上分析工具,那么你的系统就会多出一些例行性工作。像鸟哥的主机还多加了很多自己编写的分析工具,以及其他第三方软件的分析软件,鸟哥的Linux工作量可是非常大的。因为有这么多的工作需要进行,所以我们当然得要了解例行性工作的处理方式。
16.2 仅执行一次的工作调度
首先,我们先来谈谈单一工作调度的运作,那就是at这个命令的运行!
16.2.1 atd的启动与at 运行的方式
要使用单一工作调度时,我们的Linux系统上面必须要有负责这个调度的服务,那就是atd这个玩意儿。不过并非所有的 Linux distributions 都默认会把它打开的,所以,某些时刻我们必须要手动将它启用才行。启用的方法很简单,就是这样:
[root@www ~]# /etc/init.d/atd restart
正在停止 atd: [ 确定 ]
正在激活 atd: [ 确定 ]
再设置一下开机时就启动这个服务,免得每次重新启动都得再来一次!
[root@www ~]# chkconfig atd on
重点是那个“正在启动(或starting)”选项就OK啦!那表示启动是正常的。这部分我们在第18章会谈及。如果你真的有兴趣,那么可以自行到/etc/init.d/atd 这个 shell script 内去瞧一瞧先,至于那个chkconfig,你也可以使用man先查阅一下,我们第18章再介绍。
at的运行方式
既然是工作调度,那么应该会有产生工作的方式,并且将这些工作排进日程表中。那么生成工作的方式是怎么进行的?事实上,我们使用at这个命令来生成所要运行的工作,并将这个工作以文本文件的方式写入/var/spool/at/目录内,该工作便能等待atd这个服务的取用与执行了,就这么简单。
不过,并不是所有的人都可以进行at工作调度。为什么?因为安全的理由,很多主机被进行所谓的“绑架”后,最常发现的就是他们的系统当中多了很多的黑客程序(cracker program),这些程序非常可能运用工作调度来执行或搜集系统信息,并定时回报给黑客团体。所以,除非是你认可的账号,否则先不要让他们使用at吧!那怎么使用at的管理呢?
我们可以利用/etc/at.allow与/etc/at.deny这两个文件来进行at的使用限制呢!加上这两个文件后,at的工作情况其实是这样的:
1.先寻找/etc/at.allow这个文件,写在这个文件中的用户才能使用at,没有在这个文件中的用户则不能使用at(即使没有写在at.deny当中);
2.如果/etc/at.allow不存在,就寻找/etc/at.deny这个文件,若写在这个at.deny的用户则不能使用at,而没有在这个at.deny文件中的用户就可以使用at了;
3.如果两个文件都不存在,那么只有root可以使用at这个命令。
通过这个说明,我们知道/etc/at.allow是管理较为严格的方式,而/etc/at.deny则较为松散(因为账号没有在该文件中,就能够执行at了)。在一般的distributions当中,由于假设系统上的所有用户都是可信任的,因此系统通常会保留一个空的/etc/at.deny文件,意思是允许所有人使用 at 命令的意思(你可以自行检查一下该文件)。不过,万一你不希望有某些用户使用 at的话,将那个用户的账号写入/etc/at.deny即可!一个账号写一行。
16.2.2 实际运行单一工作调度
单一工作调度的进行就使用 at这个命令。这个命令的运行非常简单!将at加上一个时间即可!基本的语法如下:
[root@www ~]# at [-mldv] TIME
[root@www ~]# at -c 工作号码
参数:
-m :当 at 的工作完成后,即使没有输出信息,以 email 通知用户该工作已完成。
-l :at -l 相当于 atq,列出目前系统上面的所有该用户的 at 调度;
-d :at -d 相当于 atrm ,可以取消一个在 at 调度中的工作;
-v :可以使用较明显的时间格式列出 at 调度中的任务列表;
-c :可以列出后面接的该项工作的实际命令内容。
TIME:时间格式,这里可以定义什么时候要进行 at 这项工作的时间,格式有:
HH:MM ex> 04:00
在今日的 HH:MM 时刻进行,若已超过该时刻,则明天的 HH:MM 进行此工作。
HH:MM YYYY-MM-DD ex> 04:00 2009-03-17
强制规定在某年某月的某一天的特殊时刻进行该工作!
HH:MM[am|pm] [Month] [Date] ex> 04pm March 17
也是一样,强制在某年某月某日的某时刻进行!
HH:MM[am|pm] + number [minutes|hours|days|weeks]
ex> now + 5 minutes ex> 04pm + 3 days
就是说,在某个时间点“再加几个时间后”才进行。
老实说,这个at命令的执行最重要的地方在于“时间”的指定了。鸟哥喜欢使用“now+…”的方式来定义现在过多少时间再进行工作,但有时也需要定义特定的时间点来进行!下面的范例先看看。
范例一:再过五分钟后,将 /root/.bashrc 寄给 root 自己
[root@www ~]# at now + 5 minutes <==记得单位要加 s 。
at> /bin/mail root -s "testing at job" < /root/.bashrc
at> <EOT> <==这里输入 [ctrl] + d 就会出现 <EOF> 的字样!代表结束!
job 4 at 2009-03-14 15:38
上面这行信息在说明,第 4 个 at 工作将在 2009/03/14 的 15:38 进行!
而执行 at 会进入所谓的 at shell 环境,让你执行多重命令。
范例二:将上述的第 4 项工作内容列出来查阅
[root@www ~]# at -c 4
!/bin/sh <==就是通过 bash shell 。
atrun uid=0 gid=0
mail root 0
umask 22
….(中间省略许多的环境变量项目)….
cd /root || { <==可以看出,会到执行 at 时的工作目录去执行命令
echo 'Execution directory inaccessible' >&2
exit 1
}
/bin/mail root -s "testing at job" < /root/.bashrc
你可以看到命令执行的目录 (/root),还有多个环境变量与实际的命令内容。
范例三:由于机房预计于 2009/03/18 停电,我想要在 2009/03/17 23:00 关机
[root@www ~]# at 23:00 2009-03-17
at> /bin/sync
at> /bin/sync
at> /sbin/shutdown -h now
at> <EOT>
job 5 at 2009-03-17 23:00
你瞧瞧! at 还可以在一个工作内输入多个命令!
事实上,当我们使用 at 时会进入一个 at shell 的环境来让用户执行工作命令,此时,建议你最好使用绝对路径来执行你的命令,比较不会有问题。由于命令的执行与PATH变量有关,同时与当时的工作目录也有关联(如果有牵涉到文件的话),因此使用绝对路径来执行命令会是比较一劳永逸的方法。为什么呢?举例来说,你在/tmp 中执行“at now”然后输入“mail root -s "test" < .bashrc”,问一下,那个.bashrc的文件会是在哪里?答案是“/tmp/.bashrc”!因为at在运行时,会跑到当时执行at命令的那个工作目录的缘故。
有些朋友会希望我要在某某时刻在我的终端机显示出Hello的字样,然后就在at里面执行“echo"Hello"”这样的信息,等到时间到了,却发现没有任何信息在屏幕上显示,这是什么原因啊?这是因为at 的执行与终端机环境无关,而所有standard output/standard error output 都会传送到执行者的mailbox 去啦!所以在终端机当然看不到任何信息。那怎么办?没关系,可以通过终端机的设备来处理。假如你在 tty1 登录,则可以使用“echo "Hello" > /dev/tty1”来替代。
要注意的是,如果在at shell内的命令并没有任何的信息输出,那么at默认不会发Email给执行者的。如果你想要让at无论如何都发一封Email告知你是否执行了命令,那么可以使用“at -m 时间格式”来执行命令,at 就会传送一个信息给执行者,而不论该命令执行有无信息输出了!
at有另外一个很棒的优点,那就是“后台执行”的功能了!什么是后台执行啊?很难了解吗?其实与bash的nohup(第17章)类似。鸟哥提我自己的几个例子来给你听听,你就明白了!
脱机继续工作的任务:鸟哥初次接触 UNIX 为的是要跑空气质量模式,那是一种大型的程序,这个程序在当时的硬件下面跑,一个案例要跑3天。由于鸟哥也要进行其他研究工作,因此经常使用 Windows 98 来连接到 UNIX 工作站跑那个 3 天的案例。结果你也该知道,Windows 98 连开 3天而不死机的几率是很低的。而死机时,所有在Windows上的连接都会中断。包括鸟哥在跑的那个程序也中断了,明明三个钟头就跑完的程序,由于死机害我又得跑3天。
另一个常用的时刻则是例如上面的范例三,由于某个突发情况导致你必须要进行某项工作时,这个at就很好用啦!
由于在 at 工作调度的使用上,系统会将该项 at 工作独立出你的 bash 环境中,直接交给系统的atd 程序来接管,因此,当你执行了 at 的工作之后就可以立刻脱机了,剩下的工作就完全交给 Linux管理即可!所以,如果有长时间的网络工作时,使用at可以让你免除网络断线后的困扰。
at工作的管理
那么万一我执行了 at 之后,才发现命令输入错误,该如何是好?就将它删除。利用 atq 与atrm吧!
[root@www ~]# atq
[root@www ~]# atrm [jobnumber]
范例一:查询目前主机上面有多少的 at 工作调度
[root@www ~]# atq
5 2009-03-17 23:00 a root
上面说的是在 2009/03/17 的 23:00 有一项工作,该项工作命令执行者为
root,而且,该项工作的工作号码 (jobnumber) 为 5 号喔!
范例二:将上述的第 5 个工作删除!
[root@www ~]# atrm 5
[root@www ~]# atq
没有任何信息,表示该工作被删除了!
如此一来,你可以利用atq来查询,利用atrm来删除错误的命令,利用at来直接执行单一工作调度。很简单吧!不过,有个问题需要处理。如果你是在一个非常忙碌的系统下运行 at,能不能指定你的工作在系统较闲的时候才进行呢?可以的,那就使用batch命令吧!
batch:系统有空时才进行后台任务
其实batch是利用at来进行命令的执行。只是加入一些控制参数而已。这个batch神奇的地方在于:它会在CPU工作负载小于0.8的时候,才进行你所执行的工作任务。那什么是负载0.8呢?这个负载的意思是:CPU在单一时间点所负责的工作数量,不是CPU的使用率。举例来说,如果我有一个程序它需要一直使用CPU的运算功能,那么此时CPU的使用率可能到达100%,但是CPU 的工作负载则是趋近于“1”,因为CPU 仅负责一个工作嘛!如果同时执行这样的程序两个呢?CPU的使用率还是100%,但是工作负载则变成2了。明白不?
所以也就是说,当CPU的工作负载越大,代表CPU必须要在不同的工作之间进行频繁的工作切换。这样的CPU运行情况我们在第0章有谈过,忘记的话请回去瞧瞧!因为一直切换工作,所以会导致系统忙碌。系统如果很忙碌,还要额外进行 at,不太合理!所以才有 batch命令的产生!
那么 batch 如何执行命令呢?很简单,与 at 相同。例如下面的范例:
范例一:同样是机房停电,在 2009/3/17 23:00 关机,但若当时系统负载太高,则暂缓执行
[root@www ~]# batch 23:00 2009-3-17
at> sync
at> sync
at> shutdown -h now
at> <EOT>
job 6 at 2009-03-17 23:00
[root@www ~]# atq
6 2009-03-17 23:00 b root
[root@www ~]# atrm 6
你会发现其实 batch 也是使用 atq/atrm 来管理的!这样了解吗?
16.3 循环执行的例行性工作调度
相对于at是仅执行一次的工作,循环执行的例行性工作调度则是由cron(crond)这个系统服务来控制的。刚才谈过Linux系统上面原本就有非常多的例行性工作,因此这个系统服务是默认启动的。另外,由于用户自己也可以进行例行性工作调度,所以,Linux 也提供用户控制例行性工作调度的命令(crontab)。下面我们分别来聊一聊!
16.3.1 用户的设置
用户想要新建循环型工作调度时,使用的是crontab这个命令。不过,为了安全性的问题,与at类似,我们可以限制使用crontab的用户账号。使用的限制数据有:
/etc/cron.allow
将可以使用crontab的账号写入其中,若不在这个文件内的用户则不可使用crontab。
/etc/cron.deny
将不可以使用 crontab 的账号写入其中,若未记录到这个文件当中的用户,就可以使用crontab。
与at很像吧?同样,以优先级来说,/etc/cron.allow比/etc/cron.deny要优先,而判断上面,这两个文件只选择一个来限制而已,因此,建议你只要保留一个即可,免得影响自己在设置上面的判断。一般来说,系统默认是保留/etc/cron.deny,你可以将不想执行crontab的那个用户写入/etc/cron.deny当中,一个账号一行!
当用户使用 crontab 这个命令来新建工作调度之后,该项工作就会被记录到/var/spool/cron/里面去了,而且是以账号来作为判别的。举例来说, dmtsai 使用 crontab 后,他的工作会被记录到/var/spool/cron/dmtsai里面去。但请注意,不要使用vi直接编辑该文件,因为可能由于输入语法错误,会导致无法执行cron。另外,cron执行的每一项工作都会被记录到/var/log/cron这个日志文件中,所以,如果你的Linux不知道有否被植入木马时,也可以查询一下/var/log/cron这个日志文件。
好了,那么我们就来聊一聊crontab的语法吧!
[root@www ~]# crontab [-u username] [-l|-e|-r]
参数:
-u :只有 root 才能进行这个任务,也即帮其他用户新建/删除 crontab 工作调度;
-e :编辑 crontab 的工作内容;
-l :查阅 crontab 的工作内容;
-r :删除所有的 crontab 的工作内容,若仅要删除一项,请用 -e 去编辑。
范例一:用 dmtsai 的身份在每天的 12:00 发信给自己
[dmtsai@www ~]$ crontab -e
此时会进入 vi 的编辑界面让你编辑工作。注意到,每项工作都是一行。
0 12 * mail dmtsai -s "at 12:00" < /home/dmtsai/.bashrc
分 时 日 月 周 |<==============命令串========================>|
默认情况下,任何用户只要不被列入/etc/cron.deny 当中,那么他就可以直接执行“crontab -e”去编辑自己的例行性命令了。整个过程就如同上面提到的,会进入vi的编辑界面,然后以一个工作一行来编辑,编辑完毕之后输入“:wq”保存后离开 vi 就可以了。而每项工作(每行)的格式都是具有六个字段,这六个字段的意义如表16-1所示。
表16-1
比较有趣的是那个“周”。周的数字为 0 或 7 时,都代表“星期天”的意思。另外,还有一些辅助的字符,大概有下面这些,如表16-2所示。
表16-2
我们就来搭配几个例子练习看看吧!下面的案例请实际用 dmtsai 这个身份执行看看。后续的操作才能够搭配起来!
假若你的女朋友生日是5月2日,你想要在5月1日的23:59发一封信给她,这封信的内容已经写在/home/dmtsai/lover.txt内了,该如何进行?
答:直接执行 crontab -e 之后,编辑成为:
59 23 1 5 * mail kiki < /home/dmtsai/lover.txt
那样的话,每年她都会收到你的这封信。(当然,信的内容就要每年变一变啦!)
假如每五分钟需要执行/home/dmtsai/test.sh一次,又该如何?
答:同样使用 crontab -e 进入编辑:
/5 * /home/dmtsai/test.sh
那个crontab每个用户都只有一个文件存在,就是在/var/spool/cron里面。还有建议你:执行命令时,最好使用绝对路径,这样比较不会找不到执行文件。
假如你每星期六都与朋友有约,那么想要每个星期五下午4:30告诉你朋友星期六的约会不要忘记,则:答:还是使用crontab-e。
30 16 5 mail friend@his.server.name < /home/dmtsai/friend.txt
真的是很简单吧!那么,该如何查询用户目前的crontab内容呢?我们可以这样来看看:
[dmtsai@www ~]$ crontab -l
59 23 1 5 * mail kiki < /home/dmtsai/lover.txt
/5 * /home/dmtsai/test.sh
30 16 5 mail friend@his.server.name < /home/dmtsai/friend.txt
注意,若仅想要删除一项工作而已的话,必须要用 crontab -e 去编辑
如果想要全部的工作都删除,才使用 crontab -r 。
[dmtsai@www ~]$ crontab -r
[dmtsai@www ~]$ crontab -l
no crontab for dmtsai
看到了吗?crontab整个内容都不见了!所以请注意:如果只是要删除某个crontab的工作项目,那么请使用 crontab -e 来重新编辑即可!如果使用-r 的参数,是会将所有的 crontab 数据内容都删掉的,千万注意了!
16.3.2 系统的配置文件:/etc/crontab
这个crontab–e是针对用户的cron来设计的,如果是系统的例行性任务时,该怎么办呢?是否还是需要以 crontab -e 来管理你的例行性工作调度呢?当然不需要,你只要编辑/etc/crontab 这个文件就可以。有一点需要特别注意,那就是 crontab -e 这个 crontab 其实是/usr/bin/crontab 这个执行文件,但是/etc/crontab可是一个“纯文本文件”。你可以root的身份编辑一下这个文件。
基本上,cron 这个服务的最低检测限制是“分钟”,所以 cron 会每分钟去读取一次/etc/crontab与/var/spool/cron里面的数据内容,因此,只要你编辑完/etc/crontab这个文件,并且将它保存之后,那么cron的设置就自动会来执行了!
在Linux下面的crontab会自动帮我们每分钟重新读取一次/etc/crontab的例行工作事项,但是出于某些原因或者是其他的Unix系统中,由于crontab是读到内存当中的,所以在你修改完/etc/crontab之后,可能并不会马上执行,这个时候请重新启动crond这个服务吧(“/etc/init.d/crondrestart”)!
废话少说,我们就来看一下这个/etc/crontab的内容吧!
[root@www ~]# cat /etc/crontab
SHELL=/bin/bash <==使用哪种 shell 接口
PATH=/sbin:/bin:/usr/sbin:/usr/bin <==执行文件查找路径
MAILTO=root <==若有额外STDOUT,以 email将数据送给谁
HOME=/ <==默认此 shell 的主文件夹所在
run-parts
01 root run-parts /etc/cron.hourly <==每小时
02 4 * root run-parts /etc/cron.daily <==每天
22 4 0 root run-parts /etc/cron.weekly <==每周日
42 4 1 root run-parts /etc/cron.monthly <==每个月 1 号
分 时 日 月 周 执行者身份 命令串
看到这个文件的内容你大概就了解了吧!这个文件与刚才我们执行 crontab -e 的内容几乎完全一模一样!只是有几个地方不太相同:
MAILTO=root
这个选项是说,当/etc/crontab这个文件中的例行性工作的命令发生错误时,或者是该工作的执行结果有STDOUT/STDERR时,会将错误信息或者是屏幕显示的信息传给谁,默认当然是由系统直接寄发一封mail给root。不过,由于root并无法在客户端中以POP3之类的软件收信,因此,鸟哥通常都将这个 Email 改成自己的账号,好让我随时了解系统的状况!例如:MAILTO=dmtsai@my.host.name。
PATH=….
还记得我们在第11章的BASH当中一直提到的执行文件路径问题吧。这里就是输入执行文件的查找路径,使用默认的路径设置就已经很足够了。
01 root run-parts /etc/cron.hourly
这个/etc/crontab里面默认定义出四项工作任务,分别是每小时、每天、每周及每个月分别进行一次的工作!但是在五个字段后面接的并不是命令,而是一个新的字段,那就是执行后面那串命令的身份!这与用户的 crontab -e 不相同。由于用户自己的 crontab 并不需要指定身份,但/etc/crontab里面当然要指定身份。以上面的内容来说,系统默认的例行性工作是以root的身份来进行的。
那么后面那串命令是什么呢?你可以使用“which run-parts”搜寻看看,其实那是一个 bashscript。如果你直接进入/usr/bin/run-parts去看看,会发现这个命令会将后面接的“目录”内的所有文件找出来执行!这也就是说如果你想让系统每小时主动帮你执行某个命令,将该命令写成script,并将该文件放置到/etc/cron.hourly/目录下即可。
现在你知道系统是如何进行它默认的一堆例行性工作调度了吗?如果你执行“ll/etc/cron.daily”就可以看到一堆文件,那些文件就是系统提供的 script,而这堆 script 将会在每天的凌晨 4:02 开始运行!这也是为啥如果你是夜猫族,就会发现奇怪的是,Linux 系统为何早上 4:02 开始会很忙碌地发出一些硬盘转动的声音。因为它必须要进行 makewhatis, updatedb, rpm rebuild 等任务。
由于CentOS提供的run-parts这个script的辅助,因此/etc/crontab这个文件里面支持两种执行命令的方式,一种是直接执行命令,一种则是以目录来规划,例如:
命令类型
01 dmtsai mail -s "testing" kiki < /home/dmtsai/test.txt
以dmtsai这个用户的身份,在每小时执行一次mail命令。
目录规划
/5 * root run-parts /root/runcron
新建一个/root/runcron 的目录,将要每隔五分钟执行的“可执行文件”都写到该目录下,就可以让系统每五分钟执行一次该目录下的所有可执行文件。
你现在大概了解了这一个命令了吧?假设你现在有一个目录,让系统可以每2分钟去执行这个目录下的所有可以执行的文件,你可以写下如下的这一行在/etc/crontab中:
/2 * root run-parts /etc/cron.min
当然,/etc/cron.min这个目录是需要存在的。那如果我需要执行的是一个“程序”而已,不需要用到一个目录呢?该如何是好?例如在检测网络流量时,我们希望每五分钟检测分析一次,可以这样写:
/5 * root /bin/mrtg /etc/mrtg/mrtg.cfg
如何?新建例行性命令很简单。如果你是系统管理员而且你的工作又是系统维护方面的例行任务时,直接修改/etc/crontab这个文件即可。又便利,又方便管理呢!
16.3.3 一些注意事项
有的时候,我们以系统的cron来进行例行性工作时,要注意一些使用方面的特性。举例来说,如果我们有四个工作都是五分钟要进行一次的,那么是否这四个操作全部都在同一个时间点进行?如果同时进行,该四个操作又很耗系统资源,如此一来,每五分钟不是会让系统忙得要死?此时好好地分配一些运行时间就OK啦!所以,注意一下:
资源分配不均的问题
当大量使用crontab的时候,总是会有问题发生的,最严重的问题就是系统资源分配不均的问题,以鸟哥的系统为例,我有检测主机流量的信息,包括:
流量;
区域内其他PC的流量检测;
CPU使用率;
RAM使用率;
在线人数实时检测。
如果每个流程都在同一个时间启动的话,那么在某个时段时,我的系统会变的相当繁忙,所以,这个时候就必须要分别设置。我可以这样做:
[root@www ~]# vi /etc/crontab
1,6,11,16,21,26,31,36,41,46,51,56 root CMD1
2,7,12,17,22,27,32,37,42,47,52,57 root CMD2
3,8,13,18,23,28,33,38,43,48,53,58 root CMD3
4,9,14,19,24,29,34,39,44,49,54,59 root CMD4
看到了没?那个“,”分隔的时候,请注意,不要有空格符(连续的意思)!如此一来,则可以将每五分钟工作的流程分别在不同的时刻来工作,则可以让系统的执行较为顺畅。
取消不要的输出选项
另外一个困扰发生在当有执行结果或者是执行的选项中有输出的数据时,该数据将会mail给MAILTO设置的账号,那么当有一个调度一直出错(例如DNS的检测系统当中,若DNS上层主机挂掉,那么你就会一直收到错误信息)。怎么办?还记得第 11 章谈到的数据流重定向吧?直接以“命令重定向”将输出的结果输出到/dev/null这个垃圾桶当中就好了。
安全的检验
很多时候被植入木马都是以例行命令的方式植入的,所以可以由检查/var/log/cron的内容来查看是否有非你设置的cron被执行了?这个时候就需要小心一点。
周与日、月不可同时并存
另一个需要注意的地方在于:你可以分别以周或者是日、月为单位作为循环,但你不可使用“几月几号且为星期几”的模式工作。这个意思是说,你不可以这样编写一个工作调度:
30 12 11 9 5 root echo "just test" <==这是错误的写法
本来你以为9月11日且为星期五才会进行这项工作,无奈的是,系统可能会判定每个星期五做一次,或每年的9月11日分别进行,如此一来与你当初的规划就不一样了。所以,得要注意这个地方。上述的写法是不对的。
16.4 可唤醒停机期间的工作任务
如果你的 Linux 主机是作为 24 小时全天、全年无休的服务器之用,那么你只要有 atd 与 crond这两个服务来管理你的例行性工作调度即可。如果你的服务器并非 24 小时无间断开机,那么你该如何进行例行性工作?举例来说,如果你每天晚上都要关机,等到白天才启动你的Linux主机时,由于CentOS默认的工作调度都在每天凌晨4:02进行,如此一来不就一堆系统例行工作都没有人在做了。那可怎么办?此时就得要anacron这工具了!
16.4.1 什么是 anacron
anacron并不是用来替代crontab的,anacron存在的目的就在于我们上头提到的,在处理非24小时一直启动的Linux系统的crontab的执行。所以anacron并不能指定何时执行某项任务,而是以天为单位或者是在开机后立刻进行anacron的操作,它会去检测停机期间应该进行但是并没有进行的crontab任务,并将该任务执行一遍,然后anacron就会自动停止了。
由于anacron会以一天、七天、一个月为期去检测系统未进行的crontab任务,因此对于某些特殊的使用环境非常有帮助。举例来说,如果你的Linux主机是放在公司给同事使用的,因为周末假日大家都不在公司所以也没有必要开启,因此你的Linux是周末都会关机两天的。但是crontab大多在每天的凌晨以及周日的早上进行各项任务,偏偏你又关机了,此时系统很多crontab的任务就无法进行。anacron刚好可以解决这个问题!
那么anacron又是怎么知道我们的系统什么时候关机的呢?这就得要使用anacron读取的时间记录文件(timestamps)了!anacron会去分析现在的时间与时间记录文件所记载的上次执行anacron的时间,两者比较后若发现有区别,那就是在某些时刻没有进行crontab。此时anacron就会开始执行未进行的crontab任务了。所以anacron其实也是通过crontab来运行的!因此anacron运行的时间通常有两个,一个是系统开机期间运行,一个是写入 crontab 的调度中。这样才能够在特定时间分析系统未进行的crontab工作。
16.4.2 anacron 与/etc/anacrontab
anacron 其实是一个程序并非一个服务。这个程序在 CentOS 当中已经进入 crontab 的调度。不相信吗?你可以这样跟踪看看:
[root@www ~]# ll /etc/cron/ana*
-rwxr-xr-x 1 root root 379 Mar 28 2007 /etc/cron.daily/0anacron
-rwxr-xr-x 1 root root 381 Mar 28 2007 /etc/cron.monthly/0anacron
-rwxr-xr-x 1 root root 380 Mar 28 2007 /etc/cron.weekly/0anacron
刚好是每天、每周、每月有调度的工作目录!查看一下每天的任务
[root@www ~]# cat /etc/cron.daily/0anacron
if [ ! -e /var/run/anacron.pid ]; then
anacron -u cron.daily
fi
所以其实也仅是执行 anacron -u 的命令,因此我们得来谈谈这个程序!
基本上,anacron的语法如下:
[root@www ~]# anacron [-sfn] [job]..
[root@www ~]# anacron -u [job]..
参数:
-s :开始连续执行各项工作 (job),会依据时间记录文件的数据判断是否进行;
-f :强制进行,而不去判断时间记录文件的时间戳;
-n :立刻进行未进行的任务,而不延迟 (delay) 等待时间;
-u :仅更新时间记录文件的时间戳,不进行任何工作。
job:由/etc/anacrontab定义的各项工作名称。
所以我们发现其实/etc/cron.daily/0anacron仅进行时间戳的更新,而没有进行任何anacron的操作。在我们的CentOS中,anacron的进行其实是在开机完成后才进行的一项工作任务,你也可以将anacron排入crontab的调度中。但是为了担心anacron误判时间参数,因此/etc/cron.daily/里面的anacron 才会在文件名之前加个 0(0anacron),让 anacron 最先进行,就是为了让时间戳先更新,以避免anacron误判crontab尚未进行任何工作的意思。
接下来我们看一下/etc/anacrontab的内容好了:
[root@www ~]# cat /etc/anacrontab
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
1 65 cron.daily run-parts /etc/cron.daily
7 70 cron.weekly run-parts /etc/cron.weekly
30 75 cron.monthly run-parts /etc/cron.monthly
天数 延迟时间 工作名称定义 实际要进行的命令串
天数单位为天;延迟时间单位为分钟;工作名称定义可自定义;
命令串则通常与 crontab 的设置相同!
[root@www ~]# more /var/spool/anacron/*
::::::::::::::
/var/spool/anacron/cron.daily
::::::::::::::
20090315
::::::::::::::
/var/spool/anacron/cron.monthly
::::::::::::::
20090301
::::::::::::::
/var/spool/anacron/cron.weekly
::::::::::::::
20090315
上面则是三个工作名称的时间记录文件以及记录的时间戳
由于/etc/cron.daily 内的任务比较多,因此我们使用每天进行的任务来解释一下 anacron 的运行情况好了。anacron 若执行“anacron -scron.daily”时,它会这样运行的:
1.由/etc/anacrontab分析到cron.daily这项工作名称的天数为1天;
2.由/var/spool/anacron/cron.daily取出最近一次执行anacron的时间戳;
3.由上个步骤与目前的时间比较,若差异天数为1天以上(含1天),就准备进行命令;
4.若准备进行命令,根据/etc/anacrontab的设置将延迟65分钟;
5.延迟时间过后,开始执行后续命令,即“run-parts /etc/cron.daily”这串命令;
6.执行完毕后,anacron程序结束。
所以说,时间戳是非常重要的。anacron 是通过该记录与目前的时间差异,了解到是否应该要进行某项任务的工作。举例来说,如果我的主机在2009/03/15(星期天)18:00关机,然后在2009/03/16 (星期一)8:00开机,由于我的crontab是在早上04:00左右进行各项任务,由于该时刻系统是关机的,因此时间戳依旧为 20090315(旧的时间),但是目前时间已经是 20090316(新的时间),因此run-parts/etc/cron.daily就会在开机过65分钟后开始运行了。
所以,anacron并不需要额外的设置,使用默认值即可!只是我们的CentOS只有在开机时才会执行anacron就是了。如果要确定anacron是否开机时会主动执行,你可以执行下列命令:
[root@www ~]# chkconfig —list anacron
anacron 0:off 1:off 2:on 3:on 4:on 5:on 6:off
详细的 chkconfig 说明我们会在后续章节提到,注意看 3, 5
的选项,都是 on 。那就是有启动啦!开机时才会执行的意思。
现在你知道为什么隔了一阵子才将CentOS开机,开机过后约1小时左右系统会有一小段时间的忙碌,而且硬盘会跑个不停!那就是因为anacron正在执行过去crontab未进行的各项工作调度。这样对anacron有没有概念了呢?
16.5 重点回顾
系统可以通过 at 这个命令来调度单一工作的任务!“at TIME”为命令执行的方法,当 at 进入调度后,系统执行该调度工作时,会到执行时的目录进行任务。
at的执行必须要有atd服务的支持,且/etc/at.deny为控制是否能够执行的用户账号。
通过atq,atrm可以查询与删除at的工作调度。
batch与at相同,不过batch可在CPU工作负载小于0.8时才进行后续的工作调度。
系统的循环例行性工作调度使用 cron 这个服务,同时利用 crontab -e 及/etc/crontab 进行调度的安排。
crontab -e 设置项目分为六列,分、时、日、月、周、命令为其设置依据。
/etc/crontab设置分为七列,分、时、日、月、周、执行者、命令为其设置依据。
anacron配合/etc/anacrontab的设置,可以唤醒停机期间系统未进行的crontab任务。
16.6 本章习题
简答题部分
X 今天假设我有一个命令程序,名称为 ping.sh。我想要让系统每三分钟执行这个文件一次,但是偏偏这个文件会有很多的信息显示出来,所以我的 root 账号每天都会收到差不多四百多封的信件,光是收信就差不多快要疯掉了。那么请问应该怎么设置比较好呢?
你预计要在 2010 年的 2 月 14 日寄出一封 Email 给 kiki,只有该年才寄出!该如何执行命令?
执行 crontab -e 之后,如果输入这一行,代表什么意思?
- 15 1-5/usr/local/bin/tea_time.sh
我用 vi 编辑/etc/crontab 这个文件,我编辑的那一行是这样的:
25 00 0 /usr/local/bin/backup.sh
这一行代表的意义是什么?
请问,你的系统每天、每周、每个月各有进行什么工作?
每个星期六凌晨三点去系统查找一下含有 SUID/SGID 的任何文件,并将结果输出到/tmp/uidgid.files中。