問題的背景:
我們常常需要通過crontab部署某個腳本運行某些定時任務,但在實際的過程中,一旦處理不好可能導致在同一時刻出現腳本的多個運行副本,比如crontab的調度是每5 分鍾運行一次腳本,如果運行的腳本能夠在5分鍾內處理完任務並退出,則沒問題,同一時刻最多只有一個腳本在運行,但如果腳本如果無法在5分鍾內處理完任務並退出,則意味着在下一個5分鍾,腳本又會被crontab調起來,出現了同一時刻有2個甚至更多的腳本事例在運行,對應一些依賴關系,需要串行處理的腳本來說,可能會導致數據相互覆蓋等問題。
為了解決這個問題,腳本必須能夠自我保護,即在啟動之前判斷是否已經有腳本啟動了,若當前已經有腳本啟動了,則雖然crontab調度到該腳本,但腳本自身會馬上退出。
解決問題的思路很多,其中一種比較簡便的是:使用文件鎖,在linux中,提供了flock命令,具體格式如下:
1, flock [-sxon] [-w timeout] lockfile [-c]command...
2, flock [-sxun] [-w timeout] fd
選項:
-s, --shared: 獲得一個共享鎖
-x, --exclusive: 獲得一個獨占鎖
-u, --unlock: 移除一個鎖,腳本執行完會自動丟棄鎖
-n, --nonblock: 如果沒有立即獲得鎖,直接失敗而不是等待
-w, --timeout: 如果沒有立即獲得鎖,等待指定時間
-o, --close: 在運行命令前關閉文件的描述符號。用於如果命令產生子進程時會不受鎖的管控
-c, --command: 在shell中運行一個單獨的命令
-h, --help 顯示幫助
-V, --version: 顯示版本
鎖類型:
共享鎖:多個進程可以使用同一把鎖,常被用作讀共享鎖
獨占鎖:同時只允許一個進程使用,又稱排他鎖,寫鎖。
這里我們需要同時只允許一個進程使用,所以使用獨占鎖。
修改后的定時任務如下:日志為了方便排查問題
---------------------
* * * * * flock -xn /tmp/test.lock -c "timeout 200 php /home/app/email.php >> /home/log/test.log 2>&1"
開心嗎😺?