一、crond簡介
crond是linux下用來周期性的執行某種任務或等待處理某些事件的一個守護進程,與windows下的計划任務類似,當安裝完成操作系統后,默認會安裝此服務工具,並且會自動啟動crond進程,crontab依賴的服務就是crond,crond進程每分鍾會定期檢查是否有要執行的任務,如果有要執行的任務,則自動執行該任務。這個crond定時任務服務就相當於我們生活中的鬧鍾!
由於crond 是Linux的內置服務,但它不自動起來,可以用以下的方法啟動、關閉這個服務:
/sbin/service crond start //啟動服務 /sbin/service crond stop //關閉服務 /sbin/service crond restart //重啟服務 /sbin/service crond reload //重新載入配置 或者使用下面的命令: /etc/init.d/crond start /etc/init.d/crond restart /etc/init.d/crond stop
設置crond服務開機自啟動:
[root@gin tmp]# chkconfig crond on
特殊需要:crond服務搞不定了,一般工作中寫腳本守護程序執行:
[root@gin tmp]# cat cron.sh while true do echo "I am Bruce Lee" sleep 1 done
程序文件:程序代碼組成,但是沒有在計算機內執行。當前沒有執行。
守護程序或守護進程:進程就是所算機中正在執行的程序,守護進程就是保護正在一直運行的程序。
Linux下的任務調度分為兩類,系統任務調度和用戶任務調度。
A. 系統任務調度:
系統周期性所要執行的工作,比如寫緩存數據到硬盤、日志清理等。在/etc目錄下有一個crontab文件,這個就是系統任務調度的配置文件。
/etc/crontab文件包括下面幾行:
SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ # 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
前四行是用來配置crond任務運行的環境變量
第一行SHELL變量指定了系統要使用哪個shell,這里是bash
第二行PATH變量指定了系統執 行命令的路徑
第三行MAILTO變量指定了crond的任務執行信息將通過電子郵件發送給root用戶,如果MAILTO變量的值為空,則表示不發送任 務執行信息給用戶
第四行的HOME變量指定了在執行命令或者腳本時使用的主目錄。第六至九行表示的含義將在下個小節詳細講述。這里不在多說。
B. 用戶任務調度:
用戶定期要執行的工作,比如用戶數據備份、定時郵件提醒等。用戶可以使用 crontab 工具來定制自己的計划任務。所有用戶定義的crontab 文件都被保存在 /var/spool/cron目錄中。其文件名與當前用戶名一致。
嚴格的說,linux系統下的定時任務軟件還真不少,例如:at , crontab , anacron。
at:適合僅執行一次就結束的調度任務命令,如:某天晚上需要處理一個任務,僅僅是這一天的晚上,屬於突發性的工作任務。要執行at命令,還需要啟動一個名為atd的服務才行。在生產環境中此需要會很少用到。因此,建議不要深入研究!
提示:
1:我們所說的crond服務是運行的程序,而crontab命令用戶用來設置定時規則的命令
2:crond服務是企業生產工作中常用的重要服務,at和anacron很少使用,可以忽略
3:幾乎每個服務器都會用到crond服務
二、crontab工具的使用
(1)crontab的使用格式
crontab常用的使用格式有如下兩種:
crontab [-u user] [file] crontab [-u user] [-e|-l|-r |-i]
選項含義如下:
參數名稱 |
含義 |
指定示例 |
-l |
顯示用戶crontab文件內容,l即list |
crontab -l |
-e |
編輯某個用戶的crontab文件內容。如果不指定用戶,則表示編輯當前用戶的crontab文件。 |
crontab -e |
-i |
在刪除用戶的crontab文件時給確認提示。 |
crontab -ri |
-r |
從/var/spool/cron目錄中刪除某個用戶的crontab文件,不指定用戶,則刪除當前用戶的crontab文件。 |
crontab -r |
-u |
用來設定某個用戶的crontab服務,此參數一般由root用戶來運行 |
crontab -u root -l |
常用的選項命令為 l and e!crontab -e 相當於 vi /var/spool/cron/root ; crontab -l 相當於 cat /var/spool/cron/root
使用者權限文件:
文件 |
說明 |
/etc/cron.deny |
該文件中所列用戶不允許使用crontab命令 |
/etc/cron.allow |
該文件中所列用戶允許使用crontab命令 |
/var/spool/cron/ |
所有用戶crontab文件存放的目錄,以用戶名命令 |
(2)crontab文件的含義
用戶所建立的crontab文件中,每一行都代表一項任務,每行的每個字段代表一項設置,它的格式共分為六個字段,前五段是時間設定段,第六段是要執行的命令段,格式如下:
minute hour day month week command
其中:
* minute: 表示分鍾,可以是從0到59之間的任何整數。 * hour:表示小時,可以是從0到23之間的任何整數。 * day:表示日期,可以是從1到31之間的任何整數。 * month:表示月份,可以是從1到12之間的任何整數。 * week:表示星期幾,可以是從0到7之間的任何整數,這里的0或7代表星期日。 * command:要執行的命令,可以是系統命令,也可以是自己編寫的腳本文件。
在以上各個字段中,還可以使用以下特殊字符:
* 星號(*):代表所有可能的值,例如month字段如果是星號,則表示在滿足其它字段的制約條件后每月都執行該命令操作。 * 逗號(,):可以用逗號隔開的值指定一個列表范圍,例如,“1,2,5,7,8,9” * 中杠(-):可以用整數之間的中杠表示一個整數范圍,例如“2-6”表示“2,3,4,5,6” * 正斜線(/):可以用正斜線指定時間的間隔頻率,例如“0-23/2”表示每兩小時執行一次。同時正斜線可以和星號一起使用,例如*/10,如果用在minute字段,表示每十分鍾執行一次。
(3)crontab文件舉例
0 */3 * * * /usr/local/apache2/apachectl restart
#表示每隔3個小時重啟apache服務一次。
30 3 * * 6 /webdata/bin/backup.sh
#表示每周六的3點30分執行/webdata/bin/backup.sh腳本的操作。
0 0 1,20 * * fsck /dev/sdb8
#表示每個月的1號和20號檢查/dev/sdb8磁盤設備。
10 5 */5 * * echo "">/usr/local/apache2/log/access_log
#表示每個月的5號、10號、15號、20號、25號、30號的5點10分執行清理apache日志操作。
(4)任務調度設置文件的寫法
可用crontab -e命令來編輯,編輯的是/var/spool/cron下對應用戶的cron文件,也可以直接修改/etc/crontab文件
具體格式如下:
Minute Hour Day Month Dayofweek command 分鍾 小時 天 月 天每星期 命令 每個字段代表的含義如下: Minute 每個小時的第幾分鍾執行該任務 Hour 每天的第幾個小時執行該任務 Day 每月的第幾天執行該任務 Month 每年的第幾個月執行該任務 DayOfWeek 每周的第幾天執行該任務 Command 指定要執行的程序
在這些字段里,除了“Command”是每次都必須指定的字段以外,其它字段皆為可選字段,可視需要決定。對於不指定的字段,要用“*”來填補其位置。
舉例如下:
5 * * * * ls 指定每小時的第5分鍾執行一次ls命令 30 5 * * * ls 指定每天的 5:30 執行ls命令 30 7 8 * * ls 指定每月8號的7:30分執行ls命令 30 5 8 6 * ls 指定每年的6月8日5:30執行ls命令 30 6 * * 0 ls 指定每星期日的6:30執行ls命令[注:0表示星期天,1表示星期1,
以此類推,也可以用英文來表示,sun表示星期天,mon表示星期一等。
30 3 10,20 * * ls 每月10號及20號的3:30執行ls命令[注:“,”用來連接多個不連續的時段 25 8-11 * * * ls 每天8-11點的第25分鍾執行ls命令[注:“-”用來連接連續的時段 */15 * * * * ls 每15分鍾執行一次ls命令 [即每個小時的第0 15 30 45 60分鍾執行ls命令 30 6 */10 * * ls 每個月中,每隔10天6:30執行一次ls命令[即每月的1、11、21、31日是的6:30執行一次ls 命令。
每天7:50以root 身份執行/etc/cron.daily目錄中的所有可執行文件
50 7 * * * root run-parts /etc/cron.daily [ 注:run-parts參數表示,執行后面目錄中的所有可執行文件。
(5)cron文件語法:
分 小時 日 月 星期 命令 0-59 0-23 1-31 1-12 0-6 command (取值范圍,0表示周日一般一行對應一個任務)
記住幾個特殊符號的含義:
“*”代表取值范圍內的數字, “/”代表”每”, “-”代表從某個數字到某個數字, “,”分開幾個離散的數字
(6)應用案例
1:
30 30,12 * * * /bin/sh /scripts/andy.sh
在本例中,該定時任務的意思就是每天凌晨3點30分和中午12點30分執行/scripts/andy.sh
2:
30 */6 * * * /bin/sh /scripts/andy.sh
每隔6個小時的半點時刻執行后面的腳本任務
3:
30 8-18/2 * * * /bin/sh /scripts/andy.sh
8點到18點中每隔2小時的30分執行后面的腳本任務(也就是每天的8點半,10點半,12點半,14點半,16點半,18點半)
4:
45 4 1,10,22 * * /application/apache/bin/apachectl graceful
每月的1,10,22日的凌晨4:45分重啟apache
5:
* 23,00-07/1 * * * /application/apache/bin/apachectl gracefull
上面的例子並不表示晚上23點和早上0-7點之間每隔一小時重啟apache
提示:以上結果是不規范的,也是不對的。
以上的定時任務的第一列為*,表示每分都執行任務即晚上23點和早上0-7點之間每隔一小時的每分都重啟apache
三、 使用crontab工具的注意事項
(1)注意環境變量問題
有時我們創建了一個crontab,但是這個任務卻無法自動執行,而手動執行這個任務卻沒有問題,這種情況一般是由於在crontab文件中沒有配置環境變量引起的。
在crontab文件中定義多個調度任務時,需要特別注意的一個問題就是環境變量的設置,因為我們手動執行某個任務時,是在當前shell環境下進行的, 程序當然能找到環境變量,而系統自動執行任務調度時,是不會加載任何環境變量的,因此,就需要在crontab文件中指定任務運行所需的所有環境變量,這樣,系統執行任務調度時就沒有問題了。
(2)注意清理系統用戶的郵件日志
每條任務調度執行完畢,系統都會將任務輸出信息通過電子郵件的形式發送給當前系統用戶,這樣日積月累,日志信息會非常大,可能會影響系統的正常運行,因此,將每條任務進行重定向處理非常重要。
例如,可以在crontab文件中設置如下形式,忽略日志輸出:
0 */3 * * * /usr/local/apache2/apachectl restart >/dev/null 2>&1
“/dev/null 2>&1”表示先將標准輸出重定向到/dev/null,然后將標准錯誤重定向到標准輸出,由於標准輸出已經重定向到了/dev/null,因此標准錯誤也會重定向到/dev/null,這樣日志輸出問題就解決了。
為crontab中的任務增加自己的日志,這樣出錯后,比較容易看到原因。
0 6 * * * $HOME/for_crontab/createTomorrowTables >> $HOME/for_crontab/mylog.log 2>&1
把錯誤輸出和標准輸出都輸出到mylog.log中。
注意:不要寫成
0 6 * * * $HOME/for_crontab/createTomorrowTables 2>&1 >> $HOME/for_crontab/mylog.log
否則就輸出到標准輸出了
(3)系統級任務調度與用戶級任務調度
系統級任務調度主要完成系統的一些維護操作,用戶級任務調度主要完成用戶自定義的一些任務,可以將用戶級任務調度放到系統級任務調度來完成(不建議這么做),但是反過來卻不行,root用戶的任務調度操作可以通過“crontab –uroot –e”來設置,也可以將調度任務直接寫入/etc/crontab文件,需要注意的是,如果要定義一個定時重啟系統的任務,就必須將任務放到/etc /crontab文件,即使在root用戶下創建一個定時重啟系統的任務也是無效的。
四:企業生產場景如何調試crontab定時任務
(1)增加執行任務頻率調試任務(某些任務不能用於生產環境,沒有測試機會)
代碼發布:個人開發環境 -- 辦公測試環境 -- IDC機房測試環境 -- IDC正式環境(分組,灰度發布)
(2)調整系統時間調試任務(不能直接用於生產環境),保持五分鍾
(3)通過腳本日志輸出調試定時任務
(4)注意一些任務命令帶來的問題
(5)注意環境變量導致的定時任務故障(java環境變量問題: http://oldboy.blog.51cto.com/2561410/1541515)
(6)通過crond定時任務服務日志調試定時任務(/var/log/cron)
(7)其他稀奇古怪的問題調試的辦法
五:crontab定時任務生產應用問題八箴言
1:系統環境變量問題
2:定時任務要用絕對路徑
3:腳本權限問題加/bin/sh
4:時間變量問題用反斜線\%轉義,最好用腳本
5:>/dev/null 2>&1問題(1>/dev/null 2>/dev/null &>/dev/null)
6:定時任務規則之前加注釋
7:使用腳本程序替代命令行定時任務
8:避免不必要的程序及命令輸出
9:切到目標目錄的上一級打包目標
10:定時任務腳本中的程序命令盡量用全路徑(和環境變量的識別有關)
六:練習題
一:每周六,日上午9:00 和下午14:00去參加linux培訓學習(執行/gin/scripts/poe.sh)
要求:/gin/scripts/poe.sh腳本的功能是打印當天的日期:格式為:2016-00-10,可以隨意!
1:定時任務一定盡量用腳本實現
2:命令行操作成功,然后放到腳本執行成功,最后再配置任務
3:復制操作成功的命令行腳本,再定時任務里配置。
解答:
步驟1:創建目錄/gin/scripts和編寫poe.sh腳本
[root@Gin scripts]# mkdir /gin/scripts -p [root@Gin scripts]# echo 'date +%F' >poe.sh [root@Gin scripts]# /bin/sh /gin/scripts/poe.sh 2017-01-30
步驟2:書寫定時任務
[root@Gin scripts]# echo '#study to linux' >>/var/spool/cron/root [root@Gin scripts]# echo '00 09,14 * * 6,0 /bin/sh /gin/scripts/poe.sh >/dev/null 2>&1' >>/var/spool/cron/root [root@Gin scripts]# crontab -l */10 * * * * /usr/sbin/ntpdate time.nist.gov >/dev/null 2>&1 #study to linux 00 09,14 * * 6,0 /bin/sh /gin/scripts/poe.sh >/dev/null 2>&1
也可以輸入crontab -e 然后寫入如下內容保存:
#study to linux 00 09,14 * * 6,0 /bin/sh /server/scripts/poe.sh >/dev/null 2>&1
書寫定時任務的若干要領方法:
1:為定時任務規則加必要的注釋
2:定時任務命令或程序最好寫到腳本里執行
3:執行shell腳本任務前加/bin/sh
4:定時任務命令或腳本結尾加 >/dev/null 2>&1
【
結尾為什么要加 >/dev/null 2>&1呢?
C5:sendmail : /var/spool/clientmqueue/ -> 郵件的臨時隊列目錄
系統中開啟了 cron,而cron中執行的程序有輸出內容,輸出內容會以郵件形式發給cron的用戶,而sendmail沒有啟動所以就會在上述目錄產生N個小文件,導致的后果就是把磁盤的inode滿。 -> no space left on device.
C6:postfix /var/spool/postfix/maildrop/ and /var/spool/postfix/maildrop,同上,小文件太多造成inode索引使用完
問題表現和檢查:
1):運行 df -i 查看inode使用是否滿
2):查看/var/spool/postfix/maildrop 是否有非常多的小文件,ls直接卡死等情況;
解決:
1):cd /var/spool/postfix/maildrop; ls|xrags rm -f;
2):vi /etc/crontab; 將’MAILTO=root’替換成’MAILTO=””’,然后service crond restart即可。如不行則 crontab -e第一行增加’MAILTO=””’。
】
5:在指定用戶下執行相關的定時任務
6:生產任務程序不要隨意打印輸出信息 , tar zcf echo 123>a.log
7:定時任務執行的腳本要規范路徑(/server/scripts)
8:配置定時任務規范操作過程
二:每隔兩小時將系統文件/etc/service文件打包備份到/tmp下(每次備份按時間生成不同的備份包)
(1)在命令行把具體打包命令調用成功
[root@gin etc]# cd /etc [root@gin etc]# tar zcvf /tmp/services_$(date +%F-%H).tar.gz ./services ./services [root@gin etc]# ll /tmp -rw-r--r--. 1 root root 641020 Oct 2 2013 services -rw-r--r-- 1 root root 127304 Oct 7 20:57 services_2016-10-07-20.tar.gz
(2)寫腳本 /server/scripts/tar.sh
[root@gin scripts]# cd /server/scripts/ [root@gin scripts]# vim tar.sh cd /etc && tar zcf /tmp/services_$(date +%F-%H).tar.gz ./services //測試腳本是否可以運行成功 [root@gin scripts]# /bin/sh /server/scripts/tar.sh [root@gin scripts]# ll /tmp -rw-r--r-- 1 root root 127304 Oct 7 21:18 services_2016-10-07-21.tar.gz
(3)寫入到定時任務中
[root@gin scripts]# crontab -e //內容如下: #tar for /etc/services 2 hours per 00 */2 * * * /bin/sh /server/scripts/tar.sh >/dev/null 2>&1 //測試腳本 [root@gin scripts]# /bin/sh -x /server/scripts/tar.sh //-x表示查看命令執行過程 + cd /etc ++ date +%F-%H + tar zcf /tmp/services_2016-10-07-22.tar.gz ./services
定時任務每次執行,都會產生日志文件,定時任務的日志文件目錄:
[root@gin scripts]# ll /var/log/cron* -rw------- 1 root root 25801 Oct 7 21:30 /var/log/cron -rw-------. 1 root root 5706 Sep 7 16:10 /var/log/cron-20160907 -rw------- 1 root root 8547 Sep 11 11:24 /var/log/cron-20160911 -rw------- 1 root root 38127 Sep 27 10:50 /var/log/cron-20160927 -rw------- 1 root root 19588 Oct 2 11:18 /var/log/cron-20161002 [root@gin scripts]# cat /var/log/cron //查看日志
三:每分鍾打印一次自己的名字到/server/log/自己的名字命名的文件中
[root@Gin scripts]# crontab -e #print char task by andy for programer A at 2016-10-10 */1 * * * * echo “andy” >/server/log/andy.log 2>&1
四:每隔1分鍾,打印一個+號到andy.log
echo ‘#print a “+” every min by andy 2016-10-10’>>/var/spool/cron/root echo ‘*/1 * * * * echo + >>/tmp/andy.log’>>/var/spool/cron/root
或者:
[root@Andy andy]# echo '#!/bin/bash' >echo.sh [root@Andy andy]# echo 'echo `date` >>/tmp/andy.log' >>echo.sh