在 UNIX 操做系統中,一般都有一個 crond 守護進程來按期執行設定好的計劃任務,它能給服務器管理帶來許多便利,同時能夠大大節省管理員的時間和精力。好比,管理員但願天天凌晨 3:00 對數據庫進行一次備份,有了 crond 的幫助,管理員就沒必要天天在睡得最香的時候起牀了,crond 可以按照配置文件的指引自動完成這個任務。html
在GNU的世界裏,最不缺少的就是選擇,一樣,這個 crond 也有多種不一樣的實現,常見的有:fcron 、dcron 、vixie-cron 三種。本文將介紹其中的 dcron 實現,它的特色就是「簡單、嚴謹、安全」。linux
Dcron 3.2 版本之前是 Dillon 的做品,如今已經交給 Jim Pryor 維護,其主頁是:http://www.jimpryor.net/linux/dcron.html數據庫
Dcron 將全部任務都強制交給 /bin/sh 執行,也就是使用"/bin/sh -c"來運行任務。Dcron 不容許你在配置文件中指定環境變量或使用其它高級特性,這些事情最好放到腳本中去作。安全
Dcron 啓動後首先掃描普通用戶配置目錄,尋找以/etc/passwd中用戶名命名的文件,並將其做爲該用戶的配置文件。而後掃描root用戶配置目錄,並將其下全部文件都做爲root用戶的配置文件[筆者本人建議不要使用root配置目錄,而是在普通用戶配置目錄中放置一個"root"文件,效果徹底相同]。[注意]配置目錄下全部文件名含有句點(.)的文件和沒法匹配用戶名的文件都會被忽略。服務器
Dcron 在運行時會每分鐘檢查一次配置文件目錄中的"cron.update"文件。你能夠將已經被修改或刪除的配置文件的名字(也就是用戶名)添加到"cron.update"文件中(一行一個),這樣就能夠通知 Dcron 配置文件已經發生變化。不過,即便沒有"cron.update"文件,Dcron 也會每小時自動從新掃描一次配置目錄。函數
Dcron 有許多內置的限制以防止其被誤用。其中最重要的是:每一個配置文件最大256行規則。每行規則最長1020字符。post
Dcron 並不使用 Sysklogd 記錄日誌,通常的方法是直接將命令的結果重定向到日誌文件。spa
Dcron 的執行細節:它必須至少運行一個任務。它首先建立兩個進程本身擁有的臨時文件 O_EXCL 和 O_APPEND 存儲全部輸出,而後 fork() 出子進程並將其身份切換到該任務的屬主,而後使用 exec 函數執行"/bin/sh -c"來運行任務,可是 O_EXCL 和 O_APPEND 始終由守護進程全部,以防止被用戶惡意修改。任務完成後 crond 會校驗沒有安全防禦的 mail 文件,若是它被新增了內容,那麼就以任務屬主的身份使用 sendmail 將修改過的 mail 文件發送給其屬主。crond 不會在任務執行期間保持打開文件描述符,由於這樣作可能會致使文件描述符被耗盡。crond 老是在每一分鐘的開始時刻檢查當前是否有事情可作,這種檢查的效率很高,幾乎不消耗任何 CPU 資源。操作系統
若是輪到某一條命令執行的時候,先前啓動的命令還沒有執行結束,那麼將跳過這次執行。好比,若是設定每分鐘執行一次"sleep 70",實際效果將是每兩分鐘執行一次。若是你不喜歡這樣,能夠在命令以後加上"&"轉入後臺執行,這樣就不會受此影響了。.net
Dcron 是一個標準的 ANSI C 程序,理論上可使用任何符合標準的編譯器進行編譯(推薦使用 GCC)。但事實上,源代碼中切換用戶身份的操做是特定於Linux的方式,因此,只建議在Linux上編譯和安裝。
編譯以前你須要詳細閱讀 Makefile 和 defs.h 文件,並根據你的須要進行修改。好比做者本人常常進行這樣的修改:
sed -i -e's|/var/spool/cron/crontabs|/etc/crontabs|' -e's|/etc/cron.d|/share/empty|' defs.h
這個命令的做用是將配置文件的默認目錄位置調整到"/etc/crontabs",並將root用戶配置文件的默認目錄位置調整到"/share/empty"。
而後使用下面的命令進行編譯和安裝:
make CFLAGS="$CFLAGS $LDFLAGS" install -o 0 -g 0 -m 0500 crond /bin/crond chown 0:0 /etc/crontabs /share/empty chmod 1700 /etc/crontabs /share/empty
請注意在安裝時爲 crond 及其配置目錄設置的權限。
crond 一般在系統啓動的時候由 /etc/rc.local 啓動。在啓動腳本中一般使用"-l8"指定日誌等級。因爲 Dcron 並不使用 Sysklogd 記錄日誌,因此通常直接將命令的結果重定向到日誌文件。好比:
/bin/crond -l8 >> /var/log/crond.log 2>&1
語法
crond [-l#] [-d#] [-f] [-b] [-c directory] [-s directory]
選項說明
配置文件的格式與 vixie cron 相似,可是缺乏一些高級特性,好比不容許在配置文件中使用環境變量。
空白行以及以"#"開頭的行將被忽略。
配置文件中的每一行都須要指定5個時間字段+1個命令字段,也就是:
分鐘(0-59) 小時(0-23) 日(1-31) 月(jan-dec) 星期(sun-sat) 命令
每一個字段均可以指定一個範圍(好比:feb-nov),或者逗號分隔的清單(好比:1,5,8,23),或者星號(*)表明所有。
月份和星期除了數字,還可使用字符串縮寫,具體以下:
1-12月:jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec
週日-週六:sun,mon,tue,wed,thu,fri,sat
若是你同時指定了每週中的某一天和每個月中的某一天,那麼二者同時有效,也就是這個任務會在每週的這一天執行,同時也在每個月的這一天執行。
下面是幾個例子:
# 整年每分鐘執行一次 * * * * * /bin/false # 天天上午 6:10 執行一次 10 6 * * * date # 每一年 4月2日 22:25 執行一次 25 22 2 apr * /bin/true # 每週1、周2、週三 上午 2:00 6:00 11:00 22:00 # 或者 每個月4號 上午 2:00 6:00 11:00 22:00 執行一次 0 2,6,11,22 4 * mon-wed date >>/var/log/messages 2>&1
命令部分將使用
/bin/sh -c 命令
方式執行。
一般將命令的結果重定向到一個日誌文件,不然默認將輸出到 stdout 或 stderr ,而且同時使用sendmail發送到任務的屬主。若是你但願爲某些特別的用戶(好比 UUCP)利用這個sendmail機制,最好爲這個用戶設置一個別名以將郵件重定向到 root 或 postmaster 之類的用戶。