crontab使用進程鎖解決沖突


想到一個問題,如果在crontab里有個定時任務設置為一分鍾執行一次,但是它執行的時間可能會超過一分鍾,此時crontab一分鍾后會再次運行該腳本嗎?這樣會不會出現沖突呢?網上找了下,說可以用Linux中的進程鎖控制crontab執行的並發問題。

給一個shell腳本加鎖,使用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 :顯示版本。

測試一下看看:
在/home目錄下建立一個test.sh。

vim /home/test.sh

輸入:

#!/bin/bash
wget --limit-rate=200k -P /tmp http://cachefly.cachefly.net/100mb.test

運行一個超過一分鍾的命令。

chmod +x /home/test.sh

編輯crontab:

crontab -e

輸入:

*/1 * * * * /usr/bin/flock -xn /var/run/test.lock -c '/home/test.sh'

設置每一分鍾執行一次。

重啟服務:

service crond restart

這樣只有第一個進程執行完畢后,才會執行當前的下一個進程。在第一個進程執行過程中,下一分鍾crontab運行flock檢測到獲得不了鎖,就直接退出,直到第一個進程執行完,flock再次獲得鎖。

 

注:

1、這種使用文件鎖的方式,在linux中非常常見,通過一個pid文件,來避免兩個進程同時運行,mysql和postgresql都有pid文件,mysql中只記錄了pid值,postgresql的pid中除了記錄有pid值,還有數據目錄,pid文件的創建時間,端口號,監聽地址和共享內存的地址。

2、使用PID文件鎖還有一個好處,方便進程向自己發停止或者重啟信號。Nginx編譯時可指定參數--pid-path=/var/run/nginx.pid,進程起來后就會把當前的PID寫入這個文件,當然如果這個文件已經存在了,也就是前一個進程還沒有退出,那么Nginx就不會重新啟動。進程管理工具Supervisord也是通過記錄進程的PID來停止或者拉起它監控的進程的

3、flock加的advisory lock,也就是建議性鎖,巧合的是,postgresql中也有advisory lock,非常適用於秒殺等高並發的場景。flock是通過獲取文件的fd來加鎖的。

 

參考:

http://www.live-in.org/archives/1036.html

https://linux.die.net/man/2/flock


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM