2021-05-12 14:32:11
crond指令碼執行並行衝突問題
2020-06-16 17:12:40
在計劃任務中,偶爾會看到重複執行的情況:
例如我們公司的計劃任務舉例:
*/2 * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testOne >/dev/null 2>&1 */2 * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testTwo >/dev/null 2>&1
這是兩分鐘執行一次的任務,並不能保證每次開啟的進程能夠在兩分鐘內絕對的執行完畢關閉,進程一直堆積的話,可能會把系統資源給耗盡,導致系統宕機。
舉例:
新建test.php檔案,程式碼如下:
<?php sleep(70); ?>
新增計劃任務:
*/1 * * * * root cd /home/ganjincheng;php test.php
等待執行,發生堆積
root 26722 0.0 0.0 9232 1064 ? Ss 12:05 0:00 /bin/sh -c cd /home/ganjincheng;php test.php root 26744 0.0 0.0 112304 8840 ? S 12:05 0:00 php test.php root 29102 0.0 0.0 9232 1060 ? Ss 12:06 0:00 /bin/sh -c cd /home/ganjincheng;php test.php root 29116 0.1 0.0 112304 8840 ? S 12:06 0:00 php test.php root 29906 0.0 0.0 103320 904 pts/3 S+ 12:06 0:00 grep test.php
解決方案
第一種,程式碼中控制並行
這種方法,就是對程式碼進行改造。增加是否有進程執行的判斷。如下面的程式碼:
<?php $lockfile = '/tmp/mytest.lock'; if(file_exists($lockfile)){ exit(); } file_put_contents($lockfile, date("Y-m-d H:i:s")); sleep(70); unlink($lockfile); ?>
這種判斷檔案是否不存在的方式,會有一個問題。那就是有可能程式未執行到最後,也就是沒有刪除之前建立的mytest.lock檔案。這會導致,之後程式將不能正常執行。
第二種,資料庫控制並行
可以將第一種方案轉移到redis,memache中,進行鍵值判斷。
如果計劃任務是對資料庫進行存取,那可以進行鎖表操作。偶爾我們也可以利用唯一索引與聯合索引的唯一性來避免重複插入情況
第三種,判斷進程是否存在
舉例:
$fp = popen("ps aux | grep 'test.php' | wc -l", "r"); $proc_num = fgets($fp); if ($proc_num > 3) { //這裡要注意為什麼進程數要大於3,實際操作一遍你就明白了 exit; } sleep(70);
這種方式有一個弊端,就是ps命令要寫的精確。避免把不是執行test.php指令碼的進程也統計到。如:
我們通過vim開啟test.php檔案。就會導致上面命令誤統計。所以當我們不小心vim開啟test.php檔案的時候,就執行不起來了。
第四種,使用linux的flock命令
讓linux幫我們去判斷啊,flock命令提供了檔案鎖的功能。命令引數如下:
[root@www.linuxidc.com]# flock -h flock (util-linux-ng 2.17.2) Usage: flock [-sxun][-w #] fd# flock [-sxon][-w #] file [-c] command... flock [-sxon][-w #] directory [-c] command... -s --shared Get a shared lock -x --exclusive Get an exclusive lock -u --unlock Remove a lock -n --nonblock Fail rather than wait -w --timeout Wait for a limited amount of time -o --close Close file descriptor before running command -c --command Run a single command string through the shell -h --help Display this text -V --version Display version
設定舉例:
*/1 * * * * root flock -xn /tmp/mytest.lock -c 'php ./test.php'
本文永久更新連結地址:http://www.linuxidc.com/Linux/2017-06/144883.htm
相關文章