在linux上定期執行命令、指令碼(cron,crontab,anacron)

diwugebingren發表於2019-04-05

人類把時間做了切割,想象一條筆直的線永遠向前,本來這條直線上什麼都沒有,但是人類根據時間的長短(單位)在這條直線上做了密密麻麻的標記(世紀-年-月-日-時-分-秒-豪秒......),通過這樣的方式歷史上的每一個時刻都能夠被單獨拿出來,而未來的每一個時刻也能被單獨計劃。更重要的是,每一個單獨的時刻又能跟相鄰的被更大單位所控制的相似時刻做比較,比如,今天的晚上12點跟明天的晚上12點,相似的是,兩個時刻都是12點,不同的是今天跟明天,她們是相鄰的更大單位。因為這樣的緣故,在被更大單位所隔開的每一個相同時刻,我們可以告訴計算機重複某個任務。

在linux下,如果想要在未來的某個時刻執行某個任務,並且在未來的每一個這樣的時刻裡都要執行這個任務,舉個簡單的例子,比如說想要在將來,每天的十二點都重啟路由器,大多數發行版都自帶一個守護程式(daemon)cron來完成這項工作。

1.cron,crontab以及anacron的關係

cron是大多數linux發行版都自帶的守護程式(daemon),用來重複執行某些被設定好了確定的執行時間的任務,這些任務可以是每個月執行、每週執行、每天執行,甚至是每一分鐘執行。用cron執行的任務適合於24小時執行的機器,cron執行的任務會在設定好的時刻執行,當機器處於關機狀態下並錯過了任務執行的時間,cron任務就無法預期執行了。

crontab(cron table的簡稱)既可以指cron用來定期執行特定任務所需要的列表檔案,又可以指用來建立、刪除、檢視當前使用者(或者指定使用者)的crontab檔案的命令。

anacron不是守護程式,可以看做是cron守護程式的某種補充程式,anacron是獨立的linux程式,被cron守護程式或者其他開機指令碼啟動執行,可以每天、每週、每個月週期性地執行一項任務(最小單位為天)。適合於可能經常會關機的機器,當機器重新開機anacron程式啟動之後,anacron會檢查anacron任務是否在合適的週期執行了,如果未執行則在anacron設定好的延遲時間之後只執行一次任務,而不管任務錯過了幾次週期。舉個例子,比如你設定了一個每週備份檔案的任務,但是你的電腦因為你外出度假而處於關機狀態四周,當你回到家中開機後,anacron會在延遲一定時間之後只備份一次檔案。由於發行版的不同,cron守護程式如何執行anacron會有所不同。

2.crontab命令,crontab檔案語法

系統預設crontab檔案為/etc/crontab,以及/etc/cron.d/目錄下的檔案,有些程式會把自己的crontab檔案放在/etc/cron.d/目錄下。要修改/etc/crontab以及/etc/cron.d/目錄下的檔案需要root許可權。cron守護程式會檢查/etc/crontab以及/etc/cron.d/目錄下的檔案,根據這些檔案中的cron任務所設定的執行時間決定是否執行任務,如果當前時間與cron任務所設定的執行時間相同,則執行任務。

每個使用者自己的crontab檔案都會被放在 /var/spool/cron目錄下,預設為空,可以使用crontab命令建立。cron守護程式會檢查/var/spool/cron目錄下的檔案,根據這些檔案中的cron任務所設定的執行時間決定是否執行任務,如果當前時間與cron任務所設定的執行時間相同,則執行任務。

當cron的配置檔案發生改變時,不需要重置cron守護程式。cron守護程式會檢查配置檔案的變化。

建立自己的crontab之前,首先要設定環境變數EDITOR,cron程式根據它來確定使用哪個編輯器編輯crontab檔案。在home目錄下的.bashrc或者.profile里加入一行

#你也可以使用自己喜愛的其他終端編輯器
EDITOR=vim; export EDITOR

複製程式碼

2.1.crontab命令引數及使用示例

usage:	crontab [-u user] file
	crontab [ -u user ] [ -i ] { -e | -l | -r }
	-e	(edit user's crontab)
	-l	(list user's crontab)
	-r	(delete user's crontab)
	-i	(prompt before deleting user's crontab)
複製程式碼

建立並編輯當前使用者的crontab

crontab -e
複製程式碼

列出當前使用者的crontab

crontab -l
複製程式碼

刪除使用者linus的crontab

crontab -u linus -i -r
複製程式碼

2.2.crontab檔案語法詳解及示例

當用crontab -e編輯當前使用者的crontab檔案時,首先寫入以下內容。

# crontab -e
SHELL=/bin/bash
MAILTO=root@example.com
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

複製程式碼

該檔案的前三行程式碼設定了預設環境。cron守護程式並不提供任何環境。SHELL變數設定當cron任務(命令以及指令碼)執行時的shell,MAILTO變數設定cron任務執行結果傳送的郵箱,PATH設定去哪些目錄下尋找cron任務的命令。註釋部分則解釋一條cron任務的構成,一條cron任務就是一行,要設定多少條cron任務則寫多少行。一條cron任務由七個部分組成,從左到右依次為:

  • 分鐘(0-59)
  • 小時(0-23)
  • 天(1-31)
  • 月 (1-12):或者可以使用月份的英文單詞的前三個字母,比如jan,feb,mar,apr...
  • 星期(0-6):星期天用0或者7都可以,或者可以使用星期的英文單詞的前三個字母,比如sun,mon,tue,wed,thu,fri,sat
  • 使用者名稱稱(可以省略)
  • 要執行的命令或者指令碼目錄

前五個部分的編寫注意特殊符號的含義:

  • 如果你想匹配取值範圍內的所有值,使用“*”
  • 想匹配某些特殊的值,使用“,”,比如2,4,7就匹配的是2,4以及7。
  • 兩個值被“-”連線表示範圍,此時匹配的是範圍內所有值,包含“-”兩邊的值,比如4-7匹配的就是從4到7。
  • 想要表達每隔一段時間執行一次任務,使用 “/”, 比如分鐘部分中的 “*/10”表示每10分鐘執行一次,比如小時部分中的“10-22/2”則表示在早上10點到晚上10點這段時間內,每隔兩個小時執行一次。 注意:當“/”左邊的值可以除盡“/”右邊的值時,任務才會執行。

例子1: 每天凌晨執行

0 0 * * * root command
複製程式碼

例子2: 每週星期天早上五點執行

0 5 * * sun root command
複製程式碼

例子3: 每個月的前10天晚上10點開始每隔10分鐘執行一次命令

*/10 22 1-10 * * root command
複製程式碼

例子4: 從星期一到五,每個小時的第10分鐘、第20分鐘以及第30分鐘都執行一次命令

10,20,30 * * * 1-5 root command
複製程式碼

例子5: 從早上10點到晚上10點,每個偶數的小時(比如10點,12點)裡每五分鐘執行一次命令

*/5 10-22/2 * * * root command
複製程式碼

特殊簡便寫法:

@hourly 代表0 * * * *,每個小時執行一次

@daily 代表0 0 * * * ,每天凌晨執行一次

@weekly 代表0 0 * * 0,每週星期天凌晨執行一次

@monthly 代表0 0 1 * *,每個月第一天凌晨執行一次

@yearly 代表0 0 1 1 *,每年的頭一分鐘執行一次

@reboot 重啟後執行一次

例子: 每天凌晨執行一次 @daily command 你可以把需要每個小時執行一次的指令碼放到/etc/cron.hourly目錄下,cron守護程式會每個小時都執行一次。

2.3.限制可以使用cron的使用者

在/etc/目錄下,可能預設會有cron.allow以及cron.deny檔案,也可能沒有,沒有的情況下可以自己建立,cron.allow檔案包含了可以使用cron的使用者名稱,cron.deny檔案包含了不可以使用cron的使用者名稱。兩個檔案中每個使用者名稱佔一行,並且不允許出現空格。 root使用者在任何情況下都可以使用cron。 假如cron.allow存在,則只有列在這個檔案中的使用者名稱可以使用cron,這時候cron.deny被忽視。 假如cron.allow不存在,則列在cron.deny檔案中的使用者名稱不可以使用cron。

3.用anacron執行週期性的任務

anacron程式可以週期性的執行任務,但具體執行時間並不確定。可以每天、每週、每個月週期性的執行任務。當anacron的配置檔案發生改變時,下一次anacron執行時會檢查到配置檔案的變化。anacron的配置檔案為/etc/anacrontab,編輯需要root許可權,預設以下內容:

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7       25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly
複製程式碼

可以看到前三行設定了預設環境,RANDOM_DELAY變數設定了最大延遲執行時間,START_HOURS_RANGE變數設定了anacron任務執行的時間範圍,預設在每天的3點到22點之間。最後三行則設定了三條預設的anacron任務,分別是每天執行,每週執行,每月執行。

3.1.anacron檔案語法

觀察前面三條預設的anacron任務,可以看到一條anacron任務分為四個部分,從左到右依次為:

  • 週期(天):設定任務執行的頻率,以天數為單位,寫1則代表每天執行,寫3則代表每3天執行,可以使用特殊符號“@”,@daily代表每天,@weekly代表每週,@monthly代表每月。
  • 延遲時間:設定任務的延遲時間,以分鐘為單位,比如寫5,則當anacron啟動後,anacron等待5分鐘就會執行該任務。設定延遲時間是為了當機器啟動時不會因為執行很多anacron任務而過載。
  • 任務標識:其目的是識別訊息,日誌檔案和執行特殊操作。
  • 要執行的命令

在/etc/anacrontab中的三條預設anacron任務中,nice命令用來調整後面命令的優先順序,run-parts命令用來執行設定的目錄下的所有指令碼,就是說這三條任務分別每天,每週,每月執行/etc/cron.daily,/etc/cron.weekly,/etc/cron.monthly目錄下的指令碼。所以我們不用自己往/etc/anacrontab中新增anacrontab任務,而只需把指令碼放到相應的目錄下,anacron就會週期性的執行這些指令碼了。

3.2.anacron如何執行

既然anacron不是守護程式,那它是如何做到週期性執行任務的呢?在centos7下,cron會執行/etc/cron.d/0hourly,在/etc/cron.d/0hourly檔案裡,有一條cron任務是這樣的: 01 * * * * root run-parts /etc/cron.hourly 這條cron任務會執行/etc/cron.hourly目錄下的所有指令碼,其中有一個名為0anacron的指令碼,該指令碼則會在合適的時間執行anacron,anacron則會檢查/etc/anacrontab,在合適的時間分別執行/etc/cron.daily,/etc/cron.weekly,/etc/cron.monthly目錄下的指令碼。

參考資料:

How to Schedule Job on Linux using Cron, Anacron and at Commands

How to use cron in Linux

歡迎瀏覽我的個人部落格,https://diwugebingren.github.io

歡迎關注我的公眾號

相關文章