摘自:http://www.ibm.com/developerworks/cn/linux/l-job-scheduling.html
Linux® 和 UNIX® 系統允許調度任務在以後執行一次,或者重複運行。本文是從 developerWorks 教程 “LPI 102 考試準備:管理任務” 摘錄的,講解如何調度作業定期運行,或在指定的時間運行一次。
在 Linux 系統上,許多管理任務必須頻繁地定期執行。這些任務包括輪轉日誌文件以避免裝滿文件系統、備份數據和連接時間服務器來執行系統時間同步。上面提到的教程更詳細地介紹了這些管理任務。在本文中,學習 Linux 中提供的調度機制,包括 cron
和 anacron
設施以及 crontab
和 at
命令。即使系統常常關機,anacron
也可以幫助調度作業。
以一定的時間間隔運行作業需要使用 cron 設施進行管理,它由 crond
守護進程和一組表(描述執行哪些操作和採用什麼樣的頻率)組成。這個守護進程每分鐘喚醒一次,並通過檢查 crontab 判斷需要做什麼。用戶使用 crontab
命令管理 crontab。crond
守護進程常常是在系統啓動時由 init 進程啓動的。
爲了簡單,假設希望定期運行清單 1 所示的命令。這個命令實際上只報告日期和時間,其他什麼事都不做,但是它可以說明如何使用 crontab
設置 cron 作業,而且還可以通過輸出看到作業運行的時間。設置 crontab 條目需要一個包含轉義的 shell 元字符的字符串,所以適合於簡單的命令和參數。在這個示例中,將從腳本 /home/ian/mycrontab.sh 運行 echo
命令,這個腳本不需要參數。 這可以減少處理轉義字符的工作。
清單 1. 一個簡單的命令示例
[ian@lyrebird ~]$ cat mycrontest.sh #!/bin/bash echo "It is now $(date +%T) on $(date +%A)" [ian@lyrebird ~]$ ./mycrontest.sh It is now 18:37:42 on Friday |
使用 crontab
命令和 -e
(表示 “edit”)選項創建 crontab。這會打開 vi
編輯器,除非在 EDITOR 或 VISUAL 環境變量中指定了另一種編輯器。
每個 crontab 條目包含六個字段:
- 分鐘
- 小時
- 日
- 月
- 星期
- 由
sh
執行的字符串
分鐘和小時的範圍分別是 0-59 和 0-12,日和月的範圍分別是 1-31 和 1-12。星期的範圍是 0-6,0 表示星期日。星期也可以指定爲 sun、mon、tue 等等。第 6 個字段包含前 5 個字段之後的所有內容,它是要傳遞給 sh
的字符串。百分號(%)將轉換爲空行,所以如果要使用 % 或其他任何特殊字符,就要在前面加上反斜線(\)。第一個 % 之前的一行傳遞給 shell,這個 % 之後的所有行都作爲標準輸入傳遞。
各個與時間相關的字段可以指定一個單獨的值、值的範圍(比如 0-10 或 sun-wed)或者以逗號分隔的單獨值和範圍列表。清單 2 給出一個 crontab 條目示例。
清單 2. 一個簡單的 crontab 示例
0,20,40 22-23 * 7 fri-sat /home/ian/mycrontest.sh |
在這個示例中,我們的命令在 7 月的每個星期五和星期六晚上 10 點到午夜之間的第 0、20、40 分鐘(每 20 分鐘)執行。關於指定時間的其他方式的細節,參見 crontab(5) 的手冊頁。
您可能想知道對來自命令的輸出會如何處理。爲使用 cron 而設計的大多數命令會使用 syslog 在日誌中記錄輸出(參見教程 “LPI 102 考試準備:管理任務” 中的討論)。但是,定向到 stdout 的輸出會通過電子郵件發送給用戶。清單 3 給出我們的命令示例可能產生的輸出。
清單 3. 通過電子郵件發送的 cron 輸出
From [email protected] Fri Jul 6 23:00:02 2007 Date: Fri, 6 Jul 2007 23:00:01 -0400 From: [email protected] (Cron Daemon) To: [email protected] Subject: Cron <ian@lyrebird> /home/ian/mycrontest.sh Content-Type: text/plain; charset=UTF-8 Auto-Submitted: auto-generated X-Cron-Env: <SHELL=/bin/sh> X-Cron-Env: <HOME=/home/ian> X-Cron-Env: <PATH=/usr/bin:/bin> X-Cron-Env: <LOGNAME=ian> X-Cron-Env: <USER=ian> It is now 23:00:01 on Friday |
用 crontab
命令創建的 crontab 存儲在 /etc/spool/cron 下面的一個子目錄中,這個子目錄與創建 crontab 的用戶同名,所以上面的 crontab 存儲在 /etc/spool/cron/ian 中。因此,與 passwd
命令一樣,crontab
命令是一個用根權限運行的 suid 程序。
除了 /var/spool/cron 中的用戶 crontab 文件之外,cron
還會檢查 /etc/crontab 文件和 /etc/cron.d 目錄中的文件。在這些系統 crontab 中,在第五個時間字段(星期)和命令之間增加了一個字段。這個字段指定哪個用戶應該運行這個命令,一般情況下是根用戶。清單 4 給出一個 /etc/crontab 文件示例。
清單 4. /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 |
在這個示例中,真正的工作由 run-parts
命令執行,它運行 /etc/cron.hourly、/etc/cron.daily 等目錄中的腳本;/etc/crontab 僅僅控制執行作業的時間。注意,這裏的所有命令都作爲根用戶運行。還要注意,crontab 可以包含 shell 變量賦值,這些賦值會在運行命令之前執行。
cron 適合那些連續運行的系統。對於那些常常不開機的系統,比如筆記本計算機,可以使用另一個實用程序 anacron(表示 “anachronistic cron”)調度每日、每週或每月執行的作業。anacron 不處理每小時執行的作業。
anacron 在 /var/spool/anacron 中保留時間戳文件,記錄作業運行的時間。當 anacron 運行時,它檢查自作業上一次運行以來是否已經經過了所需的天數,如果需要,就運行作業。anacron 的作業表存儲在 /etc/anacrontab 中,文件格式與 /etc/crontab 略有不同。與 /etc/crontab 一樣,/etc/anacrontab 可以包含環境設置。每個作業有四個字段:
- 週期
- 延遲
- 作業標識符
- 命令
週期是天數,但是可以指定爲 @monthly,這確保作業每個月只運行一次(無論這個月中有多少天)。延遲是在作業符合運行條件之後,到實際啓動它之前等待的分鐘數。可以使用這個設置防止在系統啓動時集中執行作業。作業標識符可以包含除了斜線(/)之外的所有非空白字符。
/etc/crontab 和 /etc/anacrontab 都通過直接編輯進行更新。不使用 crontab
命令更新這些文件或 /etc/cron.d 目錄中的文件。
有時候,需要只運行作業一次而不是定期運行。爲此,應該使用 at
命令。要運行的命令是從 -f
選項指定的文件讀取的,如果沒有使用 -f
,那麼從 stdin 讀取。-m
選項向用戶發送郵件,即使命令沒有 stdout。-v
選項顯示運行作業的時間。這個時間也顯示在輸出中。
清單 5 給出一個運行 mycrontest.sh
腳本的示例。清單 6 顯示在運行作業之後通過郵件發送給用戶的輸出。注意,這裏的輸出比對應的 cron 作業輸出要簡單一些。
清單 5. 使用 at 命令
[ian@lyrebird ~]$ at -f mycrontest.sh -v 10:25 Sat Jul 7 10:25:00 2007 job 5 at Sat Jul 7 10:25:00 2007 |
清單 6. 來自 at 的作業輸出
From [email protected] Sat Jul 7 10:25:00 2007 Date: Sat, 7 Jul 2007 10:25:00 -0400 From: Ian Shields <[email protected]> Subject: Output from your job 5 To: [email protected] It is now 10:25:00 on Saturday |
時間的設置可以非常複雜。清單 7 給出幾個示例。參見 at
的手冊頁、/usr/share/doc/at/timespec 文件或 /usr/share/doc/at-3.1.10/timespec 這樣的文件(這個示例中的 3.1.10 是 at
包的版本號)。
清單 7. at 命令使用的時間值
[ian@lyrebird ~]$ at -f mycrontest.sh 10pm tomorrow job 14 at Sun Jul 8 22:00:00 2007 [ian@lyrebird ~]$ at -f mycrontest.sh 2:00 tuesday job 15 at Tue Jul 10 02:00:00 2007 [ian@lyrebird ~]$ at -f mycrontest.sh 2:00 july 11 job 16 at Wed Jul 11 02:00:00 2007 [ian@lyrebird ~]$ at -f mycrontest.sh 2:00 next week job 17 at Sat Jul 14 02:00:00 2007 |
at
命令還有一個 -q
選項。隨着隊列的增長,作業的 nice
值也會增長。 還有一個 batch
命令,它與 at
命令相似,但是作業只在系統負載足夠低時運行。這些特性的細節參見手冊頁。