<a href="#_Toc3520%20">目錄 1</a>
<a href="#_Toc22033%20">1. 研究目的 1</a>
<a href="#_Toc6134%20">2. 基本概念 1</a>
<a href="#_Toc18347%20">3. crontab 1</a>
<a href="#_Toc18059%20">3.1. 編輯 2</a>
<a href="#_Toc5471%20">3.1.1. “crontab -e”工作流 2</a>
<a href="#_Toc9783%20">3.2. 問題 3</a>
<a href="#_Toc7333%20">4. crond 3</a>
<a href="#_Toc7082%20">4.1. /etc/crontab 3</a>
更好使用crontab,和解決crontab使用問題。本文分析的是Paul Vixie版本crontab和crond。一般可通過執行“man crontab”檢視AUTHOR是不是“Paul Vixie”。
1) crond是一個背景守護程式,定時執行由它負責;
2) crontab是crond的指令行工具,通過它來增删改定時任務,不同使用者的crontab是獨立分開的。
crontab啟動後,會首先切換目前目錄,目前目錄由宏CRONDIR定義(pathnames.h中):
#ifndef CRONDIR
/* CRONDIR is where cron(8) and crontab(1) both chdir
* to; SPOOL_DIR, CRON_ALLOW, CRON_DENY, and LOG_FILE
* are all relative to this directory.
*/
#define CRONDIR "/var/cron"
#endif
老版本一般為/var/cron,新版本目錄為:/var/spool。
接下來會檢查使用者是否有權限執行crontab,比如使用者名密碼過期了則不能執行。檢查通過後根據指令行參數分成4個命名分别執行:
1) list_cmd:對應于crontab -l;
2) delete_cmd:對應于crontab -r;
3) edit_cmd:對應于crontab -e
4) replace_cmd:對應于crontab filepath。
crontab預設使用宏_PATH_VI指定的程式設計器,檔案/usr/include/paths.h定義了_PATH_VI:
#define _PATH_VI "/usr/bin/vi"
但如果系統沒有檔案/usr/include/paths.h或沒有定義_PATH_VI,則為/usr/ucb/vi:
#if defined(_PATH_VI)
# define EDITOR _PATH_VI
#else
# define EDITOR "/usr/ucb/vi"
除此外,crontab還支援從環境變量VISUAL和EDITOR讀取采用哪個編輯器,其中先讀取VISUAL,如果沒有指定再讀取EDITOR。
“crontab -e”的完整工作流如下:
以使用者root為例:
1) 切換目前目錄為“/var/cron”;
2) 拼寫檔案名“tabs/username”,假設使用者名為root,則為“tabs/root(新版本檔案為:cron/root)”,完整的路徑為:/var/cron/tabs/root。檔案tabs/root的内容和指令“crontab -l”的輸出相同;
3) 打開檔案/var/cron/tabs/root,然後取得檔案的通路時間和修改時間。如果檔案不存在,則讀取/dev/null的通路時間和修改時間;
4) 生成格式為“crontab.XXXXXXXXXX”的臨時檔案,比如:crontab.b2gvnE;
5) 修改臨時檔案的owner;
6) 将檔案tabs/root的内容逐字元複制到臨時檔案中;
7) 取得編輯用的編輯器,預設為“/usr/bin/vi”;
8) fork一個子程序;
9) 通過execlp執行/usr/bin/vi;
10) 等待vi程序退出;
11) 如果vi正常退出,檢查修改時間,如果有變化,則執行replace_cmd;
12) replace_cmd過程上,會加上頭:
/* write a signature at the top of the file.
*
* VERY IMPORTANT: make sure NHEADER_LINES agrees with this code.
fprintf(tmp, "# DO NOT EDIT THIS FILE - edit the master and reinstall.\n");
fprintf(tmp, "# (%s installed on %-24.24s)\n", Filename, ctime(&now));
fprintf(tmp, "# (Cron version %s -- %s)\n", CRON_VERSION, rcsid);
13) replace_cmd會建立一個新的位于目前目錄(比如/var/cron或/var/spool)下的臨時檔案;
14) 然後複制原來的臨時檔案内容到瓣的臨時檔案中,并檢查文法;
15) 完成再調用rename将臨時檔案名改為第2步取得的正式檔案名;
16) 更新檔案的通路時間和修改時間。
1) “crontab -e”未退出前的修改但已儲存是否生效?
2) crontab中定義的環境變量,注釋是否可以在同一行,如:
STARTDATE=2017-12-18 # 開始日期
老版本的crond,修改改需要重新開機程序才會生效,新版本crond通過inotify監控檔案變化,修改後不用重新開機即會生效。
系統crontab檔案,在加載使用者crontab前會先加載/etc/crontab,而且/etc/crontab總是屬性root使用者。