朋友們肯定在工作中會經常碰到這種情況,一段代碼我需要在一個固定時間上線,那我們肯定不可能說掐着表,盯着屏幕來手動執行吧,要是在半夜凌晨三四點了?運維是個苦逼的工作,其實在凌晨兩三點起來處理問題也不是什麼稀奇事,好吧,言歸正傳,我們今天一起來探討的話題是如何使用計劃任務工具來實現在某一特定時間讓系統自動完成某項工作。
計劃任務工具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 [email protected] (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任務來講,%有特殊用途;如果在命令中要使用%,則需要轉義;不過,如果把%放置於單引號中,也可以不用轉義在需要秒級別運行任務時可以藉助腳本的循環來完成