linux 下的 crontab 定時任務服務,可以用來定時執行指令碼。工作中經常會用到這樣的服務,使用起來比較簡單。
/sbin/service crond start # 開啟服務
/sbin/service crond stop # 停止服務
/sbin/service crond restart #重啟服務
sudo crontab -e #插入一條定時任務
sudo crontab -l #檢視所有的 root 使用者下的定時任務列表
tail -f /var/log/cron # 實時檢視定時任務日誌
#例如,新增如下一條定時任務
#分 時 日 月 周
* * * * * php test.php
最近在工作中經常會用到定時任務,發現當我們的腳步的執行時間(假設:130s)大於定時任務的設定時間(假設:1分鐘)時,定時任務會重複開始執行,即上次的任務還沒有執行完,下次的任務的又開始執行。往往執行的指令碼裡的資源是不允許同時兩個指令碼同時共享資源,即保證操作的原子性。這樣會造成執行出錯,下面我們來驗證一下。
以下是乙個測試的 php 指令碼,該指令碼執行一次需要 130s
<?php
$time = time();
$id = uniqid(); //一次執行的唯一標示
while(time() - $time
< 130)
然後新增定時任務,每分鐘(60s)執行一次
*/1 * * * * php /home/phachon/cron/test.php
過一段時間後,檢視日誌:
分析日誌我們會發現 id = 57bbcd4d10262 的任務在 12:13:01 開始,但是還沒有結束的時候,id=57bbcd890e7f7 和 id=57bbcdc510685 的任務就已經開始了,這樣明顯存在問題。我們想要的是每次單獨執行完後,下乙個執行開始:
利用臨時檔案
思路很簡單,在執行檔案的開頭先判斷是否有乙個 test.lock 的檔案,如果有 test.lock 檔案,則 exit(),如果沒有的話,建立 test.lock 檔案,然後執行指令碼檔案,執行完畢刪除 test.lock;
實現後**:
<?php
$time = time();
$id = uniqid();
$lock = '/home/phachon/cron/lock/test.lock';
if(file_exists($lock))
touch($lock);
while(time() - $time
< 130)
unlink($lock);
檢視日誌如下:
利用指令碼加鎖
思路和第一種方式類似,只是不是用檔案判斷的方式,而是給檔案加鎖的方式
實現**:
<?php
$fp = fopen("/tmp/lock.txt", "w+");
// 進行排它型鎖定
if (flock($fp, lock_ex | lock_nb)) else
fclose($fp);
?>
第一種和第二種方法本質思路一樣,確實也解決了問題,但是這樣需要加**在我們的指令碼裡,而且,這樣其實 crontab 服務還是多了很多不必要的執行,浪費資源。
我們需要找到更加好的方法,在執行**前就已經判斷是否可以執行指令碼。
利用 linux flock 鎖機制
利用 flock(freebsd lockf,centos下為 flock),在指令碼執行前先檢測能否獲取某個檔案鎖,以防止指令碼執行衝突。
格式:
flock [-sxun][-w #] fd#
flock [-sxon][-w #] file [-c] command
選項:
-s, --shared: 獲得乙個共享鎖
-x, --exclusive: 獲得乙個獨佔鎖
-u, --unlock: 移除乙個鎖,指令碼執行完會自動丟棄鎖
-n, --nonblock: 如果沒有立即獲得鎖,直接失敗而不是等待
-w, --timeout: 如果沒有立即獲得鎖,等待指定時間
-o, --close: 在執行命令前關閉檔案的描述符號。用於如果命令產生子程序時會不受鎖的管控
-c, --command: 在shell中執行乙個單獨的命令
-h, --help 顯示幫助
-v, --version: 顯示版本
鎖型別:
共享鎖:多個程序可以使用同一把鎖,常被用作讀共享鎖
獨佔鎖:同時只允許乙個程序使用,又稱排他鎖,寫鎖。
這裡我們需要同時只允許乙個程序使用,所以使用獨佔鎖。
修改後的定時任務如下:
*/1 * * * * flock -xn /tmp/test.lock -c 'php /home/phachon/cron/test.php' >> /home/phachon/cron/cron.log'
日誌如下:
完美的解決了我們的問題
總體看來,還是用第三種方法比較好,而且也方便.
crontab防止指令碼週期內未執行完重複執行
八月 28,2015 no comments 個人體會 flock xn my.lock commond my.lock是乙個檔案,應該可以是任意檔案,可以新建乙個空檔案 當flock 獲得鎖後就會執行後面的 commond 測試過程 1 flock xn my.lock sleep 20 2 fl...
crontab任務未執行
最近在ubuntu系統中使用crontab定時任務遇到了問題,現記錄下來,希望能夠幫助到遇到同樣問題的同學。問題描述 使用crontab做mysql資料庫的定時備份,發現到點确沒有正常執行任務完成備份操作。解決思路 1.使用 service cron status 檢視crontab任務是否正常啟動...
unix週期執行指令Crontab命令
鏈結 主要內容 簡單解釋一下 crontab e 編輯,類似 vim,儲存退出時會檢查語法 l 列舉所有任務 r 刪除所有任務 如果 crontab 執行出錯,可以檢視日誌檔案 var log syslog 基本語法 min表示分鐘,範圍 0 59 hour表示小時,範圍 0 23 day表示天,範...