Linux 基礎學習篇 - Mandrake 9

第十五章、例行性命令的建立 - for Mandrake 9

鳥哥的第一本書籍的主要內容,內容稍微與書籍不太一樣了!

最近更新時間: 2002/05/30

鳥哥的第一本書大約是在 2002 年的年底左右出版的,內容幾乎都是 Linux 基礎學習,一點也沒有談到伺服器的部份!這也是後來的雛型! 不過內容錯誤的地方很多,導致在 2003 年的年底推出了『基礎學習篇增訂版』的內容,大致上就是處理掉一些比較有嚴重錯誤的部份。 不過,因為 Linux 的版本變化非常快速,因此,寫完了這些文件之後,鳥哥還是持續在網站上更新文件內容,導致原本書籍內容的資料與網站資料差異太大! 這個問題直到鳥哥在 2008 年左右才發現!糟糕了!舊版的文件資料已經遺失~覺得相當扼腕~

因此,在底下的文件內容與當初的書籍內容雖然大同小異,不過章節的編排卻是有所不同!再花時間去一個一個處理,似乎也不太符合成本效益! 鳥哥僅是想要將自己以前的文件記錄下來而已,同時將過時的 big5 編碼改回 utf8 編碼,再加上可以支援 RWD 的樣式而已啦! 內容已經不多做編排~因此,如果內容文件你看不懂,那也是應該的! ^_^

建議您前往本站查詢最新版本的 Linux distribution 文章來閱讀,比較不會浪費時間。最新文章請前往鳥站首頁查閱囉!

什麼是例行性命令?

每個人或多或少都有一些約會或者是工作,有的工作是例行性的,例如每年一次的加薪、每個月一次的工作報告、每週一次的午餐會報、每天需要的打卡等等;有的工作則是臨時發生的,例如剛好總公司有高官來訪,需要你準備演講器材等等!用在生活上面,例如每年的愛人的生日、每天的起床時間等等、還有突發性的電腦大降價(阿~我等好久了~~)等等囉。這些工作都可以稱為例行性命令,而這些工作 Linux 也都可以幫您提醒,例如:每一天早上 8:00 鐘要伺服器連接上音響,並啟動音樂來喚你起床;而中午 12:00 希望 Linux 可以發一封信到你的郵件信箱,提醒你可以去吃午餐了;另外,在每年的你愛人的生日的前一天,先發封信提醒你,以免忘記這麼重要的一天。
從上面的說明當中可以很清楚的發現兩種工作排程的方式:
  • 一種是例行性的,就是每隔一定的週期要來辦的事項;
  • 一種是突發性的,就是這次做完以後就沒有的那一種(電腦大降價....)
那麼在 Linux 底下如何達到這兩個功能呢?呵呵!那就得使用 at 與 crontab 這兩個好東西囉!
  • at : 這個工作僅執行一次就從 Linux 系統中的排程中取消;
  • crontab : 這個工作將持續例行性的作下去!
底下我們先來談一談 Linux 的系統到底在做什麼事情,怎麼有若干多的工作排程在工作呢?然後再回來談一談 at 與 crontab 這兩個好東西!

Linux 系統的例行性命令有哪些

好了,那麼伺服器自己有什麼例行性命令要來作呀!?Linux 的工作可多著呢!由前面提到的幾篇文章中,我們知道Linux 本身在背景下的工作可是很多的,尤其是網路開放的情況下,建立與取消連線、MySQL 資料庫的即時更新、以及一些例行的系統指令,例如釋放記憶體的工作等等。由於例行的工作非常的多,實在不可能每天都要管理員來手動輸入吧!所以才會建立這個工作排程的需求的!基本預設的工作有底下這些:
  • 進行資料輪替 ( log rotate ):這個步驟重要了!尤其是在 log file 的選項當中!由於登錄檔案會越來越大,所以需要適時適量的將登錄檔備份,並以新開的檔案來進行記錄,這樣效率會比較好,因此就需要使用 log rotate 啦!系統預設的重要工作之一;
  • rpm 資料庫的建立:雖然 RPM 資料庫會在你以 RPM 安裝之後即更新到 RPM 資料庫當中去,但是難保會有漏網之魚,所以系統也會設定每隔依段時間自動的蒐集系統上面的 RPM 資料庫來建置一番;
  • 建立 locate 的資料庫:是否還記得為何使用 locate 這個指令時,搜尋速度超快!那是因為 Linux 系統上將檔案與路徑都記錄在資料庫裡面了!所以使用 locate 的時候,嘿嘿!直接指向資料庫去 ( /var/lib/slocate/slocate.db ) ,偏偏麻煩的是這個檔案的更新是每天一次!所以當你今天更新的檔案,使用 locate 反而可能會找不到....
  • 進行程序的分析:每隔依段時間會進行程序的分析,如果發現有僵屍程序的時候,就會將他刪去!以保持記憶體的工作能力!
  • 登錄檔視察:這個東西是在 Red Hat 7.1 以後才出現的東西,後來太好用了,所以被拿到舊版的 Red Hat 裡面去使用!基本上就是分析登錄檔啦!然後據以解析有問題的紀錄檔,以維護主機的安全性!這部份不才小弟也自己寫了一個簡易型的分析檔案,覺得更好用就是了!
  • 指紋資料庫的比對:基本上就是 tripwire 這個套件啦!可以用來分析最近被更動過的檔案內容!蠻不錯的一個程式!有空也來玩玩看。
Linux 預設的例行工作至少就有這些了,再加上您努力的為 Linux 進行工作排程的設計,嘿嘿!每天的工作量可是相當的大的呢!

僅執行一次的工作排程

如果僅要執行一次的工作,就使用 at 這個指令吧!這個指令其實就是 atd 這個服務啦!所以請記得一定要啟動這個服務呦!如果是在 Red Hat 系統下,可以使用:
  1. ntsysv
  2. 選擇 atd
  3. 按下 OK !
如果是在 Mandrake 系統下,可以使用:
  1. chkconfig --add atd
  2. chkconfig --list

  3. 上面這個指令可以查看 atd 在 run-level 正確的情況中,是否會在開機的時候被啟動!
基本上, atd 是預設開啟的,如果您沒有更動過系統預設值的話,那麼上面的動作就不需要動囉!下達 at 這個動作會將工作排程寫入 /var/spool/at 這個目錄下呢!然後等待系統將之執行囉!此外,這個 at 指令雖然預設是所有人都能進行,但是可以經由 root 的規範來限制使用的人口。限制的方法其實與 /etc/hosts.allow(deny) 類似,使用 /etc/at.allow(deny) 這兩個檔案來限制:
  • 限制使用者原理:當使用者執行 at 時,系統會

  •  
    1. 先找尋 /etc/at.allow 這個檔案,寫在這個檔案中的使用者才能使用 at ,沒有在這個檔案中的使用者則不能使用 at ( 即使沒有寫在 at.deny 當中  );
    2. 如果沒有 /etc/at.allow 就尋找 /etc/at.deny 這個檔案,若寫在這個 at.deny 的使用者則不能使用 at ,而沒有在這個 at.deny 檔案中的使用者,就可以使用 at 咯;
    3. 如果兩個檔案都不存在,那麼只有 root 可以使用 at 這個指令。
  • Linux 預設情況下,只有 /etc/at.deny 這個檔案,且這個檔案的內容為空白的,由於內容沒有任何使用者,所以當然『所有人都可以使用 at 』
  • 如果不想要某個使用者使用 at 時,那麼將該使用者帳號寫到 /etc/at.deny 這個檔案中即可。
好了!我們來談一談 at 的語法吧!
 
[test @test test]# at [-m] TIME    (下達工作指令)
[test @test test]# atq         (查看目前的工作排程)
[test @test test]# atrm [jobnumber]  (刪除排程)
參數說明:
-m    :執行 at 所規範的工作排程時,將螢幕輸出結果 mail 給下達指令的使用者
TIME  :時間的格式,有底下幾個:
   HH:MM YYYY-MM-DD             ex> 04:00 2002-05-30 (五月三十號四點執行)
   HH[pm;am] + number [hours;days;weeks]  ex> 4pm + 3 days (在過 3 天的下午 4 點)
   HH:MM                  ex> 12:00 (今天的 12 點執行)
   HH[pm;am] [Month] [Day]         ex> 1pm May 30
jobnumber:每一個 at 工作排程都有編排的順序!這個即是!
範例:

[test @test test]# at 5pm   <==在今天的 5pm 執行,如果今天已過 5 點則明天執行;
warning: commands will be executed using (in order) a) $SHELL b) login shell c) /bin/sh
at> mail -s test test < /home/test/.bashrc <==這就是我的工作!
at> <EOT> <==這裡是按下 [Ctrl] + D 就可以離開了!
job 8 at 2002-05-30 17:00  <==這裡會告訴你這個工作的號碼為 8 號,執行的日期為後面所示。

[test @test test]# atq   <==窺視一下你(test)目前有多少工作?
5       2002-05-30 12:00 a test
8       2002-05-30 17:00 a rest

[test @test test]# atrm 5<==刪除第 5 號工作
[test @test test]# atq
8       2002-05-30 17:00 a rest

請注意!在 at 下達之後,便進入指令列下達的模式!在這裡你可以重複的輸入指令,但是離開的時候請下達『 [Ctrl] + D 』就可以離開了!離開之後,系統會告訴你這個工作排程的號碼與使用者是誰!呵呵!很簡單吧!

循環執行的例行性命令

這個循環的例行性命令其實就是 cron 這個服務啦 (crond)!當你下達 crontab 的指令之後,會將你的命令寫入 /var/spool/cron這個目錄當中呦!例如 test 下達了他的 crontab 命令,那麼就會自動產生 /var/spool/cron/test 這個檔案!『但請注意,這個檔案不能直接編輯!』然後執行的指令記錄會放置在 /var/log/cron 這個檔案中!所以,『如果您的 Linux 系統不知道是否被木馬入侵時,可以搜尋一下 /var/log/cron 這個記錄擋,視察看看有沒有被搞鬼?』
好了!我們來看一下 crontab 的指令語法吧!
 
[test @test test]# crontab [-u user] [-l | -e | -r]
參數說明:
-u user :只有 root 能下達的參數,視察或編譯其他使用者的 crontab 內容
-l      :列出 crontab 的內容
-e      :編輯 crontab 的內容
-r      :刪除 crontab 的內容
範例:
一般使用者 test 要在每天的 12:00 發信給自己:

[test @test test]# crontab -e <==自己編輯自己的 crontab 內容

進入 crontab 編輯內容,使用 vi 呦!

0 12 * * * mail test < /home/test/test.txt
分時日月週 |========指令列===============|

上面的例子是說:假如你需要在每天的正午 12:00 發一封信給你自己,而且信的內容已經寫好了,那要怎樣作呢?而且,另一個假設是,你在 Linux Server 中的權限僅止於一般使用者,並不是 root (管理員)身份,那要怎樣設定你的例行性命令呢?哈哈!那就使用 crontab 這個指令吧!你只要執行『 crontab -e 』就可以進入 vi 的編輯畫面來編輯你的例行性命令說!

在上面的例子中,輸入 crontab -e 時,會出現一個 vi 畫面,然後你在 vi 畫面中輸入上面的一行字,之後按 :wq 儲存後離開!即可完成編輯!容易吧!那上面那一行字代表什麼意義呢?你可以看到,在真正執行命令之前(就是 mail test < /home/test/test.txt )總共有五個數字,這五個數字分別代表:
分  (0-59)
小時 (0-23)
日期 (1-31)
月份 (1-12)
週  (0-6)
數字代表的意義
分鐘
小時
日期
月份
範圍
0-59
0-23
1-31
1-12
0-6 (0為星期天)
另外,如果是『 *  』的時候,代表所有數字都適用的意思。所以,你就可以知道我上面那一行寫的意義為何了!那就是『不論何月、何日、星期幾的 12 點 0 分時,執行 mail test < /home/test/test.txt 這個命令』!還不瞭解?沒關係,我們這裡作幾個例子!
 
例題一:假如你的女朋友生日是 5 月 2 日,你想要在 5 月 1 日的 23:59 發一封信給他,
    這封信的內容已經寫在 /home/test/lover.txt 中了

[test @test test]# crontab -e

59 23 1 5 * mail pigpp < /home/test/lover.txt

那樣的話,每年 pigpp 都會收到你的這封信喔!(當然囉,信的內容就要每年變一變啦!)
 
例題二:假如你每隔五分鐘要去 check 你的一個名為 test.sh 的批次檔一次,則:

[test @test test]# crontab -e

59 23 1 5 * mail pigpp < /home/test/lover.txt  <==剛剛的那個指令還存在呦!
*/5 * * * * /home/test/test.sh  <==新加入的一個排程!

注意到呦!那個 crontab 每個人都只有一個檔案,就是在 /var/spool/cron 裡面的檔案啦!還有兩件事要注意一下:
(1) 指令的路徑最好是下達絕對路徑,這樣比較不會找不到執行的檔案喔;
(2) 第一個數字 */5 表示『每五分鐘執行一次』的意思!
例題三:假如你每個禮拜的星期五下午 4:30 要告訴朋友星期六的約會不要忘記,則:

[test @test test]# crontab -e

59 23 1 5 * mail pigpp < /home/test/lover.txt 
*/5 * * * * /home/test/test.sh
30 16 * * 5 mail frend@test.domain.name < /home/test/frend.txt <==新加入的!

呵呵!這樣很簡單吧!如此就可以輕易的達到您所需要的例行性工作排程的安排囉!
好了!那麼我們要如何來查看使用者目前的 crontab 的工作排程呢?
 
[test @test test]# crontab -l <==這個 -l 是 L 的小寫
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.27683 installed on Thu May 30 13:38:38 2002)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
59 23 1 5 * mail pigpp < /home/test/lover.txt
*/5 * * * * /home/test/test.sh
30 16 * * 5 mail frend@test.domain.name < /home/test/frend.txt
呵呵呵!其實這個顯示的內容就是 /var/spool/cron/test 檔案的內容啦!那麼如何刪除排程呢?
 
[test @test test]# crontab -r
[test @test test]# crontab -l
no crontab for test
看到了嗎? crontab 『整個內容都不見了!』所以請注意:『如果只是要刪除某個 crontab 的工作項目,那麼請使用 crontab -e 來重新編輯即可!』如果使用 -r 的參數,是會將所有的 crontab 資料內容都刪掉的!千萬注意了!

系統的 crontab 設定

這個『 crontab -e 』是針對使用者的 cron 來設計的,如果是『系統的例行性任務』時,該怎麼辦呢?是否還是需要以 crontab -e 來管理你的例行性命令呢?當然不需要,你只要編輯 /etc/crontab這個檔案就可以啦!有一點需要特別注意喔!那就是 crontab -e 這個 crontab 其實是 /usr/bin/crontab 這個執行檔,但是 /etc/crontab 可是一個『純文字檔』喔!你可以 root 的身份編輯一下這個檔案哩!
基本上, cron 這個服務的最低偵測限制是『分鐘』,所以『 cron 會每分鐘去讀取一次 /etc/crontab 與 /var/spool/cron 裡面的資料內容』,因此,只要你編輯完 /etc/crontab 這個檔案,並且將他儲存之後,呵呵!那麼 crontab 的設定就自動的會來執行了!
注意:在 Linux 底下的 crontab 會自動的幫我們每分鐘重新讀取一次 /etc/crontab 的例行工作事項,但是某些原因或者是其他的 Unix 系統中,由於 crontab 是讀到記憶體當中的,所以在你修改完 /etc/crontab 之後,可能並不會馬上執行,這個時候請重新啟動 crond 這個服務吧!
/etc/rc.d/init.d/crond restart
好了,我們來看看 /etc/crontab 這的檔案的內容吧:
 
[root@test /root]# vi /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  <==每個月執行的工作
分 時日月週 使用者    參數     指令

看到這個檔案的內容你大概就瞭解了吧!呵呵,沒錯!這個檔案與將剛剛我們下達 crontab -e 的內容幾乎完全一模一樣!只是有幾個地方不太相同:
    • MAILTO=root:是說,當 /etc/crontab 這個檔案中的例行性命令發生錯誤時,會將錯誤訊息或者是螢幕顯示的訊息傳給誰?由於 root 並無法在用戶端中收信,因此,我通常都將這個 e-mail 改成自己的帳號,好讓我隨時瞭解系統的狀況!
    • 01 * * * * root run-parts /etc/cron.hourly:在註解符號 #run-parts 這一行以後的命令,我們可以發現,五個數字後面接的是 root 喔!沒錯,這一行代表的是『執行的層級為 root 身份』當然囉,你也可以將這一行改寫成其他的身份哩!而 run-parts 代表後面接的 /etc/cron.hourly 是『一個目錄內(/etc/cron.hourly)的所有可執行檔』,這也就是說,個小時的 01 分,系統會以 root 層級的使用者去 /etc/cron.hourly 這個目錄下執行所有可以執行的檔案!後面的三行也都是類似的意思!你可以到 /etc/ 底下去看看,系統本來就預設了這四個目錄了!你可以將每天需要執行的命令直接寫到 /etc/cron.daily 即可,還不需要使用到 crontab -e 的程式呢!方便吧!
        注意:基本上 /etc/crontab 裡頭支援兩種下達指令的方式,一種是直接以 指令型態 下達,一種則是以『目錄規劃』來下達;
        • 指令型態

        • 01 * * * * test mail -s test test < /home/test/test.txt
          使用者是 test, 且在每個小時執行一次指令 mail ...
        • 目錄規劃

        • */5 * * * * root run-parts /root/runcron
          建立一個 /root/runcron 的目錄,將要每隔五分鐘執行的『可執行檔』都寫到該目錄下,就可以讓系統每五分鐘執行一次該目錄下的所有可執行檔。
    這樣就可以曉得 run-parts 的用意了吧!此外,與 crontab -e 規劃當中最不相同的就是多了一個『使用者層級』的概念,通常我們都是以 root 的角度來規劃例行性命令,但是總有不需要 root 的指令吧!就可以使用這個層級來規範該程序的使用者屬於誰囉!
    好!你現在大概瞭解了這一個咚咚吧!OK!假設你現在要作一個目錄,讓系統可以每 2 分鐘去執行這個目錄下的所有可以執行的檔案,你可以寫下如下的這一行在 /etc/crontab 中:
      */2 * * * * root run-parts /etc/cron.min
    當然囉, /etc/cron.min 這個目錄是需要存在的喔!那如果我需要執行的是一個『程式』而已,不需要用到一個目錄呢?該如何是好?例如在偵測網路流量時,我們希望每五分鐘偵測分析一次,可以這樣寫:
      */5 * * * * root /usr/local/mrtg-2/bin/mrtg /usr/local/apache/htdocs/mrtg/net/mrtg.cfg
    沒有了 run-parts 就是代表『一個檔案』的意思啦!
    如何!?建立例行性命令很簡單吧!如果你是系統管理員的話,直接修改 /etc/crontab 這個檔案即可喔!又便利,又方便管理呢!

安全的防護

  • 資源分配不均

  • 當大量使用 crontab 的時候,總是會有問題發生的,最嚴重的問題就是『系統資源分配不均』的問題,以我的系統為例, VBird 有偵測流量的資訊,包括:
    • 流量
    • 區域內其他 PC 的流量偵測
    • CPU 使用率
    • RAM 使用率
    • 線上人數即時偵測
    如果每個流程都在同一個時間啟動的話,呵呵!那麼在某個時段時,我的系統會變的相當的繁忙,所以,這個時候就必須要分別設定啦!我可以這樣做:
     
    [root@test /root]# vi /etc/crontab
    1,6,11,16,21,26,31,36,41,46,51,56 * * * * root ........  <==那個 .. 代表你的指令
    2,7,12,17,22,27,32,37,42,47,52,57 * * * * root ........
    3,8,13,18,23,28,33,38,43,48,53,58 * * * * root ........
    4,9,14,19,24,29,34,39,44,49,54,59 * * * * root ........
    看到了沒?那個『 , 』分隔的時候,請注意,不要有空白字元!(連續的意思)如此一來,則可以將每五分鐘工作的流程分別在不同的時刻來工作!則可以讓系統的執行較為順暢呦!
  • 取消不要的輸出項目

  • 另外一個困擾發生在『當有執行成果或者是執行的項目中有輸出的資料時,該資料將會 mail 給 MAILTO 設定的帳號』,好啦,那麼當有一個排程一直出錯(例如 DNS 的偵測系統當中,若 DNS 上層主機掛掉,那麼你就會一直收到錯誤訊息!)怎麼辦?呵呵!還記得 BASH 與 Shell scripts 那一章吧!?直接以『命令重導向』將輸出的結果輸出到 /dev/null 這個垃圾桶當中就好了!
  • 安全的檢驗

  • 很多時候被植入木馬都是以例行命令的方式植入的,所以可以藉由檢查 /var/log/cron 的內容來視察是否有『非您設定的 cron 被執行了?』這個時候就需要小心一點囉!

本章習題練習 ( 要看答案請將滑鼠移動到『答:』底下的空白處,按下左鍵圈選空白處即可察看)

  • 今天假設我有一個指令程式,名稱為: ping.sh 這個檔名!我想要讓系統每三分鐘執行這個檔案一次,但是偏偏這個檔案會有很多的訊息顯示出來,所以我的 root 帳號每天都會收到差不多四百多封的信件,光是收信就差不多快要瘋掉了!那麼請問應該怎麼設定比較好呢?

  • 答:
      這個涉及命令重導向的問題,我們可以將他導入檔案或者直接丟棄!如果該訊息不重要的話,那麼就予以丟棄,如果訊息很重要的話,才將他保留下來!假設今天這個命令不重要,所以將他丟棄掉!因此,可以這樣寫:
      */5 * * * * root /usr/local/ping.sh > /dev/null 2>&1
修改歷史:
  • 2002/05/30:第一次完成
  • 2003/02/10:重新編排與加入 FAQ
伺服器篇文件
各版本彙整說明
CentOS 6.x