在計畫任務中,偶爾會看到重複執行的情況:
例如我們公司的計畫任務範例:
*/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指令提供了檔案鎖的功能。指令參數如下:
[root@qkzj_Multi-Purpose_1A_113.107.248.124 ganjincheng]# 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'
以上是crond腳本執行並發衝突怎麼解決?的詳細內容。更多資訊請關注PHP中文網其他相關文章!