at命令:一次性执行定时任务

at 命令要想正确执行,需要 atd 服务的支持。atd 服务是独立的服务,启动的命令如下:

[root@localhost ~]# service atd start
正在启动 atd: [确定]

如果想让 atd 服务开机时自启动,则可以使用如下命令:

[root@localhost ~]# chkconfig atd on

 atd 服务启动之后,at 命令才可以正常使用,

 at 命令的访问控制

这里的访问控制指的是允许哪些用户使用 at 命令设定定时任务,或者不允许哪些用户使用 at 命令。at 命令的访问控制是依靠 /etc/at.allow(白名单)和 /etc/at.deny(黑名单)这两个文件来实现的,具体规则如下: 

  • 如果系统中有 /etc/at.allow 文件,那么只有写入 /etc/at.allow 文件(白名单)中的用户可以使用 at 命令,其他用户不能使用 at 命令(/etc/at.deny 文件会被忽略,也就是说,同一个用户既写入 /etc/at.allow 文件,又写入 /etc/at.deny 文件,那么这个用户是可以使用 at 命令的,因为 /etc/at.allow 文件的优先级更高)。

  • 如果系统中有 /etc/at.allow 文件,那么只有写入 /etc/at.allow 文件(白名单)中的用户可以使用 at 命令,其他用户不能使用 at 命令(/etc/at.deny 文件会被忽略,也就是说,同一个用户既写入 /etc/at.allow 文件,又写入 /etc/at.deny 文件,那么这个用户是可以使用 at 命令的,因为 /etc/at.allow 文件的优先级更高)。

  • 如果系统中没有 /etc/at.allow 文件,只有 /etc/at.deny 文件,那么写入 /etc/at.deny 文件(黑名单)中的用户不能使用 at 命令,其他用户可以使用 at 命令。不过这个文件对 root 用户不生效。

  • 如果系统中这两个文件都不存在,那么只有 root 用户可以使用 at 命令。

系统中默认只有 /etc/at.deny 文件,而且这个文件是空的,这样系统中所有的用户都可以使用 at 命令。不过,如果我们打算控制用户的 at 命令权限,那么只需把用户写入 /etc/at.deny 文件即可。/etc/at.allow 文件的优先级高,如果 /etc/at.allow 文件存在,则 /etc/at.deny 文件失效。/etc/at.allow 文件的管理更加严格,因为只有写入这个文件的用户才能使用 at 命令,如果需要禁用 at 命令的用户较多,则可以把少数用户写入这个文件。/etc/at.deny 文件的管理较为松散,如果允许使用 at 命令的用户较多,则可以把禁用的用户写入这个文件。不过这两个文件都不能对 root 用户生效。

at命令

at 命令的格式非常简单,只需在 at 命令后面加入时间即可,这样 at 命令就会在指定的时间执行。at 命令格式如下:

[root@localhost ~] # at [选项] 时间

【选项】

  • -m:当 at 工作宪成后,无论命令是否有输出,都用 E-mail 通知执行 at 命令的用户;

  • -c 工作号: 显示该 at 工作的实际内容;

【时间】

  • HH:MM 在指定的“小时:分钟”执行命令,如 02:30;

  • HH:MM YYYY-MM-DD 在指定的“小时:分钟 年-月-日”执行命令,如 02:30 2013-07-25;

  • HH:MM[am|pm] [month] [date] 在指定的“小时:分钟[上午|下午][月][日]”执行命令,如 02:30 July 25;

  • HH:MM[am|pm] + [minutes | hours | days | weeks ]在指定的时间“再加多久"执行命令,如 now + 5 minutes, 05am +2 hours;

at 命令只要指定正确的时间,就可以输入需要在指定时间执行的命令。这个命令可以是系统命令,也可以是 Shell 脚本。 

定时执行脚本

[coot@localhost ~]# cat /root/hello.sh#!/bin/bashecho "hello world!!"#该脚本会打印"hello world!!"

使用 at 定时调用

复制代码

[root@localhost ~]# at now +2 minutes
at> /root/hello.sh >> /root/hello.log
#执行hello.sh脚本,并把输出写入/root/hello.log文件
at> <EOT>#使用Ctrl+D快捷键保存at任务
job 8 at 2018-12-16 20:54 #这是第8个at任务,会在2018年12月16日20:54执行

复制代码

查询第8个at任务的内容

[root@localhost ~]# at -c 8
 ...省略部分内容.../root/hello.sh >> /root/hello.log
#可以看到at执行的任务

在指定的时间关机

在一个at任务中是可以执行多个系统命令的

[root@localhost ~J# at 02:00 2018-12-16at> /bin/syncat> /sbin/shutdown -h now
at> <EOT>job 9 at 2018-12-16 21:00

在使用系统定时任务时,不论执行的是系统命令还是 Shell 脚本,最好使用绝对路径来写命令,这样不容易报错。at 任务一旦使用 Ctrl+D 快捷键保存,实际上写入了 /var/spool/at/ 这个目录,这个目录内的文件可以直接被 atd 服务调用和执行。

查询当前服务器上的at任务

[root@localhost ~]# atq9 2018-12-16 21:00 a root
#说明root用户有一个at任务在2018-12-16 21:00 执行,工作号是9

删除指定的at任务

[root@localhost ~]# atrm 9[root@localhost ~]# atq
#删除9号at任务,再查询就没有at任务存在了

crontab命令:循环执行定时任务 

at 命令仅仅可以在指定的时间执行一次任务,但是系统的定时任务一般是需要重复执行的。所以需要利用 crontab 命令来执行循环定时任务。

crond服务管理与访问控制

crontab 命令是需要 crond 服务支持的。crond 服务同样是独立的服务,启动和自启动方法如下:

[root@localhost ~]# service crond restart
停止 crond: [确定]
正在启动 crond: [确定]
#重新启动crond服务

设定crond服务为开机自启动

[root@localhost ~]# chkconfig crond on

crond 服务默认是自启动的。如果服务器上有循环执行的系统定时任务,就不要关闭 crond 服务了。

crontab 命令和 at 命令类似,也是通过 /etc/cron.allow 和 /etc/cron.deny 文件来限制某些用户是否可以使用 crontab 命令的。而且原则也非常相似:

  • 当系统中有 /etc/cron.allow 文件时,只有写入此文件的用户可以使用 crontab 命令,没有写入的用户不能使用 crontab 命令。同样,如果有此文件,/etc/cron.deny 文件会被忽略,因为 /etc/cron.allow 文件的优先级更高。

  • 当系统中只有 /etc/cron.deny 文件时,写入此文件的用户不能使用 crontab 命令,没有写入文件的用户可以使用 crontab 命令。

  • 这个规则基本和 at 命令的规则一致,同样是 /etc/cron.allow 文件比 /etc/cron.deny 文件的优先级高,Linux 系统中默认只有 /etc/cron.deny 文件。

用户的crontab设置

每个用户都可以实现自己的 crontab 定时任务,只需使用这个用户身份执行“crontab -e”命令即可。当然,这个用户不能写入 /etc/cron.deny 文件。crontab 命令格式如下:

[root@localhost ~]# crontab [选项]

[选项]:

  • -e:编辑 crontab 定时任务;

  • -l:查询 crontab 定时任务;

  • -r:删除当前用户所有的 crontab 定时任务。如果有多个定时任务,只想删除一个,则可以使用“crontab -e”;

  • -u 用户名:修改或删除其他用户的 crontab 定时任务。只有 root 用户可用;

crontab 文件格式 

crontab 编辑的文件中是通过5个“*”来确定命令或任务的执行时间的,这 5 个“*”的具体含义:

项目 含义 范围
第一个"*" 一小时当中的第几分钟 0~59
第二个"*" 一天当中的第几小时 0~23
第三个"*" 一个月当中的第几天 1~31
第四个"*" 一年当中的第几个月 1~12
第五个"*" 一周当中的星期几 0~7(0和7都代表星期日)

 在时间表示中,还有一些特殊符号需要学习:

特殊符号 含义
* 代表任何时间。比如第一个"*"就代表一小时种每分钟都执行一次的意思
, 代表不连续的时间。比如"0 8,12,16***命令"就代表在每天的8点0分、12点0分、16点0分都执行一次命令
代表连续的时间范围。比如"0 5 ** 1-6命令",代表在周一到周六的凌晨5点0分执行命令
*/n 代表每隔多久执行一次。比如"*/10****命令",代表每隔10分钟就执行一次命令

当“crontab -e”编辑完成之后,一旦保存退出,那么这个定时任务实际就会写入 /var/spool/cron/ 目录中,每个用户的定时任务用自己的用户名进行区分。而且 crontab 命令只要保存就会生效,只要 crond 服务是启动的。知道了这 5 个时间字段的含义,我们多举几个时间的例子来熟悉一下时间字段,如表 3 所示。

时间 含义
45 22 *** 命令 在22点45分执行命令
0 17 ** 1 命令 在每周一的17点0分执行命令
0 5 1,15** 命令 在每月1日和15日的凌晨5点0分执行命令
40 4 ** 1-5 命令 在每周一到周五的凌晨4点40分执行命令
*/10 4 *** 命令 在每天的凌晨4点,每隔10分钟执行一次命令
0 0 1,15 * 1 命令

在每月1日和15日的0点0分及每周一的0点0分都会执行命令,

注意:星期几和几日最好不要同时出现,因为定义的都是天,非常容易混淆

在“执行的任务”字段中既可以定时执行系统命令,也可以定时执行某个 Shell 脚本。 

让系统每隔 5 分钟就向 /tmp/test 文件中写入一行“11”

[root@localhost ~]# crontab -e
#进入编辑界面*/5 * * * * /bin/echo "11" >> /tmp/test

如果觉得每隔 5 分钟太长,那就换成“*”,让它每分钟执行一次。而且和 at 命令一样,如果我们定时执行的是系统命令,那么最好使用绝对路径。

让系统在每周二的凌晨5点05分重启一次

[root@localhost ~]# crontab -e5.5 * * 2 /sbin/shutdown -r now

如果服务器的负载压力比较大,则建议每周重启一次,让系统状态归零。比如绝大多数游戏服务器每周维护一次,维护时最主要的工作就是重启,让系统状态归零。这时可以让我们的服务器自动来定时执行。

在每月1日、10日、15 日的凌晨 3 点 30 分都定时执行日志备份脚本 autobak.sh

[root@localhost ~]# crontab -e30.3 1,10,15 * * /root/sh/autobak.sh

这些定时任务保存之后,就可以在指定的时间执行了。

 查看root用户的crontab任务

[root@localhost ~]# crontab -l*/5 * * * * /bin/echo "11" >> /tmp/test5.5 * * 2 /sbin/shutdown -r now30.3 1,10,15 * * /root/sh/autobak.sh

删除root用户所有的定时任务

 [root@localhost ~]# crontab -r

如果只想删除某个定时任务,则可以执行“crontab -e”命令进入编辑模式手工删除

[root@localhost ~]# crontab -l
no crontab for root

删除后,再查询就没有root用户的定时任务了

crontab的注意事项

在书写 crontab 定时任务时,需要注意以下几个事项:

  • 6 个选项都不能为空,必须填写。如果不确定,则使用“*”代表任意时间。

  • crontab 定时任务的最小有效时间是分钟,最大有效时间是月。像 2018 年某时执行、3 点 30 分 30 秒这样的时间都不能被识别。

  • 在定义时间时,日期和星期最好不要在一条定时任务中出现,因为它们都以天为单位,非常容易让管理员混淆。

  • 在定时任务中,不管是直接写命令,还是在脚本中写命令,最好都使用绝对路径。有时使用相对路径的命令会报错。

系统的crontab设置

“crontab -e”是每个用户都可以执行的命令,也就是说,不同的用户身份可以执行自己的定时任务。但是有些定时任务需要系统执行,这时就需要编辑 /etc/crontab 这个配置文件了。

当然,并不是说写入 /etc/crontab 配置文件中的定时任务在执行时不需要用户身份,而是“crontab -e”命令在定义定时任务时,默认用户身份是当前登录用户。而在修改 /etc/crontab 配置文件时,定时任务的执行者身份是可以手工指定的。

复制代码

[root@localhost ~]#  /etc/=/bin/=/sbin:/bin:/usr/sbin:/usr/==/   - |.———————— hour ( - | |.——————— day of month ( - | | |.———— month ( - | | | | .———day of week(-)(Sunday= or | | | | |* * * * * user-

复制代码

我们看到 /etc/crontab 中有一句提示,让我们“man 4 crontabs”来查看帮助,在这个帮助中,写明了“在旧版本的 crontab 配置文件中,通过 run-parts 脚本来调用 cron.{daily,weekly,monthly} 目录,定时执行这些目录中的脚本。在当前系统中,为了避免 cron 和 anacron 之间产生冲突,只要 anacron 已经安装,就使用 anacron 来执行这些目录中的脚本。具体可以查看 anacron(8) 的帮助”。  其实,对用户来讲,配置方法都有两种。

第一种方法就是把需要定时执行的工作写成脚本程序,并赋予执行权限,然后直接把这个脚本复制到 /etc/cron.{daily,weekly,monthly} 目录中的任意一个。比如,我需要让某个脚本每周执行,就把这个脚本复制到 /etc/cron.weekly/ 目录中。这样这个脚本就会每周执行一次,具体的执行时间要参考 anacron 的配置文件。

第二种方法就是修改 /etc/crontab 这个配置文件,加入自己的定时任务,不过需要注意指定脚本的执行者身份。例如让系统每分钟都执行一次/root/cron/目录中的脚本,脚本执行者是root用户:

[root@localhost ~]# vi /etc/crontab
…省略部分输出…* * * * * root run-parts /root/cron/

虽然在CentOS 6.x中不直接通过此配置文件调用/etc/cron.{daily,weekly,monthly}这些目录,但是run-parts脚本还是可以使用的。所以我完全可以参照CentOS 5.x的方法来写定时任务
使用run-parts脚本调用并执行/root/cron/目录中所有的可执行文件只要保存 /etc/crontab 文件,这个定时任务就可以执行了。当然要确定 crond 服务是运行的。

复制代码

[root@localhost ~]# mkdir cron
#建立/root/cron/目录
[root@localhost cron]# vi /root/cron/hello.sh#/bin/bashecho "hello" >> /root/cron/hello.log
#在/root/cron/hello.log文件中写入“hello”
[root@localhost cron]# chmod 755 hello.sh#赋予执行权限
#因为hello.sh脚本放入了/root/cron/目录中,所以每分钟执行一次。

复制代码

这两种方法都是可以使用的,不过,要想修改 /etc/crontab 文件,必须是 root 用户,普通用户不能修改,只能使用用户身份的 crontab 命令。

anacron命令 

在Linux 服务器中,如果不是 24 小时开机的,而刚好在关机的时间段之内有系统定时任务(cron)需要执行,那么这些定时任务是不会执行的。例如:假设我们需要在凌晨 5 点 05 分执行系统的日志备份,但是我们的 Linux 服务器不是 24 小时开机的,在晚上需要关机,在白天上班之后才会再次开机,在这个定时任务的执行时间我们的服务器刚好没有开机,那么这个定时任务就不会执行了。anacron 就是用来解决这个问题的。anacron 会使用 1 天、7 天、一个月作为检测周期,用来判断是否有定时任务在关机之后没有执行。如果有这样的任务,那么 anacron 会在特定的时间重新执行这些定时任务。

在系统的 /var/spool/anacron/ 目录中存在 cron.{daily,weekly,monthly} 文件,这些文件中都保存着 anacron 上次执行的时间。anacron 会读取这些文件中的时间,然后和当前时间进行比较,如果两个时间的差值超过 anacron 的指定时间差值(一般是 1 天、7 天和一个月),就说明有定时任务没有执行,这时 anacron 会介入而执行这个漏掉的定时任务,从而保证在关机时没有执行的定时任务不会被漏掉。

在 CentOS 6.x 中使用 cronie-anacron 取代了 vixie-cron 软件包。而且在原先的 CentOS 版本的 /etc/cron.{daily,weekly,monthly} 目录中的定时任务会同时被 cron 和 anacron 调用,这样非常容易出现重复执行同一个定时任务的错误。在 CentOS 6.x 中,/etc/cron.{daily,weekly,monthly} 目录中的定时任务只会被 anacron 调用,从而保证这些定时任务只会在每天、每周或每月定时执行一次,而不会重复执行。

在 CentOS 6.x 中 anacron 还有一个变化,那就是 anacron 不再是单独的服务,而变成了系统命令。也就是说,我们不再使用“service anacron restart”命令来管理 anacron 服务了,而需要使用 anacron 命令来管理 anacron 工作。anacron命令格式如下:

[root@localhost ~]# anacron [选项] [参数]

[选项]:

  • -s:开始执行 anacron 工作,依据 /etc/anacrontab 文件中设定的延迟时间执行;

  • -s:开始执行 anacron 工作,依据 /etc/anacrontab 文件中设定的延迟时间执行;

  • -n:立即执行 /etc/anacrontab 中所有的工作,忽略所有的延迟时间;

  • -u:更新 /var/spool/anacron/cron.{daily,weekly,monthly} 文件中的时间戳,但不执行任何工作;

[参数]:

  • 工作名:依据 /etc/anacrontab 文件中定义的工作名;

在当前的 Linux 中,其实不需要执行任何 anacron 命令,只需要配置好 /etc/anacrontab 文件,系统就会依赖这个文件中的设定来通过 anacron 执行定时任务了。这个文件的内容如下:

复制代码

[root@localhost ~]# vi /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/shPATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root
#前面的内容和/etc/crontab类似
#the maximal random delay added to the base delay of the jobs RANDOM_DELAY=45#最大随机廷迟
#the jobs will be started during the following hours only START_H0URS_RANGE=3-22fanacron的执行时间范围是3:00~22:00#period in days delay in minutes job-identifier command1 5 cron.daily nice run-parts /etc/cron.daily7 25 cron.weekly nice run-parts /etc/cron.weekly
©monthly 45 cron.monthly nice run-parts /etc/cron.monthly
#天数 强制延迟(分) 工作名称 实际执行的命令
#当时间差超过天数时,强制延迟多少分钟之后就执行命令

复制代码

在这个文件中,“RANDOM_DELAY”定义的是最大随机延迟,也就是说,cron.daily 工作如果超过 1 天没有执行,则并不会马上执行,而是先延迟强制延迟时间,再延迟随机延迟时间,之后再执行命令;“START_HOURS_RANGE”的是定义 anacron 执行时间范围,anacron 只会在这个时间范围内执行。

我们用 cron.daily 工作来说明一下 /etc/anacrontab 的执行过程:

  1. 读取 /var/spool/anacron/cron.daily 文件中 anacron 上一次执行的时间。

  2. 和当前时间比较,如果两个时间的差值超过1天,就执行cron.daily工作。

  3. 只能在 03:00-22:00 执行这个工作。

  4. 执行工作时强制延迟时间为 5 分钟,再随机延迟 0~45 分钟。

  5. 使用 nice 命令指定默认优先级,使用 run-parts 脚本执行 /etc/cron.daily 目录中所有的可执行文件。

大家会发现,/etc/cron.{daily,weekly,monthly} 目录中的脚本在当前的 Linux 中是被 anacron 调用的,不再依靠 cron 服务。不过,anacron 不用设置多余的配置,我们只需要把需要定时执行的脚本放入 /etc/cron.{daily,weekly,monthly} 目录中,就会每天、每周或每月执行,而且也不再需要启动 anacron 服务了。如果需要进行修改,则只需修改 /etc/anacrontab 配置文件即可。

比如,让定时任务在凌晨 03:00-05:00 执行,就可以进行如下修改:

复制代码

[root@localhost ~] # vi /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL-/bin/shPATH-/sbin:/bin:/usr/sbin:/usr/bin MAILTO-root
# the maximal random delay added to the base delay of the jobs RANDOM_DELAY=0#把最大随机廷迟改为0分钟,不再随机廷迟
# the jobs will be started during the following hours only START_HOORS_RANGE=3-5#执行时间范围为03:00—05:00#period in days delay in minutes job-identifier command1 0 cron.daily nice run-parts /etc/cron.daily7 0 cron.weekly nice run-parts /etc/cron.weekly
@monthly 0 cron.monthly nice run-parts /etc/cron.monthly
#把强制延迟也改为0分钟,不再强制廷迟

复制代码

这样,所有放入 /etc/cron.{daily,weekly,monthly} 目录中的脚本都会在指定时间执行,而且也不怕服务器万一关机的情况了。