天天看點

crontab和crond分析 目錄 1. 研究目的 2. 基本概念 3. crontab 3.1. 編輯 3.1.1. “crontab -e”工作流 3.2. 問題 4. crond 4.1. /etc/crontab

<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(&amp;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使用者。