朋友们肯定在工作中会经常碰到这种情况,一段代码我需要在一个固定时间上线,那我们肯定不可能说掐着表,盯着屏幕来手动执行吧,要是在半夜凌晨三四点了?运维是个苦逼的工作,其实在凌晨两三点起来处理问题也不是什么稀奇事,好吧,言归正传,我们今天一起来探讨的话题是如何使用计划任务工具来实现在某一特定时间让系统自动完成某项工作。

   计划任务工具at 和crontab

    那么我们这两个工具有什么区别了?

      我们首先来看一下at

at命令是由atd服务提供,属于一次性的计划任务,如果指定计划任务时间超过了当前时间,那么将在下一次这个时间执行,centos6版本使用service atd start来启动,在centos7版本使systemctl start atd来启动服务。查看atd服务是否开机启动使用:chkconfig --list|grep atd


下面我们一起来了解一下at支持哪些选项及时间定义格式

at -l 列出当前系统所有用户的at队列

at -d 取消某一排行中的队列,后面跟上队列号(使用-l选项查看已存在的队列)

at -f 把要执行的任务放置文件,使用at来读取此文件作为要运行的任务

at -c 查看队列中指定序列号的任务计划内容

atq 相当于at -l


时间格式

at时间格式支持使用具体的某一时间:例如 00:00 或者可以指定在某一年某一天的某个时辰 00:00 2016-11-11 (这里需要注意的是如果今天这个时间已过,那么这个任务将会在明天执行)

当前时间之后的多长时间:例如 now + 5 minutes(hours,days,OR weeks)或者指定具体时间后的多长时间 05pm + 2 minutes

还支持像使用tomorrow,acquired,noon,midnight,teatime


任务文件存放位置:/var/spool/at/

任务文件日志位置:/var/log/at


执行方式 交互式|交互式输入重定向|文件载入

交互式:

  at TIME

  at>具体执行的任务

  a>  ctrl+d (使用ctrl+d来保存交互式的任务)


 交互式输入重定向


  at TIME <<end

  at>命令

  at>end 结束

  

非交互式输入重定向载入文件

  at TIME < FILENAME



  文件载入  

at -f FILENAME TIME



 下面用一个例子来看看at具体相关使用方法

[root@centos6 ~]# at 02:39 
at> wall hello word 
at> <EOT>
job 1 at 2016-07-26 02:39
#使用at设定一个计划任务
[root@centos6 ~]# date
Tue Jul 26 02:37:49 CST 2016
#查看队列存在的任务
[root@centos6 ~]# at -l
1 2016-07-26 02:39 a root
#查看队列号为1的具体任务内容
[root@centos6 ~]# at -c 1
#!/bin/sh
# atrun uid=0 gid=0
# mail root 0
umask 22
HOSTNAME=centos6.test1; export HOSTNAME
SELINUX_ROLE_REQUESTED=; export SELINUX_ROLE_REQUESTED
SHELL=/bin/bash; export SHELL
HISTSIZE=1000; export HISTSIZE
SSH_CLIENT=10.1.45.199\ 49988\ 22; export SSH_CLIENT
SELINUX_USE_CURRENT_RANGE=; export SELINUX_USE_CURRENT_RANGE
QTDIR=/usr/lib64/qt-3.3; export QTDIR
QTINC=/usr/lib64/qt-3.3/include; export QTINC
SSH_TTY=/dev/pts/3; export SSH_TTY
USER=root; export USERLS_COLORS=rs=0:di=01\;34:ln=01\;36:mh=00:pi=40\;33:so=01\;35:do=01\;35:bd=40\;33\;01:cd=40\;33\;01:or=40\;31\;01:mi=01\;05\;37\;41:su=37\;41:sg=30\;43:ca=30\;41:tw=30\;42:ow=34\;42:st=37\;44:ex=01\;32:\*.tar=01\;31:\*.tgz=01\;31:\*.arj=01\;31:\*.taz=01\;31:\*.lzh=01\;31:\*.lzma=01\;31:\*.tlz=01\;31:\*.txz=01\;31:\*.zip=01\;31:\*.z=01\;31:\*.Z=01\;31:\*.dz=01\;31:\*.gz=01\;31:\*.lz=01\;31:\*.xz=01\;31:\*.bz2=01\;31:\*.tbz=01\;31:\*.tbz2=01\;31:\*.bz=01\;31:\*.tz=01\;31:\*.deb=01\;31:\*.rpm=01\;31:\*.jar=01\;31:\*.rar=01\;31:\*.ace=01\;31:\*.zoo=01\;31:\*.cpio=01\;31:\*.7z=01\;31:\*.rz=01\;31:\*.jpg=01\;35:\*.jpeg=01\;35:\*.gif=01\;35:\*.bmp=01\;35:\*.pbm=01\;35:\*.pgm=01\;35:\*.ppm=01\;35:\*.tga=01\;35:\*.xbm=01\;35:\*.xpm=01\;35:\*.tif=01\;35:\*.tiff=01\;35:\*.png=01\;35:\*.svg=01\;35:\*.svgz=01\;35:\*.mng=01\;35:\*.pcx=01\;35:\*.mov=01\;35:\*.mpg=01\;35:\*.mpeg=01\;35:\*.m2v=01\;35:\*.mkv=01\;35:\*.ogm=01\;35:\*.mp4=01\;35:\*.m4v=01\;35:\*.mp4v=01\;35:\*.vob=01\;35:\*.qt=01\;35:\*.nuv=01\;35:\*.wmv=01\;35:\*.asf=01\;35:\*.rm=01\;35:\*.rmvb=01\;35:\*.flc=01\;35:\*.avi=01\;35:\*.fli=01\;35:\*.flv=01\;35:\*.gl=01\;35:\*.dl=01\;35:\*.xcf=01\;35:\*.xwd=01\;35:\*.yuv=01\;35:\*.cgm=01\;35:\*.emf=01\;35:\*.axv=01\;35:\*.anx=01\;35:\*.ogv=01\;35:\*.ogx=01\;35:\*.aac=01\;36:\*.au=01\;36:\*.flac=01\;36:\*.mid=01\;36:\*.midi=01\;36:\*.mka=01\;36:\*.mp3=01\;36:\*.mpc=01\;36:\*.ogg=01\;36:\*.ra=01\;36:\*.wav=01\;36:\*.axa=01\;36:\*.oga=01\;36:\*.spx=01\;36:\*.xspf=01\;36:; export LS_COLORS
MAIL=/var/spool/mail/root; export MAIL
PATH=/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin; export PATH
PWD=/root; export PWD
LANG=en_US.UTF-8; export LANG
KDE_IS_PRELINKED=1; export KDE_IS_PRELINKED
KDEDIRS=/usr; export KDEDIRS
SELINUX_LEVEL_REQUESTED=; export SELINUX_LEVEL_REQUESTED
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass; export SSH_ASKPASS
HISTCONTROL=ignoredups; export HISTCONTROL
SHLVL=1; export SHLVL
HOME=/root; export HOME
LOGNAME=root; export LOGNAME
QTLIB=/usr/lib64/qt-3.3/lib; export QTLIB
CVS_RSH=ssh; export CVS_RSH
SSH_CONNECTION=10.1.45.199\ 49988\ 10.1.45.60\ 22; export SSH_CONNECTION
LESSOPEN=\|\|/usr/bin/lesspipe.sh\ %s; export LESSOPEN
G_BROKEN_FILENAMES=1; export G_BROKEN_FILENAMES
cd /root || {
 echo 'Execution directory inaccessible' >&2
 exit 1
}
${SHELL:-/bin/sh} << 'marcinDELIMITER348f4254'
wall hello word

marcinDELIMITER348f4254

[root@centos6 ~]# 
Broadcast message from root@centos6.test1 (Tue Jul 26 02:39:00 2016):

hello word

[root@centos6 ~]# at -l
2 2016-07-26 10:10 a root
#删除任务计划
[root@centos6 ~]# at -d 2
[root@centos6 ~]# at -l


控制普通用户的at任务权限

/etc/at.deny 黑名单,设置后文件内用户不能创建at计划任务

/etc/at.allow 白名单,设置后将不再读取黑名单,设置白名单后只有白名单里的用户可以使用at创建计划任务。

我们看一下具体例子

 

#当前有这几个用户
[root@centos6 etc]# ls /home/
liaoxz liao liaox liaoz
#默认白名单文件不存在
[root@centos6 etc]# ls at.*
at.deny
[root@centos6 etc]# vim at.deny 
liaoxz
liaox
[root@centos6 etc]# su - liaoxz

[liaoxz@centos6 ~]$ at 10:00
You do not have permission to use at.
#用户liaoxz被我加到了黑名单
[liaoxz@centos6 ~]$ exit
logout

[root@centos6 etc]# su - liaoz
[liaoz@centos6 ~]$ at 10:00
at> <EOT>
job 4 at 2016-07-26 10:00
#用户liaoz没有加到黑名单所以是能执行at计划任务的
[liaoz@centos6 ~]$ exit
logout
[root@centos6 etc]# su - liaox
[liaox@centos6 ~]$ at 10:00
You do not have permission to use at.

[liaox@centos6 ~]$ exit
logout
[root@centos6 etc]# touch at.allow
liaoxz
liao
liaox
liaoz
[root@centos6 etc]# vim at.allow 
[root@centos6 etc]# su - liaoxz
[liaoxz@centos6 ~]$ at 10:00
at> <EOT>
job 5 at 2016-07-26 10:00
[liaoxz@centos6 ~]$ exit
logout
[root@centos6 etc]# at - liaox
syntax error. Last token seen: -
Garbled time
[root@centos6 etc]# su - liao
[liao@centos6 ~]$ at 10:00
at> <EOT>
job 6 at 2016-07-26 10:00
[liao@centos6 ~]$ exit
logout
#只要白名单存在,即使黑名单里面有和白名单一样的用户,生效的还是白名单

周期性任务计划工具crontab

crontab是由cron服务提供的,entos6版本使用service crond start来启动,在centos7版本使用

systemctl start crond来启动服务可以用来自定义一些系统任务,或者针对用户来自定义某一时间或某一周期性时间内执行一些任务。

程序包:

程序包包括主程序包cronie和补充程序包cronie-anacron,补充程序包是用来监控cronie任务的执行状态,如果定义的任务在该时间点未能正常运行,则ancron会随后启动一次此任务

crontab定义格式:

[root@centos6 cron]# cat /etc/crontab 
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed



时间格式:

 (1)特定值


              给定时间点有效取值范围内的值

      例如

 10 10 1 10 * root cp /var/log/message  /backup/

1月1日早上10点10分cp一个文件到/backup/

 (2)*


              给定时间点上有效取值范围内的所有值。表示”每…“

      例如

 1 * * * * root wall It has been a minute

 

 (3)指定时间点上的离散取值


              在给定时间点上使用逗号分隔的多个值即可。

1,2,3 12 * * *   wall ok 在12点过1分钟2分钟3分钟的时候执行wall ok


 (4)连续取值


              在时间点上使用“-”连接开头和结束

       1-3 12 * * * wall ok    在12点过1分钟2分钟3分钟的时候执行wall ok

 (5)在指定时间点上,定义步长。


              /#: #即步长

      */1 * * * * 每一分支执行某一个命令 

 crontab相关文件

用户定义文件

/var/spool/USERNAME

日志文件/var/log/cron 

系统cron文件

 /etc/crontab

/etc/cron.d/ 配置文件

/etc/cron.hourly/ 每小时执行的脚本文件夹

/etc/cron.daily/每天执行的脚本文件夹

/etc/cron.weekly/每周执行的脚本文件夹

/etc/cron.monthly/没月执行的脚本文件夹


用户定义crontab格式

crontab [-u user][-l|-r|-e|-i]

-l l列出所有任务

-e 编辑任务

-r 移除所有任务

-i 和-r一起使用,交互式移除指定任务

-u user:只有root可以运行,指定用户管理cron任务


用户控制执行计划任务


控制普通用户的任务权限

/etc/cron.deny 黑名单,设置后文件内用户不能创建计划任务

/etc/cron.allow 白名单,设置后将不再读取黑名单,设置白名单后只有白名单里的用户可以创建计划任务。 


注意:对于cron任务来讲,%有特殊用途;如果在命令中要使用%,则需要转义;不过,如果把%放置于单引号中,也可以不用转义在需要秒级别运行任务时可以借助脚本的循环来完成