Linux運維五:定時任務crond服務


一、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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM