鸟哥的Linux私房菜(基础篇)- 第十六章、例行性工作排程 (crontab)
最近升級日期:2009/09/11
| 學習了基礎篇也一陣子了,你會發(fā)現(xiàn)到為什么系統(tǒng)常常會主動的進行一些任務?這些任務到底是誰在配置工作的?如果你想要讓自己設計的備份程序可以自動的在系統(tǒng)底下運行,而不需要手動來啟動他,又該如何處置?這些例行的工作可能又分為『單一』工作與『循環(huán)』工作,在系統(tǒng)內又是哪些服務在負責?還有還有,如果你想要每年在老婆的生日前一天就發(fā)出一封信件提醒自己不要忘記,可以辦的到嗎?嘿嘿!這些種種要如何處理,就看看這一章先! |
1. 什么是例行性工作排程
1.1 Linux 工作排程的種類: at, crontab
1.2 Linux 上常見的例行性工作
2. 僅運行一次的工作排程
2.1 atd 的啟動與 at 運行的方式: /etc/at.deny
2.2 實際運行單一工作排程: at,atq & atrm, batch
3. 循環(huán)運行的例行性工作排程
3.1 使用者的配置: /etc/cron.deny, crontab
3.2 系統(tǒng)的配置檔: /etc/crontab
3.3 一些注意事項
4. 可喚醒停機期間的工作任務
4.1 什么是 anacron
4.2 anacron 與 /etc/anacrontab
5. 重點回顧
6. 本章習題
7. 針對本文的建議:http://phorum.vbird.org/viewtopic.php?t=23889
什么是例行性工作排程
每個人或多或少都有一些約會或者是工作,有的工作是例行性的,例如每年一次的加薪、每個月一次的工作報告、每周一次的午餐會報、每天需要的打卡等等;有的工作則是臨時發(fā)生的,例如剛好總公司有高官來訪,需要你準備演講器材等等!用在生活上面,例如每年的愛人的生日、每天的起床時間等等、還有突發(fā)性的計算機大降價 (啊!真希望天天都有!) 等等羅。
像上面這些例行性工作,通常你得要記錄在行事歷上面才能避免忘記!不過,由於我們常常在計算機前面的緣故,如果計算機系統(tǒng)能夠主動的通知我們的話,那么不就輕松多了!嘿嘿!這個時候 Linux 的例行性工作排程就可以派上場了!在不考慮硬件與我們服務器的連結狀態(tài)下,我們的 Linux 可以幫你提醒很多任務,例如:每一天早上 8:00 鐘要服務器連接上音響,并啟動音樂來喚你起床;而中午12:00 希望 Linux 可以發(fā)一封信到你的郵件信箱,提醒你可以去吃午餐了;另外,在每年的你愛人生日的前一天,先發(fā)封信提醒你,以免忘記這么重要的一天。
那么 Linux 的例行性工作是如何進行排程的呢?所謂的排程就是將這些工作安排運行的流程之意!咱們的 Linux 排程就是透過 crontab 與 at 這兩個東西!這兩個玩意兒有啥異同?就讓我們來瞧瞧先!
Linux 工作排程的種類: at, cron
從上面的說明當中,我們可以很清楚的發(fā)現(xiàn)兩種工作排程的方式:
- 一種是例行性的,就是每隔一定的周期要來辦的事項;
- 一種是突發(fā)性的,就是這次做完以后就沒有的那一種 (計算機大降價...)
那么在 Linux 底下如何達到這兩個功能呢?那就得使用 at 與 crontab 這兩個好東西羅!
- at :at 是個可以處理僅運行一次就結束排程的命令,不過要運行 at 時,必須要有 atd 這個服務 (第十八章) 的支持才行。在某些新版的 distributions 中,atd 可能默認并沒有啟動,那么 at 這個命令就會失效呢!不過我們的 CentOS 默認是啟動的!
- crontab :crontab 這個命令所配置的工作將會循環(huán)的一直進行下去!可循環(huán)的時間為分鐘、小時、每周、每月或每年等。crontab 除了可以使用命令運行外,亦可編輯 /etc/crontab 來支持。至於讓 crontab 可以生效的服務則是 crond 這個服務喔!
底下我們先來談一談 Linux 的系統(tǒng)到底在做什么事情,怎么有若干多的工作排程在進行呢?然后再回來談一談at 與 crontab 這兩個好東西!
Linux 上常見的例行性工作
如果你曾經使用過 Linux 一陣子了,那么你大概會發(fā)現(xiàn)到 Linux 會主動的幫我們進行一些工作呢!比方說自動的進行線上升級 (on-line update)、自動的進行 updatedb (第七章談到的 locate 命令) 升級檔名數(shù)據(jù)庫、自動的作登錄檔分析(所以 root 常常會收到標題為 logwatch 的信件) 等等。這是由於系統(tǒng)要正常運行的話,某些在背景底下的工作必須要定時進行的緣故。基本上 Linux 系統(tǒng)常見的例行性任務有:
- 進行登錄檔的輪替 (log rotate):
Linux 會主動的將系統(tǒng)所發(fā)生的各種資訊都記錄下來,這就是登錄檔 (第十九章)。由於系統(tǒng)會一直記錄登錄資訊,所以登錄檔將會越來越大!我們知道大型文件不但占容量還會造成讀寫效能的困擾,因此適時的將登錄檔數(shù)據(jù)挪一挪,讓舊的數(shù)據(jù)與新的數(shù)據(jù)分別存放,則比較可以有效的記錄登錄資訊。這就是 log rotate 的任務!這也是系統(tǒng)必要的例行任務;
- 登錄檔分析 logwatch 的任務:
如果系統(tǒng)發(fā)生了軟件問題、硬件錯誤、資安問題等,絕大部分的錯誤資訊都會被記錄到登錄檔中,因此系統(tǒng)管理員的重要任務之一就是分析登錄檔。但你不可能手動透過 vim 等軟件去檢視登錄檔,因為數(shù)據(jù)太復雜了!我們的 CentOS 提供了一只程序『 logwatch 』來主動分析登錄資訊,所以你會發(fā)現(xiàn),你的 root 老是會收到標題為 logwatch的信件,那是正常的!你最好也能夠看看該信件的內容喔!
- 創(chuàng)建 locate 的數(shù)據(jù)庫:
在第七章我們談到的 locate 命令時,我們知道該命令是透過已經存在的檔名數(shù)據(jù)庫來進行系統(tǒng)上檔名的查詢。我們的檔名數(shù)據(jù)庫是放置到 /var/lib/mlocate/ 中。問題是,這個數(shù)據(jù)庫怎么會自動升級啊?嘿嘿!這就是系統(tǒng)的例行性工作所產生的效果啦!系統(tǒng)會主動的進行updatedb 喔!
- whatis 數(shù)據(jù)庫的創(chuàng)建:
與 locate 數(shù)據(jù)庫類似的,whatis 也是個數(shù)據(jù)庫,這個 whatis 是與man page 有關的一個查詢命令,不過要使用 whatis 命令時,必須要擁有 whatis 數(shù)據(jù)庫,而這個數(shù)據(jù)庫也是透過系統(tǒng)的例行性工作排程來自動運行的哩!
- RPM 軟件登錄檔的創(chuàng)建:
RPM (第二十三章) 是一種軟件管理的機制。由於系統(tǒng)可能會常常變更軟件,包括軟件的新安裝、非經常性升級等,都會造成軟件檔名的差異。為了方便未來追蹤,系統(tǒng)也幫我們將檔名作個排序的記錄呢!有時候系統(tǒng)也會透過排程來幫忙 RPM 數(shù)據(jù)庫的重新建置喔!
- 移除緩存檔:
某些軟件在運行中會產生一些緩存檔,但是當這個軟件關閉時,這些緩存檔可能并不會主動的被移除。有些緩存檔則有時間性,如果超過一段時間后,這個緩存檔就沒有效用了,此時移除這些緩存檔就是一件重要的工作!否則磁碟容量會被耗光。系統(tǒng)透過例行性工作排程運行名為 tmpwatch 的命令來刪除這些緩存檔呢!
- 與網絡服務有關的分析行為:
如果你有安裝類似 WWW 服務器軟件 (一個名為 apache 的軟件),那么你的 Linux 系統(tǒng)通常就會主動的分析該軟件的登錄檔。同時某些憑證與認證的網絡資訊是否過期的問題,我們的 Linux 系統(tǒng)也會很親和的幫你進行自動檢查!
其實你的系統(tǒng)會進行的例行性工作與你安裝的軟件多寡有關,如果你安裝過多的軟件,某些服務功能的軟件都會附上分析工具,那么你的系統(tǒng)就會多出一些例行性工作羅!像鳥哥的主機還多加了很多自己撰寫的分析工具,以及其他第三方協(xié)力軟件的分析軟件,嘿嘿!俺的 Linux 工作量可是非常大的哩!因為有這么多的工作需要進行,所以我們當然得要了解例行性工作的處理方式羅!
僅運行一次的工作排程
首先,我們先來談談單一工作排程的運行,那就是 at 這個命令的運行!
atd 的啟動與 at 運行的方式
要使用單一工作排程時,我們的 Linux 系統(tǒng)上面必須要有負責這個排程的服務,那就是 atd 這個玩意兒。不過并非所有的 Linux distributions 都默認會把他打開的,所以呢,某些時刻我們必須要手動將他激活才行。激活的方法很簡單,就是這樣:
| [root@www ~]# /etc/init.d/atd restart 正在停止 atd: [ 確定 ] 正在啟動 atd: [ 確定 ]# 再配置一下啟動時就啟動這個服務,免得每次重新啟動都得再來一次! [root@www ~]# chkconfig atd on |
重點是那個『正在啟動(或 starting)』項目的 OK 啦!那表示啟動是正常的!這部份我們在第十八章會談及。如果您真的有興趣,那么可以自行到 /etc/init.d/atd 這個 shell script 內去瞧一瞧先! ^_^。至於那個 chkconfig ,你也可以使用 man 先查閱一下啊!我們第十八章再介紹啦!
- at 的運行方式
既然是工作排程,那么應該會有產生工作的方式,并且將這些工作排進行程表中羅!OK!那么產生工作的方式是怎么進行的?事實上,我們使用 at 這個命令來產生所要運行的工作,并將這個工作以文字檔的方式寫入/var/spool/at/ 目錄內,該工作便能等待 atd 這個服務的取用與運行了。就這么簡單。
不過,并不是所有的人都可以進行 at 工作排程喔!為什么?因為安全的理由啊~很多主機被所謂的『綁架』后,最常發(fā)現(xiàn)的就是他們的系統(tǒng)當中多了很多的怪客程序 (cracker program),這些程序非??赡苓\用工作排程來運行或搜集系統(tǒng)資訊,并定時的回報給怪客團體!所以羅,除非是你認可的帳號,否則先不要讓他們使用 at 吧!那怎么達到使用 at 的列管呢?
我們可以利用 /etc/at.allow 與 /etc/at.deny 這兩個文件來進行 at 的使用限制呢!加上這兩個文件后, at 的工作情況其實是這樣的:
透過這個說明,我們知道 /etc/at.allow 是管理較為嚴格的方式,而 /etc/at.deny 則較為松散 (因為帳號沒有在該文件中,就能夠運行 at 了)。在一般的 distributions 當中,由於假設系統(tǒng)上的所有用戶都是可信任的,因此系統(tǒng)通常會保留一個空的 /etc/at.deny 文件,意思是允許所有人使用 at 命令的意思 (您可以自行檢查一下該文件)。不過,萬一你不希望有某些使用者使用 at 的話,將那個使用者的帳號寫入 /etc/at.deny 即可!一個帳號寫一行。
實際運行單一工作排程
單一工作排程的進行就使用 at 這個命令羅!這個命令的運行非常簡單!將 at 加上一個時間即可!基本的語法如下:
| [root@www ~]# at [-mldv] TIME [root@www ~]# at -c 工作號碼 選項與參數(shù): -m :當 at 的工作完成后,即使沒有輸出信息,亦以 email 通知使用者該工作已完成。 -l :at -l 相當於 atq,列出目前系統(tǒng)上面的所有該使用者的 at 排程; -d :at -d 相當於 atrm ,可以取消一個在 at 排程中的工作; -v :可以使用較明顯的時間格式列出 at 排程中的工作列表; -c :可以列出后面接的該項工作的實際命令內容。TIME:時間格式,這里可以定義出『什么時候要進行 at 這項工作』的時間,格式有:HH:MM ex> 04:00在今日的 HH:MM 時刻進行,若該時刻已超過,則明天的 HH:MM 進行此工作。HH:MM YYYY-MM-DD ex> 04:00 2009-03-17強制規(guī)定在某年某月的某一天的特殊時刻進行該工作!HH:MM[am|pm] [Month] [Date] ex> 04pm March 17也是一樣,強制在某年某月某日的某時刻進行!HH:MM[am|pm] + number [minutes|hours|days|weeks]ex> now + 5 minutes ex> 04pm + 3 days就是說,在某個時間點『再加幾個時間后』才進行。 |
老實說,這個 at 命令的下達最重要的地方在於『時間』的指定了!鳥哥喜歡使用『 now + ... 』的方式來定義現(xiàn)在過多少時間再進行工作,但有時也需要定義特定的時間點來進行!底下的范例先看看羅!
| 范例一:再過五分鐘后,將 /root/.bashrc 寄給 root 自己 [root@www ~]# at now + 5 minutes <==記得單位要加 s 喔! at> /bin/mail root -s "testing at job" < /root/.bashrc at> <EOT> <==這里輸入 [ctrl] + d 就會出現(xiàn) <EOF> 的字樣!代表結束! job 4 at 2009-03-14 15:38 # 上面這行資訊在說明,第 4 個 at 工作將在 2009/03/14 的 15:38 進行! # 而運行 at 會進入所謂的 at shell 環(huán)境,讓你下達多重命令等待運行!范例二:將上述的第 4 項工作內容列出來查閱 [root@www ~]# at -c 4 #!/bin/sh <==就是透過 bash shell 的啦! # atrun uid=0 gid=0 # mail root 0 umask 22 ....(中間省略許多的環(huán)境變量項目).... cd /root || { <==可以看出,會到下達 at 時的工作目錄去運行命令echo 'Execution directory inaccessible' >&2exit 1 }/bin/mail root -s "testing at job" < /root/.bashrc # 你可以看到命令運行的目錄 (/root),還有多個環(huán)境變量與實際的命令內容啦!范例三:由於機房預計於 2009/03/18 停電,我想要在 2009/03/17 23:00 關機? [root@www ~]# at 23:00 2009-03-17 at> /bin/sync at> /bin/sync at> /sbin/shutdown -h now at> <EOT> job 5 at 2009-03-17 23:00 # 您瞧瞧! at 還可以在一個工作內輸入多個命令呢!不錯吧! |
事實上,當我們使用 at 時會進入一個 at shell 的環(huán)境來讓使用者下達工作命令,此時,建議你最好使用絕對路徑來下達你的命令,比較不會有問題喔!由於命令的下達與 PATH 變量有關,同時與當時的工作目錄也有關連 (如果有牽涉到文件的話),因此使用絕對路徑來下達命令,會是比較一勞永逸的方法。為什么呢?舉例來說,你在 /tmp 下達『 at now 』然后輸入『 mail root -s "test" < .bashrc 』,問一下,那個 .bashrc 的文件會是在哪里?答案是『 /tmp/.bashrc 』!因為at 在運行時,會跑到當時下達 at 命令的那個工作目錄的緣故啊!
有些朋友會希望『我要在某某時刻,在我的終端機顯示出 Hello 的字樣』,然后就在 at 里面下達這樣的資訊『echo "Hello" 』。等到時間到了,卻發(fā)現(xiàn)沒有任何信息在螢幕上顯示,這是啥原因啊?這是因為 at 的運行與終端機環(huán)境無關,而所有 standard output/standard error output都會傳送到運行者的 mailbox 去啦!所以在終端機當然看不到任何資訊。那怎辦?沒關系,可以透過終端機的裝置來處理!假如你在 tty1 登陸,則可以使用『 echo "Hello" > /dev/tty1 』來取代。
| Tips: 要注意的是,如果在 at shell 內的命令并沒有任何的信息輸出,那么 at 默認不會發(fā) email 給運行者的。如果你想要讓 at 無論如何都發(fā)一封 email 告知你是否運行了命令,那么可以使用『 at -m 時間格式 』來下達命令喔!at 就會傳送一個信息給運行者,而不論該命令運行有無信息輸出了! |
at 有另外一個很棒的優(yōu)點,那就是『背景運行』的功能了!什么是背景運行啊?很難了解嗎?其實與 bash 的 nohup (第十七章) 類似啦!鳥哥提我自己的幾個例子來給您聽聽,您就了了!
- 離線繼續(xù)工作的任務:鳥哥初次接觸 Unix 為的是要跑空氣品質模式,那是一種大型的程序,這個程序在當時的硬件底下跑,一個案例要跑 3 天!由於鳥哥也要進行其他研究工作,因此常常使用 Windows98 來連線到 Unix 工作站跑那個 3 天的案例!結果你也該知道, Windows 98 連開三天而不死機的機率是很低的~@_@~而死機時,所有在 Windows 上的連線都會中斷!包括鳥哥在跑的那個程序也中斷了~嗚嗚~明明再三個鐘頭就跑完的程序,由於死機害我又得跑 3 天!
- 另一個常用的時刻則是例如上面的范例三,由於某個突發(fā)狀況導致你必須要進行某項工作時,這個 at 就很好用啦!
由於 at 工作排程的使用上,系統(tǒng)會將該項 at 工作獨立出你的 bash 環(huán)境中,直接交給系統(tǒng)的 atd 程序來接管,因此,當你下達了 at 的工作之后就可以立刻離線了,剩下的工作就完全交給 Linux 管理即可!所以羅,如果有長時間的網絡工作時,嘿嘿!使用 at 可以讓你免除網絡斷線后的困擾喔! ^_^
- at 工作的管理
那么萬一我下達了 at 之后,才發(fā)現(xiàn)命令輸入錯誤,該如何是好?就將他移除啊!利用 atq 與 atrm 吧!
| [root@www ~]# atq [root@www ~]# atrm (jobnumber)范例一:查詢目前主機上面有多少的 at 工作排程? [root@www ~]# atq 5 2009-03-17 23:00 a root # 上面說的是:『在 2009/03/17 的 23:00 有一項工作,該項工作命令下達者為 # root』而且,該項工作的工作號碼 (jobnumber) 為 5 號喔!范例二:將上述的第 5 個工作移除! [root@www ~]# atrm 5 [root@www ~]# atq # 沒有任何資訊,表示該工作被移除了! |
如此一來,你可以利用 atq 來查詢,利用 atrm 來刪除錯誤的命令,利用 at 來直接下達單一工作排程!很簡單吧!不過,有個問題需要處理一下。如果你是在一個非常忙碌的系統(tǒng)下運行 at ,能不能指定你的工作在系統(tǒng)較閑的時候才進行呢?可以的,那就使用 batch 命令吧!
- batch:系統(tǒng)有空時才進行背景任務
其實 batch 是利用 at 來進行命令的下達啦!只是加入一些控制參數(shù)而已。這個 batch 神奇的地方在於:他會在 CPU 工作負載小於 0.8 的時候,才進行你所下達的工作任務啦!那什么是負載 0.8 呢?這個負載的意思是: CPU 在單一時間點所負責的工作數(shù)量。不是 CPU 的使用率喔!舉例來說,如果我有一只程序他需要一直使用 CPU 的運算功能,那么此時 CPU 的使用率可能到達 100% ,但是 CPU 的工作負載則是趨近於『 1 』,因為 CPU 僅負責一個工作嘛!如果同時運行這樣的程序兩支呢?CPU 的使用率還是 100% ,但是工作負載則變成 2 了!了解乎?
所以也就是說,當 CPU 的工作負載越大,代表 CPU 必須要在不同的工作之間進行頻繁的工作切換。這樣的 CPU 運行情況我們在第零章有談過,忘記的話請回去瞧瞧!因為一直切換工作,所以會導致系統(tǒng)忙碌啊!系統(tǒng)如果很忙碌,還要額外進行 at ,不太合理!所以才有 batch 命令的產生!
那么 batch 如何下達命令呢?很簡單啊!與 at 相同啦!例如下面的范例:
| 范例一:同樣是機房停電在 2009/3/17 23:00 關機,但若當時系統(tǒng)負載太高,則暫緩運行 [root@www ~]# batch 23:00 2009-3-17 at> sync at> sync at> shutdown -h now at> <EOT> job 6 at 2009-03-17 23:00[root@www ~]# atq 6 2009-03-17 23:00 b root [root@www ~]# atrm 6 |
你會發(fā)現(xiàn)其實 batch 也是使用 atq/atrm 來管理的!這樣了解乎?
循環(huán)運行的例行性工作排程
相對於 at 是僅運行一次的工作,循環(huán)運行的例行性工作排程則是由 cron (crond)這個系統(tǒng)服務來控制的。剛剛談過 Linux 系統(tǒng)上面原本就有非常多的例行性工作,因此這個系統(tǒng)服務是默認啟動的。另外,由於使用者自己也可以進行例行性工作排程,所以羅, Linux 也提供使用者控制例行性工作排程的命令 (crontab)。底下我們分別來聊一聊羅!
使用者的配置
使用者想要創(chuàng)建循環(huán)型工作排程時,使用的是 crontab 這個命令啦~不過,為了安全性的問題,與 at 同樣的,我們可以限制使用 crontab 的使用者帳號喔!使用的限制數(shù)據(jù)有:
- /etc/cron.allow:
將可以使用 crontab 的帳號寫入其中,若不在這個文件內的使用者則不可使用 crontab;
- /etc/cron.deny:
將不可以使用 crontab 的帳號寫入其中,若未記錄到這個文件當中的使用者,就可以使用 crontab 。
與 at 很像吧!同樣的,以優(yōu)先順序來說, /etc/cron.allow 比 /etc/cron.deny 要優(yōu)先,而判斷上面,這兩個文件只選擇一個來限制而已,因此,建議你只要保留一個即可,免得影響自己在配置上面的判斷!一般來說,系統(tǒng)默認是保留 /etc/cron.deny ,你可以將不想讓他運行 crontab 的那個使用者寫入 /etc/cron.deny 當中,一個帳號一行!
當使用者使用 crontab 這個命令來創(chuàng)建工作排程之后,該項工作就會被紀錄到 /var/spool/cron/ 里面去了,而且是以帳號來作為判別的喔!舉例來說, dmtsai 使用 crontab 后,他的工作會被紀錄到 /var/spool/cron/dmtsai 里頭去!但請注意,不要使用 vi 直接編輯該文件,因為可能由於輸入語法錯誤,會導致無法運行 cron 喔!另外, cron 運行的每一項工作都會被紀錄到/var/log/cron 這個登錄檔中,所以羅,如果你的 Linux 不知道有否被植入木馬時,也可以搜尋一下 /var/log/cron 這個登錄檔呢!
好了,那么我們就來聊一聊 crontab 的語法吧!
| [root@www ~]# crontab [-u username] [-l|-e|-r] 選項與參數(shù): -u :只有 root 才能進行這個任務,亦即幫其他使用者創(chuàng)建/移除 crontab 工作排程; -e :編輯 crontab 的工作內容 -l :查閱 crontab 的工作內容 -r :移除所有的 crontab 的工作內容,若僅要移除一項,請用 -e 去編輯。范例一:用 dmtsai 的身份在每天的 12:00 發(fā)信給自己 [dmtsai@www ~]$ crontab -e # 此時會進入 vi 的編輯畫面讓您編輯工作!注意到,每項工作都是一行。 0 12 * * * mail dmtsai -s "at 12:00" < /home/dmtsai/.bashrc #分 時 日 月 周 |<==============命令串========================>| |
默認情況下,任何使用者只要不被列入 /etc/cron.deny 當中,那么他就可以直接下達『 crontab -e 』去編輯自己的例行性命令了!整個過程就如同上面提到的,會進入 vi 的編輯畫面,然后以一個工作一行來編輯,編輯完畢之后輸入『 :wq 』儲存后離開 vi 就可以了!而每項工作 (每行) 的格式都是具有六個欄位,這六個欄位的意義為:
| 代表意義 | 分鐘 | 小時 | 日期 | 月份 | 周 | 命令 |
| 數(shù)字范圍 | 0-59 | 0-23 | 1-31 | 1-12 | 0-7 | 呀就命令啊 |
比較有趣的是那個『周』喔!周的數(shù)字為 0 或 7 時,都代表『星期天』的意思!另外,還有一些輔助的字符,大概有底下這些:
| 特殊字符 | 代表意義 |
| *(星號) | 代表任何時刻都接受的意思!舉例來說,范例一內那個日、月、周都是 * ,就代表著『不論何月、何日的禮拜幾的 12:00 都運行后續(xù)命令』的意思! |
| ,(逗號) | 代表分隔時段的意思。舉例來說,如果要下達的工作是 3:00 與 6:00 時,就會是: 0 3,6 * * * command 時間參數(shù)還是有五欄,不過第二欄是 3,6 ,代表 3 與 6 都適用! |
| -(減號) | 代表一段時間范圍內,舉例來說, 8 點到 12 點之間的每小時的 20 分都進行一項工作: 20 8-12 * * * command 仔細看到第二欄變成 8-12 喔!代表 8,9,10,11,12 都適用的意思! |
| /n(斜線) | 那個 n 代表數(shù)字,亦即是『每隔 n 單位間隔』的意思,例如每五分鐘進行一次,則: */5 * * * * command 很簡單吧!用 * 與 /5 來搭配,也可以寫成 0-59/5 ,相同意思! |
我們就來搭配幾個例子練習看看吧!底下的案例請實際用 dmtsai 這個身份作看看喔!后續(xù)的動作才能夠搭配起來!
| 例題: 假若你的女朋友生日是 5 月 2 日,你想要在 5 月 1 日的 23:59 發(fā)一封信給他,這封信的內容已經寫在/home/dmtsai/lover.txt 內了,該如何進行? 答: 直接下達 crontab -e 之后,編輯成為: 59 23 1 5 * mail kiki < /home/dmtsai/lover.txt 那樣的話,每年 kiki 都會收到你的這封信喔!(當然羅,信的內容就要每年變一變啦!) |
| 例題: 假如每五分鐘需要運行 /home/dmtsai/test.sh 一次,又該如何? 答: 同樣使用 crontab -e 進入編輯: */5 * * * * /home/dmtsai/test.sh |
那個 crontab 每個人都只有一個文件存在,就是在 /var/spool/cron 里面啊!還有建議您:『命令下達時,最好使用絕對路徑,這樣比較不會找不到運行檔喔!』
| 例題: 假如你每星期六都與朋友有約,那么想要每個星期五下午 4:30 告訴你朋友星期六的約會不要忘記,則: 答: 還是使用 crontab -e 啊! 30 16 * * 5 mail friend@his.server.name < /home/dmtsai/friend.txt |
真的是很簡單吧!呵呵!那么,該如何查詢使用者目前的 crontab 內容呢?我們可以這樣來看看:
| [dmtsai@www ~]$ crontab -l 59 23 1 5 * mail kiki < /home/dmtsai/lover.txt */5 * * * * /home/dmtsai/test.sh 30 16 * * 5 mail friend@his.server.name < /home/dmtsai/friend.txt# 注意,若僅想要移除一項工作而已的話,必須要用 crontab -e 去編輯~ # 如果想要全部的工作都移除,才使用 crontab -r 喔! [dmtsai@www ~]$ crontab -r [dmtsai@www ~]$ crontab -l no crontab for dmtsai |
看到了嗎? crontab 『整個內容都不見了!』所以請注意:『如果只是要刪除某個 crontab 的工作項目,那么請使用 crontab -e 來重新編輯即可!』如果使用 -r 的參數(shù),是會將所有的 crontab 數(shù)據(jù)內容都刪掉的!千萬注意了!
系統(tǒng)的配置檔: /etc/crontab
這個『 crontab -e 』是針對使用者的 cron 來設計的,如果是『系統(tǒng)的例行性任務』時,該怎么辦呢?是否還是需要以 crontab -e 來管理你的例行性工作排程呢?當然不需要,你只要編輯/etc/crontab 這個文件就可以啦!有一點需要特別注意喔!那就是crontab -e 這個 crontab 其實是 /usr/bin/crontab 這個運行檔,但是 /etc/crontab可是一個『純文字檔』喔!你可以 root 的身份編輯一下這個文件哩!
基本上, cron 這個服務的最低偵測限制是『分鐘』,所以『 cron會每分鐘去讀取一次 /etc/crontab 與 /var/spool/cron 里面的數(shù)據(jù)內容』,因此,只要你編輯完 /etc/crontab 這個文件,并且將他儲存之后,那么 cron 的配置就自動的會來運行了!
| Tips: 在 Linux 底下的 crontab 會自動的幫我們每分鐘重新讀取一次 /etc/crontab 的例行工作事項,但是某些原因或者是其他的 Unix 系統(tǒng)中,由於 crontab 是讀到內存當中的,所以在你修改完 /etc/crontab 之后,可能并不會馬上運行,這個時候請重新啟動 crond 這個服務吧!『/etc/init.d/crond restart』 |
廢話少說,我們就來看一下這個 /etc/crontab 的內容吧!
| [root@www ~]# cat /etc/crontab SHELL=/bin/bash <==使用哪種 shell 介面 PATH=/sbin:/bin:/usr/sbin:/usr/bin <==運行檔搜尋路徑 MAILTO=root <==若有額外STDOUT,以 email將數(shù)據(jù)送給誰 HOME=/ <==默認此 shell 的家目錄所在# 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 <==每個月 1 號 分 時 日 月 周 運行者身份 命令串 |
看到這個文件的內容你大概就了解了吧!呵呵,沒錯!這個文件與將剛剛我們下達 crontab -e 的內容幾乎完全一模一樣!只是有幾個地方不太相同:
- MAILTO=root:
這個項目是說,當 /etc/crontab 這個文件中的例行性工作的命令發(fā)生錯誤時,或者是該工作的運行結果有 STDOUT/STDERR 時,會將錯誤信息或者是螢幕顯示的信息傳給誰?默認當然是由系統(tǒng)直接寄發(fā)一封 mail 給 root 啦!不過,由於 root 并無法在用戶端中以 POP3 之類的軟件收信,因此,鳥哥通常都將這個 e-mail 改成自己的帳號,好讓我隨時了解系統(tǒng)的狀況!例如:MAILTO=dmtsai@my.host.name
- PATH=....:
還記得我們在第十一章的 BASH 當中一直提到的運行檔路徑問題吧!沒錯啦!這里就是輸入運行檔的搜尋路徑!使用默認的路徑配置就已經很足夠了!
- 01 * * * * root run-parts /etc/cron.hourly:
這個 /etc/crontab 里面預配置義出四項工作任務,分別是每小時、每天、每周及每個月分別進行一次的工作!但是在五個欄位后面接的并不是命令,而是一個新的欄位,那就是『運行后面那串命令的身份』為何!這與使用者的 crontab -e 不相同。由於使用者自己的 crontab 并不需要指定身份,但 /etc/crontab 里面當然要指定身份啦!以上表的內容來說,系統(tǒng)默認的例行性工作是以 root的身份來進行的。
那么后面那串命令是什么呢?你可以使用『 which run-parts 』搜尋看看,其實那是一個 bash script 啦!如果你直接進入 /usr/bin/run-parts 去看看,會發(fā)現(xiàn)這支命令會將后面接的『目錄』內的所有文件捉出來運行!這也就是說『如果你想讓系統(tǒng)每小時主動幫你運行某個命令,將該命令寫成 script,并將該文件放置到 /etc/cron.hourly/ 目錄下即可』的意思!
現(xiàn)在你知道系統(tǒng)是如何進行他默認的一堆例行性工作排程了嗎?如果你下達『 ll /etc/cron.daily 』就可以看到一堆文件,那些文件就是系統(tǒng)提供的 script ,而這堆 scripts 將會在每天的凌晨 4:02 開始運行!這也是為啥如果你是夜貓族,就會發(fā)現(xiàn)奇怪的是,Linux 系統(tǒng)為何早上 4:02 開始會很忙碌的發(fā)出一些硬盤跑動的聲音!因為他必須要進行makewhatis, updatedb, rpm rebuild 等等的任務嘛!
由於 CentOS 提供的 run-parts 這個 script 的輔助,因此 /etc/crontab 這個文件里面支持兩種下達命令的方式,一種是直接下達命令,一種則是以目錄來規(guī)劃,例如:
- 命令型態(tài)
01 * * * * dmtsai mail -s "testing" kiki < /home/dmtsai/test.txt
以 dmtsai 這個使用者的身份,在每小時運行一次 mail 命令。
- 目錄規(guī)劃
*/5 * * * * root run-parts /root/runcron
創(chuàng)建一個 /root/runcron 的目錄,將要每隔五分鐘運行的『可運行檔』都寫到該目錄下,就可以讓系統(tǒng)每五分鐘運行一次該目錄下的所有可運行檔。
好!你現(xiàn)在大概了解了這一個咚咚吧!OK!假設你現(xiàn)在要作一個目錄,讓系統(tǒng)可以每 2 分鐘去運行這個目錄下的所有可以運行的文件,你可以寫下如下的這一行在 /etc/crontab 中:
*/2 * * * * root run-parts /etc/cron.min當然羅, /etc/cron.min 這個目錄是需要存在的喔!那如果我需要運行的是一個『程序』而已,不需要用到一個目錄呢?該如何是好?例如在偵測網絡流量時,我們希望每五分鐘偵測分析一次,可以這樣寫:
*/5 * * * * root /bin/mrtg /etc/mrtg/mrtg.cfg如何!創(chuàng)建例行性命令很簡單吧!如果你是系統(tǒng)管理員而且你的工作又是系統(tǒng)維護方面的例行任務時,直接修改 /etc/crontab 這個文件即可喔!又便利,又方便管理呢!
一些注意事項
有的時候,我們以系統(tǒng)的 cron 來進行例行性工作的創(chuàng)建時,要注意一些使用方面的特性。舉例來說,如果我們有四個工作都是五分鐘要進行一次的,那么是否這四個動作全部都在同一個時間點進行?如果同時進行,該四個動作又很耗系統(tǒng)資源,如此一來,每五分鐘不是會讓系統(tǒng)忙得要死?呵呵!此時好好的分配一些運行時間就 OK 啦!所以,注意一下:
- 資源分配不均的問題
當大量使用 crontab 的時候,總是會有問題發(fā)生的,最嚴重的問題就是『系統(tǒng)資源分配不均』的問題,以鳥哥的系統(tǒng)為例,我有偵測主機流量的資訊,包括:
- 流量
- 區(qū)域內其他 PC 的流量偵測
- CPU 使用率
- RAM 使用率
- 線上人數(shù)即時偵測
如果每個流程都在同一個時間啟動的話,那么在某個時段時,我的系統(tǒng)會變的相當?shù)姆泵?#xff0c;所以,這個時候就必須要分別配置啦!我可以這樣做:
| [root@www ~]# vi /etc/crontab 1,6,11,16,21,26,31,36,41,46,51,56 * * * * root CMD1 2,7,12,17,22,27,32,37,42,47,52,57 * * * * root CMD2 3,8,13,18,23,28,33,38,43,48,53,58 * * * * root CMD3 4,9,14,19,24,29,34,39,44,49,54,59 * * * * root CMD4 |
看到了沒?那個『 , 』分隔的時候,請注意,不要有空白字節(jié)!(連續(xù)的意思)如此一來,則可以將每五分鐘工作的流程分別在不同的時刻來工作!則可以讓系統(tǒng)的運行較為順暢呦!
- 取消不要的輸出項目
另外一個困擾發(fā)生在『 當有運行成果或者是運行的項目中有輸出的數(shù)據(jù)時,該數(shù)據(jù)將會mail 給 MAILTO 配置的帳號 』,好啦,那么當有一個排程一直出錯(例如 DNS的偵測系統(tǒng)當中,若 DNS 上一級主機掛掉,那么你就會一直收到錯誤信息!)怎么辦?呵呵!還記得十一章談到的數(shù)據(jù)流重導向吧?直接以『命令重導向』將輸出的結果輸出到/dev/null 這個垃圾桶當中就好了!
- 安全的檢驗
很多時候被植入木馬都是以例行命令的方式植入的,所以可以藉由檢查 /var/log/cron的內容來視察是否有『非您配置的 cron 被運行了?』這個時候就需要小心一點羅!
- 周與日月不可同時并存
另一個需要注意的地方在於:『你可以分別以周或者是日月為單位作為循環(huán),但你不可使用「幾月幾號且為星期幾」的模式工作』。這個意思是說,你不可以這樣編寫一個工作排程:
| 30 12 11 9 5 root echo "just test" <==這是錯誤的寫法 |
本來你以為九月十一號且為星期五才會進行這項工作,無奈的是,系統(tǒng)可能會判定每個星期五作一次,或每年的 9 月 11 號分別進行,如此一來與你當初的規(guī)劃就不一樣了~所以羅,得要注意這個地方!上述的寫法是不對的喔!
可喚醒停機期間的工作任務
如果你的 Linux 主機是作為 24 小時全天、全年無休的服務器之用,那么你只要有 atd 與 crond 這兩個服務來管理你的例行性工作排程即可。如果你的服務器并非 24 小時無間斷的啟動,那么你該如何進行例行性工作?舉例來說,如果你每天晚上都要關機,等到白天才啟動你的 Linux 主機時,由於 CentOS 默認的工作排程都在4:02am 每天進行,唔!如此一來不就一堆系統(tǒng)例行工作都沒有人在做了!那可怎么辦?此時就得要 anacron 這家伙了!
什么是 anacron
anacron 并不是用來取代 crontab 的,anacron 存在的目的就在於我們上頭提到的,在處理非 24 小時一直啟動的 Linux 系統(tǒng)的 crontab 的運行!所以 anacron 并不能指定何時運行某項任務,而是以天為單位或者是在啟動后立刻進行 anacron 的動作,他會去偵測停機期間應該進行但是并沒有進行的crontab 任務,并將該任務運行一遍后,anacron 就會自動停止了。
由於 anacron 會以一天、七天、一個月為期去偵測系統(tǒng)未進行的 crontab 任務,因此對於某些特殊的使用環(huán)境非常有幫助。舉例來說,如果你的 Linux 主機是放在公司給同仁使用的,因為周末假日大家都不在所以也沒有必要開啟,因此你的 Linux 是周末都會關機兩天的。但是 crontab 大多在每天的凌晨以及周日的早上進行各項任務,偏偏你又關機了,此時系統(tǒng)很多 crontab 的任務就無法進行。 anacron 剛好可以解決這個問題!
那么 anacron 又是怎么知道我們的系統(tǒng)啥時關機的呢?這就得要使用 anacron 讀取的時間記錄檔 (timestamps) 了!anacron 會去分析現(xiàn)在的時間與時間記錄檔所記載的上次運行 anacron 的時間,兩者比較后若發(fā)現(xiàn)有差異,那就是在某些時刻沒有進行 crontab 羅!此時 anacron 就會開始運行未進行的 crontab 任務了!所以 anacron 其實也是透過 crontab 來運行的!因此 anacron 運行的時間通常有兩個,一個是系統(tǒng)啟動期間運行,一個是寫入 crontab 的排程中。這樣才能夠在特定時間分析系統(tǒng)未進行的 crontab 工作嘛!了解乎!
anacron 與 /etc/anacrontab
anacron 其實是一支程序并非一個服務!這支程序在 CentOS 當中已經進入 crontab 的排程喔!不相信嗎?你可以這樣追蹤看看:
| [root@www ~]# ll /etc/cron*/*ana* -rwxr-xr-x 1 root root 379 Mar 28 2007 /etc/cron.daily/0anacron -rwxr-xr-x 1 root root 381 Mar 28 2007 /etc/cron.monthly/0anacron -rwxr-xr-x 1 root root 380 Mar 28 2007 /etc/cron.weekly/0anacron # 剛好是每天、每周、每月有排程的工作目錄!查閱一下每天的任務[root@www ~]# cat /etc/cron.daily/0anacron if [ ! -e /var/run/anacron.pid ]; thenanacron -u cron.daily fi # 所以其實也僅是運行 anacron -u 的命令!因此我們得來談談這支程序! |
基本上, anacron 的語法如下:
| [root@www ~]# anacron [-sfn] [job].. [root@www ~]# anacron -u [job].. 選項與參數(shù): -s :開始一連續(xù)的運行各項工作 (job),會依據(jù)時間記錄檔的數(shù)據(jù)判斷是否進行; -f :強制進行,而不去判斷時間記錄檔的時間戳記; -n :立刻進行未進行的任務,而不延遲 (delay) 等待時間; -u :僅升級時間記錄檔的時間戳記,不進行任何工作。 job :由 /etc/anacrontab 定義的各項工作名稱。 |
所以我們發(fā)現(xiàn)其實 /etc/cron.daily/0anacron 僅進行時間戳記的升級,而沒有進行任何 anacron 的動作!在我們的 CentOS 中,anacron 的進行其實是在啟動完成后才進行的一項工作任務,你也可以將 anacron 排入 crontab 的排程中。但是為了擔心 anacron 誤判時間參數(shù),因此 /etc/cron.daily/ 里面的 anacron 才會在檔名之前加個 0 (0anacron),讓 anacron 最先進行!就是為了讓時間戳記先升級!以避免 anacron 誤判 crontab 尚未進行任何工作的意思。
接下來我們看一下 /etc/anacrontab 的內容好了:
| [root@www ~]# cat /etc/anacrontab SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root1 65 cron.daily run-parts /etc/cron.daily 7 70 cron.weekly run-parts /etc/cron.weekly 30 75 cron.monthly run-parts /etc/cron.monthly 天數(shù) 延遲時間 工作名稱定義 實際要進行的命令串 # 天數(shù)單位為天;延遲時間單位為分鐘;工作名稱定義可自訂; # 命令串則通常與 crontab 的配置相同![root@www ~]# more /var/spool/anacron/* :::::::::::::: /var/spool/anacron/cron.daily :::::::::::::: 20090315 :::::::::::::: /var/spool/anacron/cron.monthly :::::::::::::: 20090301 :::::::::::::: /var/spool/anacron/cron.weekly :::::::::::::: 20090315 # 上面則是三個工作名稱的時間記錄檔以及記錄的時間戳記 |
由於 /etc/cron.daily 內的任務比較多,因此我們使用每天進行的任務來解釋一下 anacron 的運行情況好了。anacron 若下達『 anacron -s cron.daily 』時,他會這樣運行的:
所以說,時間戳記是非常重要的!anacron 是透過該記錄與目前的時間差異,了解到是否應該要進行某項任務的工作!舉例來說,如果我的主機在 2009/03/15(星期天) 18:00 關機,然后在 2009/03/16(星期一) 8:00 啟動,由於我的 crontab 是在早上 04:00 左右進行各項任務,由於該時刻系統(tǒng)是關機的,因此時間戳記依舊為 20090315 (舊的時間),但是目前時間已經是 20090316 (新的時間),因此run-parts /etc/cron.daily 就會在啟動過 65 分鐘后開始運行了。
所以羅, anacron 并不需要額外的配置,使用默認值即可!只是我們的 CentOS 只有在啟動時才會運行anacron 就是了。如果要確定 anacron 是否啟動時會主動的運行,你可以下達下列命令:
| [root@www ~]# chkconfig --list anacron anacron 0:off 1:off 2:on 3:on 4:on 5:on 6:off # 詳細的 chkconfig 說明我們會在后續(xù)章節(jié)提到,注意看 3, 5 # 的項目,都是 on !那就是有啟動啦!啟動時才會運行的意思! |
現(xiàn)在你知道為什么隔了一陣子才將 CentOS 啟動,啟動過后約 1 小時左右系統(tǒng)會有一小段時間的忙碌!而且硬盤會跑個不停!那就是因為 anacron 正在運行過去 crontab 未進行的各項工作排程啦!這樣對 anacron 有沒有概念了呢? ^_^
重點回顧
- 系統(tǒng)可以透過 at 這個命令來排程單一工作的任務!『at TIME』為命令下達的方法,當 at 進入排程后,系統(tǒng)運行該排程工作時,會到下達時的目錄進行任務;
- at 的運行必須要有 atd 服務的支持,且 /etc/at.deny 為控制是否能夠運行的使用者帳號;
- 透過 atq, atrm 可以查詢與刪除 at 的工作排程;
- batch 與 at 相同,不過 batch 可在 CPU 工作負載小於 0.8 時才進行后續(xù)的工作排程;
- 系統(tǒng)的循環(huán)例行性工作排程使用 cron 這個服務,同時利用 crontab -e 及 /etc/crontab 進行排程的安排;
- crontab -e 配置項目分為六欄,『分、時、日、月、周、命令』為其配置依據(jù);
- /etc/crontab 配置分為七欄,『分、時、日、月、周、運行者、命令』為其配置依據(jù);
- anacron 配合 /etc/anacrontab 的配置,可以喚醒停機期間系統(tǒng)未進行的 crontab 任務!
本章習題
( 要看答案請將鼠標移動到『答:』底下的空白處,按下左鍵圈選空白處即可察看 ) 簡答題:
- 今天假設我有一個命令程序,名稱為: ping.sh 這個檔名!我想要讓系統(tǒng)每三分鐘運行這個文件一次,但是偏偏這個文件會有很多的信息顯示出來,所以我的root 帳號每天都會收到差不多四百多封的信件,光是收信就差不多快要瘋掉了!那么請問應該怎么配置比較好呢? 這個涉及數(shù)據(jù)流重導向的問題,我們可以將他導入文件或者直接丟棄!如果該信息不重要的話,那么就予以丟棄,如果信息很重要的話,才將他保留下來!假設今天這個命令不重要,所以將他丟棄掉!因此,可以這樣寫: */3 * * * * root /usr/local/ping.sh > /dev/null 2>&1
- 您預計要在 2010 年的 2 月 14 日寄出一封給 kiki ,只有該年才寄出!該如何下達命令? at 1am 2010-02-14
- 下達 crontab -e 之后,如果輸入這一行,代表什么意思?
* 15 * * 1-5 /usr/local/bin/tea_time.sh 在每星期的 1~5 ,下午 3 點的每分鐘,共進行 60 次 /usr/local/bin/tea_time.sh 這個文件。要特別注意的是,每個星期 1~5 的 3 點都會進行 60 次ㄟ!很麻煩吧~是錯誤的寫法啦~應該是要寫成:
30 15 * * 1-5 /usr/local/bin/tea_time.sh - 我用 vi 編輯 /etc/crontab 這個文件,我編輯的那一行是這樣的:
25 00 * * 0 /usr/local/bin/backup.sh
這一行代表的意義是什么? 這一行代表......沒有任何意義!因為語法錯誤!您必須要了解,在 /etc/crontab 當中每一行都必須要有使用者才行!所以,應該要將原本那行改成:
25 00 * * 0 root /usr/local/bin/backup.sh - 請問,您的系統(tǒng)每天、每周、每個月各有進行什么工作? 因為 CentOS 系統(tǒng)默認的例行性命令都放置在 /etc/cron.* 里面,所以,你可以自行去:/etc/cron.daily/, /etc/cron.week/, /etc/cron.monthly/ 這三個目錄內看一看,就知道啦! ^_^
- 每個星期六凌晨三點去系統(tǒng)搜尋一下內有 SUID/SGID 的任何文件!并將結果輸出到 /tmp/uidgid.files vi /etc/crontab
0 3 * * 6 root find / -perm +6000 > /tmp/uidgid.files
2002/05/30:第一次完成
2003/02/10:重新編排與加入 FAQ
2005/09/07:將舊的文章移動到 此處 。
2005/09/07:呼呼!終於完成風格羅~同時加入一些習題練習。
2009/03/12:將舊的文件移動到此處。
2009/03/14:加入 batch 這個項目的說明!與 at 有關!
2009/03/15:加入了 anacron 這玩意的簡單說明!
2009/09/11:稍微修訂一下說明語氣與連結數(shù)據(jù)。
出處:http://vbird.dic.ksu.edu.tw/linux_basic/0430cron.php
總結
以上是生活随笔為你收集整理的鸟哥的Linux私房菜(基础篇)- 第十六章、例行性工作排程 (crontab)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鸟哥的Linux私房菜(基础篇)- 第十
- 下一篇: 鸟哥的Linux私房菜(基础篇)- 第十