在 linux 中,可以使用 crontab 命令指定周期執(zhí)行的定時任務(wù),也就是周期性在指定的時間點執(zhí)行某個任務(wù),而不是執(zhí)行一次之后就不再執(zhí)行。
這個 crontab 命令用于設(shè)置在指定時間點要進(jìn)行的具體操作,通過特定格式的信息來進(jìn)行指定,這些信息會被寫入一個 crontab 文件。
這些定時任務(wù)由 cron 守護(hù)進(jìn)程來執(zhí)行,該進(jìn)程一直運行在后臺,會定時檢查 crontab 文件來判斷需要做什么,如果某個任務(wù)需要被執(zhí)行,就會執(zhí)行該任務(wù)指定的操作。
一般來說,系統(tǒng)啟動時,init 進(jìn)程會啟動 cron 進(jìn)程。
可以使用 man crontab 來查看 crontab 命令的幫助信息。
使用 man 5 crontab 來查看 ctontab 文件的格式,需要基于特定格式來設(shè)置定時任務(wù)。
使用 man 8 cron 命令查看 cron 守護(hù)進(jìn)程的幫助信息。
編輯定時任務(wù)
在 crontab 命令中,可以使用 -e 選項來指定編輯定時任務(wù)。
查看 man crontab 對 -e 選項的說明如下:
The -e option is used to edit the current crontab using the editor specified by the VISUAL or EDITOR environment variables. After you exit from the editor, the modified crontab will be installed automatically. If neither of the environment variables is defined, then the default editor /usr/bin/editor is used.
即,crontab -e 命令編輯當(dāng)前用戶的 crontab 文件,在該文件中按照特定格式添加定時任務(wù),優(yōu)先使用 VISUAL、或者 EDITOR 環(huán)境變量值指定的編輯器來進(jìn)行編輯。
如果這兩個環(huán)境變量都沒有定義,則默認(rèn)使用 /usr/bin/editor 文件指定的編輯器。
在 Debian 系統(tǒng)和 Ubuntu 系統(tǒng)上, /usr/bin/editor 文件是一個鏈接文件,最終鏈接到 /bin/nano 文件,也就是默認(rèn)使用 nano 編輯器。
在 Ubuntu 系統(tǒng)上測試發(fā)現(xiàn),第一次執(zhí)行 crontab -e 命令時,它會調(diào)用 select-editor 命令提供一個編輯器菜單列表,可以選擇一個默認(rèn)的編輯器。如果按 CTRL-D,什么都沒有選擇,默認(rèn)會使用 nano 編輯器。
crontab 文件格式
執(zhí)行 crontab -e 命令后,就會打開當(dāng)前用戶的 crontab 文件,在這個文件中,以 # 開頭的語句是注釋語句。
默認(rèn)的 crontab 文件包含一些注釋,在注釋中提供了一個例子、以及設(shè)置定時任務(wù)的字段格式說明。具體內(nèi)容如下:
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# m h dom mon dow command
這里舉例說明了一個 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ 定時任務(wù),在每周一的五點鐘會執(zhí)行 tar -zcf /var/backups/home.tgz /home/ 命令。
下面具體說明如何理解這個定時任務(wù)的各個字段。
在 crontab 文件中,通過 m h dom mon dow command 這六個字段來設(shè)置定時任務(wù),每一行對應(yīng)一個定時任務(wù)。這六個字段的含義說明如下:
- m:對應(yīng)分鐘(minute)
指定要在一小時之中的第幾分鐘執(zhí)行該任務(wù)。取值范圍是 0-59. - h:對應(yīng)小時(hour)
指定要在一天之中的第幾個小時執(zhí)行該任務(wù)。取值范圍是 0-23. - dom:對應(yīng)日期(day of month)
指定要在一月之中的第幾天執(zhí)行該任務(wù)。取值范圍是 0-31. - mon:對應(yīng)月份(month)
指定要在一年之中的第幾月執(zhí)行該任務(wù)。取值范圍是 1-12。
也可以通過月份英文名稱的前三個字母來指定,不區(qū)分大小寫。例如,一月的英文單詞是 january,那么這里可以用 jan 來指定一月。 - dow:對應(yīng)星期幾(day of week)
指定要在一周之中的星期幾執(zhí)行該任務(wù)。取值范圍是 0-7,0 和 7 都對應(yīng)星期天。
也可以通過星期英文名稱的前三個字母來指定,不區(qū)分大小寫。例如,星期一的英文單詞是 monday,那么這里可以用 mon 來指定星期一。 - command:對應(yīng)具體的操作
提供具體的命令來指定進(jìn)行什么操作,可以提供腳本文件的路徑來執(zhí)行該腳本文件。
這六個字段要求用空格隔開。且每個字段都必須提供值,不能省略某個字段的值。從第五個字段之后的所有內(nèi)容都屬于第六個字段,也就是要執(zhí)行的操作。
前五個字段可以使用下面的特殊字符來指定一些特殊的時間:
- *
表示任意一個有效的取值。例如,把日期指定為 *,則表示每一天都進(jìn)行該任務(wù)。 - -
表示一個有效的范圍值。例如,在小時指定為 8-11,表示在 8點、9點、10點、和 11點都執(zhí)行該任務(wù)。 - ,
表示隔開不同的取值列表。例如,把小時指定為 2,3,5,7,表示在 2點、3點、5點、7點都執(zhí)行該任務(wù)。
注意:在逗號后面不要加空格,空格表示隔開不同的字段。 - /
表示一個時間間隔,而不是指定具體的時間。例如,把小時指定為 */2,表示每間隔兩小時執(zhí)行一次該任務(wù)。
在 command 字段中,可以使用換行符、或者 % 字符來分隔命令內(nèi)容。
在第一個 % 之前的內(nèi)容會傳遞給 shell 來執(zhí)行,這個 % 自身會被替換成換行符,在 % 之后、直到行末的內(nèi)容都作為標(biāo)準(zhǔn)輸入傳遞。
如果需要提供 % 字符自身,需要用 % 進(jìn)行轉(zhuǎn)義。
cron 守護(hù)進(jìn)程如何執(zhí)行定時任務(wù)
在 man 5 crontab 的說明中,有如下內(nèi)容:
Several environment variables are set up automatically by the cron(8) daemon. SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd line of the crontab's owner. PATH is set to "/usr/bin:/bin". HOME, SHELL, and PATH may be overridden by settings in the crontab;
An alternative for setting up the commands path is using the fact that many shells will treat the tilde(~) as substitution of $HOME, so if you use bash for your tasks you can use this:
SHELL=/bin/bash
PATH=~/bin:/usr/bin/:/bin
即,cron 守護(hù)進(jìn)程默認(rèn)使用 /bin/sh 這個 shell 來執(zhí)行 crontab 文件指定的命令。
如果想要用 bash 來執(zhí)行,可以 crontab 文件中添加 SHELL=/bin/bash 這一行。
默認(rèn)的尋址路徑是 "/usr/bin:/bin",如果需要執(zhí)行的命令、或者腳本文件沒有放在這兩個路徑下,就需要通過文件路徑來指定,建議使用絕對路徑。
由于定時任務(wù)是由 cron 守護(hù)進(jìn)程來執(zhí)行,需要確認(rèn)該進(jìn)程已經(jīng)啟動,才能執(zhí)行定時任務(wù),可以使用下面命令來確認(rèn) cron 守護(hù)進(jìn)程是否已經(jīng)啟動:
$ service --status-all |& grep cron
[ + ] cron
$ ps -e | grep cron
2340 ? 00:00:36 cron
在 service --status-all |& grep cron 命令中,看到 cron 前面顯示加號 +,表示 cron 守護(hù)進(jìn)程已經(jīng)啟動。
在 ps -e | grep cron 命令中,要能查找到 cron 這個名稱,說明 cron 這個進(jìn)程正在運行。
設(shè)置定時任務(wù)的實例
我們在使用 crontab -e 命令打開 crontab 文件后,可以輸入下面的一行:
*/5 * * * * date >> ~/testcron.txt
基于前面的說明,第一個 */5 表示每間隔 5 分鐘就執(zhí)行一次,后面四個 * 表示在每個月的每一天的每一個小時都執(zhí)行該任務(wù)。
具體執(zhí)行的命令是 date >> ~/testcron.txt,把執(zhí)行任務(wù)時的時間追加寫入到 testcron.txt 文件。
即,這個定時任務(wù)每天都會運行,每間隔 5 分鐘就運行一次。可以通過查看 testcron.txt 文件來確認(rèn)是否執(zhí)行過該任務(wù)。
保存文件之后,再過 5 分鐘,查看 testcron.txt 文件內(nèi)容如下:
$ ls
testcron.txt
$ cat testcron.txt
2019年 12月 03日 星期二 14:20:01 CST
可以看到,在指定目錄下生成了 testcron.txt 文件,且該文件內(nèi)容就是 date 命令打印的日期,說明執(zhí)行過指定的定時任務(wù)。
隔了較長時間后,再查看 testcron.txt 文件內(nèi)容如下:
$ cat testcron.txt
2019年 12月 03日 星期二 14:20:01 CST
2019年 12月 03日 星期二 14:25:01 CST
2019年 12月 03日 星期二 14:30:01 CST
可以看到,確實是每隔 5 分鐘就寫入一次日期到 testcron.txt 文件。
查看定時任務(wù)內(nèi)容
在 crontab 命令中,可以使用 -l 選項來查看 crontab 文件內(nèi)容,從而看到里面包含的各個定時任務(wù)。
查看 man crontab 對 -l 選項的說明如下:
The -l option causes the current crontab to be displayed on standard output.
這個文件會打印整個 crontab 文件內(nèi)容,包含注釋語句。部分內(nèi)容列舉如下:
# m h dom mon dow command
*/5 * * * * date >> ~/testcron.txt
其實直接執(zhí)行 crontab -e 命令也能看到 crontab 文件內(nèi)容,只是看完之后需要退出編輯器,沒有 crontab -l 命令方便。
刪除定時任務(wù)
如果要刪除某個定時任務(wù),執(zhí)行 crontab -e 命令,從 crontab 文件刪除對應(yīng)定時任務(wù)所在的行,保存文件即可。也可以注釋對應(yīng)的行,以便后續(xù)需要的時候,再打開注釋。
如果要刪除所有定時任務(wù),可以使用 -r 選項。查看 man crontab 對 -r 選項的說明如下:
The -r option causes the current crontab to be removed.
即,-r 選項會刪除當(dāng)前用戶的 crontab 文件,從而刪除所有定時任務(wù)。