crontab在一秒內刷新屢次致使部分腳本不生效的問題分析

版權聲明:本文由康中良原創文章,轉載請註明出處: 
文章原文連接:https://www.qcloud.com/community/article/182mysql

來源:騰雲閣 https://www.qcloud.com/communitysql

 

今天ob在幾臺DB上發現crontab中的監控任務,歷來沒有執行。但操做一下crontab的配置crontab –e + wq,監控任務就能正常執行,重啓cron也能正常執行。函數

出問題的機器crontab的狀況以下:

問題挺奇怪,第一條crontab執行正常,第二條crontab一直沒有執行。spa

第一條正常,證實cron有正常運行。DB監控任務的crontab是凱麗系統自動安裝的,理論上不會存在忽然出錯的狀況。日誌

問題定位:

cron出bug了? 第二個任務確實沒有執行,仍是執行前遇到問題退出,恰好日誌又打印到/dev/null了..code

考慮到crontab執行歷史在系統日誌裏會有記錄,檢查var/log/message日誌以下,整*/5的分鐘點只有crontab的第一個任務。crontab

crontab第二個任務確實沒執行,應該是crontab出了點問題,再看看在修改crontab的那一刻發生了什麼?文檔

根據crontab最後一次修改的時間(2012-06-18 17:51:01),檢查系統日誌以下:
get

剛巧,在同一秒內修改了2次crontab。根據凱麗安裝監控的順序,第一個crontab應該是在安裝第一條crontab任務,第二個crontab應該是在安裝第二個crontab任務。it

猜測:根據cron的工做原理,難道在增長第一個任務以後,cron加載了crontab的配置(/var/spool/cron/tabs/mysql),可是在增長第二個任務以後,cron沒有加載該配置? 若是是這樣,那麼cron判斷是否須要加載配置文件的機制是如何的呢?

網上文檔稀少,直接看代碼。

在網上找到一個debian的cron源代碼: cron_3.0pl1.orig.tar.gz

解壓打開,查看cron的執行過程:
在cron.c 的main函數中,cron的主函數代碼以下:

cron_sleep(): crontab 最小執行單位是分鐘,所以是每60秒執行一次.TargetTime += 60;

load_database(): 檢查crontab的配置文件是否有更新,若是有更新,則從新load,不然使用上次記錄的database cron_tick( ): 實際執行任務查看cron是如何加載crontab的配置文件的,進入load_database()函數.
database.c :

能夠看到,在cron加載配置的時候,會先獲取/var/spool/cron/tabs 目錄stat信息,而後獲取用戶的crontab配置文件的stat信息,而後比較上一次統計的修改時間與tabs目錄、crontab配置文件的最後修改時間,若是一致則不從新load,不然從新load crontab配置文件。

stat爲系統函數調用,該函數取得的結構體的st_mtime的單位爲秒。

至此,咱們能夠得出這樣的結論:

因爲兩次crontab修改時間均在同一秒,而cron的加載是以crontab配置文件的最後修改時間(秒級)來判斷文件是否須要更新。當出現如下場景,第二次對crontab的修改就會失效(不只是增長)。

crontab失效的場景:

而這個場景,恰好是咱們的DB出現crontab失效的狀況。

crontab的刷新機制,是以crontab文件的最後修改時間爲準.

所以,若是在一秒內對crontab進行屢次(大於1次)操做,就可能出現後修改的crontab不執行!

當再次對crontab文件進行保存操做時,cron會從新加載配置文件,crontab生效.

解決辦法:

該問題是因爲在一秒內執行屢次crontab變動致使。所以解決辦法有3個:

  1. 在凱麗每次操做crontab的時候增長sleep 1的操做

  2. 在凱麗每次crontab操做完成以後,sleep 1,強制刷新crontab的最後更新時間

  3. 合併並行的crontab操做爲一次操做,減小對crontab的操做頻率

根據凱麗的狀況,選擇第二個方案對現有代碼改動最小。

提醒:

腳本儘可能不要在同一秒內屢次操做crontab內容,不然可能致使crontab不生效的狀況。

相關文章
相關標籤/搜索