『學了就忘』Linux系統定時任務 — 88、循環執行定時任務

需使用crontab命令。

crontab命令可以循環執行定時任務。比如每天的凌晨2點都執行一次某個任務。

cron服務是Linux系統自帶的守護進程(daemon),用來重複運行某些被設定好了確定的運行時間的任務,這些任務可以是每個月運行、每周運行、每天運行,甚至是每一分鐘運行。

在Linxu系統中,有三種用於任務調度的工具

  • at命令調用atd服務。
  • crontab命令調用cron(crond)服務。
  • anacron工具。

1、crond服務管理與訪問控制

crontab命令是需要crond服務支援的,crond服務同樣是獨立的服務,所以啟動和自啟動方法如下:

# 重啟動crond服務
[root@localhost ~]# service crond restart
停止 crond:                                [確定]
正在啟動 crond:                             [確定]


# 設定crond服務為開機自啟動
[root@localhost ~]# chkconfig crond on

提示:只要你的Linux系統是安裝的,哪怕是最小化安裝,at服務和cron服務默認都是啟動的。

image

2、crontab命令的訪問控制

crond服務默認是自啟動的,如果伺服器上有循環執行的系統定時任務,就不要關閉crond服務了。
crontab命令和at命令類似,也是通過/etc/cron.allow/etc/cron.deny文件來限制某些用戶是否可以使用crontab命令的,而且原則也非常相似:

  1. 當系統中有/etc/cron.allow文件時,只有寫入此文件的用戶可以使用crontab命令,沒有寫入的用戶不能使用crontab 命令。同樣如果有此文件,/etc/cron.deny文件會被忽略,/etc/cron.allow文件的優先順序更高。
  2. 當系統中只有/etc/cron.deny文件時,則寫入此文件的用戶不能使用crontab命令,沒有寫入文件的用戶可以使用crontab命令。

crontab命令規則基本和at命令的規則一直,同樣/etc/cron.allow文件的優先順序比/etc/cron.deny文件的優先順序高,Linux 中默認只有/etc/cron.deny文件。

3、用戶級別的crontab命令

(1)crontab命令介紹

cron服務提供crontab命令來設定cron服務的,

也就是使用crontab命令的方式實現cron定時任務。

每個用戶都可以實現自己的crontab定時任務,只要是使用用戶身份執行crontab -e命令即可,當然這個用戶不能加入/etc/cron.deny文件中。

也就是說這種方式只能是,哪個用戶定義的crontab定時任務,就由哪個用戶來執行。

crontab命令格式如下:

[root@localhost ~]# crontab [選項]

選項:
  -e:編輯crontab定時任務
  -l:查詢crontab任務
  -r:刪除當前用戶所有的crontab任務,如果有多個任務,只想刪除一個,可以用「crontab -e」
  -u用戶名:修改或刪除其他用戶的crontab任務。只有root可用。

示例:

# 進入crontab編輯介面。
# 會打開一個空的文本文件,是一個vim編輯介面。
# 在vim中編寫你的工作。
[root@localhost ~]# crontab -e

# 編輯的內容
*****執行的任務

提示:

任務可以是單一的執行命令,單一的命令所能完成的工作是比較少的,一般在工作中都是使用執行腳本。

內容含義說明:

項目 含義 範圍
第一個」*「 一小時當中的第幾分鐘 0-59
第二個」*「 一天當中的第幾小時 0-23
第三個」*「 一個月當中的第幾天 1-31
第四個」*「 一年當中的第幾月 1-12
第五個」*「 一周當中的星期幾 0-7(0和7都代表星期日)

時間的表達式中,還有一些特殊符號:

特殊符號 含義
* 代表任何時間。比如第一個「*」就代表一小時中每分鐘都執行一次的意思。
, 代表不連續的時間。比如0 8,12,16 * * * 所要執行的命令,就代表在每天的8點0分,12點0分,16點0分都執行一次命令。
- 代表連續的時間範圍。比如0 5 * * 1-6 所要執行的命令,代表在周一到周六的凌晨5點0分執行命令。
*/10 代表每隔多久執行一次。比如*/10 * * * * 所要執行的命令,代表每隔10分鐘就執行一遍命令。

時間表達式示例:

時間 含義
10 * * * * 所要執行的命令 每小時的第10分鐘執行一次命令
45 22 * * * 所要執行的命令 在22點45分執行命令
0 17 * * 1 所要執行的命令 每周1的17點0分執行命令
0 5 1,15 * * 所要執行的命令 每月1日和15日的凌晨5點0分執行命令
40 4 * * 1-5 所要執行的命令 每周一到周五的凌晨4點40分執行命令
*/10 4 * * * 所要執行的命令 每天的凌晨4點,每隔10分鐘執行一次命令
0 0 1,15 * 1 所要執行的命令 每月1日和15日,每周1的0點0分都會執行命令。
日和星期不是並且的關係,是或者的關係。

注意:星期幾和幾號最好不要同時出現,因為他們定義的都是天,非常容易讓管理員混亂。

在舉一個特例:

0 6 31 * * 所要執行的命令,不一定每個月都有31日,在沒有31日的月份就不執行。在做定時任務的時候,最後不要選這麼極端的時間。

crontab命令定時任務示例:

  • 讓系統每隔1分鐘,就向/tmp/test文件中寫入一行「12345」,驗證一下系統定時任務是否會執行。
    [root@localhost ~]# crontab -e
    
    # 進入vim編輯介面
    * * * * * /bin/echo "12345" >> /tmp/test
    
  • 系統在每周二的凌晨5點05分重啟一次
    [root@localhost ~]# crontab -e
    
    # 進入vim編輯介面
    5 5 * * 2 /sbin/shutdown -r now
    

    提示:不建議用定時任務執行伺服器重啟,有可能出現伺服器沒有重新啟動的情況。伺服器的重啟操作最好還是需要管理員參與。

  • 在每月的1號,10號,15號的凌晨3點30分都定時執行日誌備份腳本autobak.sh
    [root@localhost ~]# crontab -e
    
    # 進入vim編輯介面
    30 3 1,10,15 * * /root/sh/autobak.sh
    

    這個操作常用。

(2)查看crontab任務

查看root用戶的crontab任務。

[root@localhost ~]# crontab -l
* * * * * /bin/echo "12345" >> /tmp/test

(3)刪除crontab任務

刪除root用戶所有的定時任務。

[root@localhost ~]# crontab -r

提示:如果只想刪除某一個定時任務,需要進入crontab -e編輯模式手工刪除。

4、crontab命令的注意事項

在書寫crontab定時任務時,需要注意幾個注意事項,這裡我們再強調下:

  1. 六個選項都不能為空,必須填寫,如果不確定使用*代表任意時間。
  2. crontab定時任務,最小有效時間是分鐘,最大有效時間是月。像2020年某時執行,3點30分30秒這樣的時間都不能識別。
  3. 在定義時間時,日期和星期最好不要在一條定時任務中出現,因為它們都是以天作為單位,非常容易讓管理員混亂。
  4. 在定時任務中,不管是直接寫命令,還是在腳本中寫命令,最好都是用絕對路徑。有時相對路徑的命令會報錯。

5、系統的crontab設置

(1)/etc/crontab配置文件說明

crontab -e是每個用戶執行的命令,也就是說不同的用戶身份可以執行自己的定時任務。可是有些定時任務需要系統執行,這時我們就需要編輯/etc/crontab這個配置文件了。

並不是說寫入/etc/crontab配置文件中的定時任務執行時,不需要用戶身份,而是crontab -e命令定義定時任務時,默認用戶身份是當前登錄用戶。而修改/etc/crontab配置文件時,定時任務的執行者的身份,是可以手工指定的。

這樣定時任務的執行會更加靈活,修改起來也更加方便。

我們來查看一下/etc/crontab配置文件:

[root@localhost ~]# vim /etc/crontab 

# /etc/crontab 配置文件內容
# 1.標識使用哪種shell
SHELL=/bin/bash
# 2.指定PATH環境變數,crontab是使用自己的PATH,
# 而不是用系統默認的,所以在定時任務中出現的命令最好使用絕對路徑。
PATH=/sbin:/bin:/usr/sbin:/usr/bin
# 3.如果有報錯輸出,或命令結果有輸出,會向root發資訊
MAILTO=root
# 4.標識主目錄
HOME=/

# 5.提示大家可以去「man 4 crontabs"查看幫助
# For details see man 4 crontabs

# 6.列出文件格式,並加入了注釋
# 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
# 分 時  日 月 周 執行者身份     命令

CentOS 5.x/etc/crontab文件的內容大概是這個樣子:

[root@localhost ~]# vim /etc/crontab 

# /etc/crontab 配置文件內容
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/


# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

說明:

  • CentOS 5.x版本中,/etc/crontab文件會使用run-parts腳本執行/etc/cron.{daily,weekly,monthly}目錄中的所有文件。這個run-parts其實是一個shell腳本,保存在/usr/bin/run-parts,它的作用就是把其後面跟隨的目錄中的所有可執行文件依次執行。
    (意思是說在daily,weekly,monthly這些目錄里存放腳本,並按賦予run-parts腳本的定時時間來執行目錄中的所有腳本)
    (在CentOS 6.x版本中也存在)
  • 02 4 * * * root run-parts /etc/cron.daily為例:
    如果我們想讓某個腳本在每天都執行一次,可以不用手工去寫定時任務,而只需要給run-parts腳本賦予執行許可權,並把它放入/etc/cron.daily/目錄中,這樣這個腳本就會在每天的凌晨4點02分執行了。
  • 我們在來看看/etc/cron.{daily,weekly,monthly}目錄
    進入到etc目錄中查看上面這幾個目錄,如下圖所示:
    image
    我們可以看到daily,weekly,monthly是三個目錄,裡邊存放著一些可執行腳本。
    這裡我們就明白了,當按照定時表達式執行一個run-parts腳本的時候,run-parts腳本會把跟在他後邊的目錄中的腳本都執行一次,從而完成定時任務。

CentOS 6.x版本中crontab命令是如何執行定時任務的呢?

我們看到/etc/crontab中有一句提示,讓我們man 4 crontabs來查看幫助。在這個幫助中,明確寫明了「在舊版本的crontab配置文件中,是通過run-parts腳本來調用/etc/cron.{daily,weekly,monthly}目錄中的腳本文件,定時執行這些目錄中的腳本。在當前系統中,為了避免cronanacron之間產生衝突,只要anacron已經安裝,就使用anacron來執行這些目錄中的腳本。」

對於anacron工具的用法,我們下一篇文章來介紹。

(2)通過配置文件的方式設置定時任務

其實對我們用戶來講,並不需要知道這個定時任務到底是由哪個程式調用的。我們需要知道的事情是如何使用系統的crontab設置。

這個新老版本的CentOS沒有區別,配置方法都有兩種:

1)方式一

第一種方法就是上面說過的,把你需要定時執行的工作寫成腳本程式,並賦予執行許可權,然後直接把這個腳本複製到/etc/cron.{daily,weekly,monthly}目錄中的任意一個。比如我需要讓某個腳本每周執行,那麼就把這個腳本複製到/etc/cron.weekly/目錄中。這樣這個腳本就會每周執行一次,具體的執行時間要參考anacron的配置。

2)方式二

第二種方法就是修改/etc/crontab這個配置文件,自己加入自己的定時任務,不過需要注意指定腳本的執行者身份。

例如:

[root@localhost ~]# vim /etc/crontab

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# 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

# 如下編輯定時任務
# 說明:
#	讓系統每分鐘都執行一次/root/cron目錄中的腳本,腳本執行者是root用戶。
#	雖然在Centos 6.x中,不是直接通過此配置文件調用/etc/cron.{daily,weekly,monthly}這些目錄,
#	但是run-parts腳本還是可以使用的。所以我完全可以參照CentOS 5.x的方法來寫定時任務。
#	使用run-parts腳本調用並執行/root/cron/目錄中所有的可執行文件
* * * * * root run-parts /root/cron/
#	/root/cron/是自己指定的目錄,也可以是默認的/etc/cron.{daily,weekly,monthly}這些目錄

# 保存退出

# 建立/root/cron目錄
[root@localhost ~]# mkdir /root/cron

# 在/root/cron/目錄中編輯一個hello.sh腳本
# 向hello.log文件中寫入「hello」
[root@localhost ~]# vim /root/cron/hello.sh
#!/bin/bash 
echo "hello" >> /root/cron/hello.log

# 保存退出

# 給hello.sh腳本賦予執行許可權。
[root@localhost ~]# chmod 755 hello.sh

# 註:因為hello.sh腳本放入了/root/cron/目錄,所以會每分鐘執行一次。

只要保存/etc/crontab文件,這個定時任務就可以執行了,當然要確定crond服務是運行的。

這兩種方法都是可以使用的,具體看個人的習慣吧!不過要想修改/etc/crontab文件,當然我要是root用戶才可以,普通不能修改,只能使用用戶身份的crontab命令。