首頁 > 後端開發 > PHP問題 > flock php 鎖不成功怎麼辦?

flock php 鎖不成功怎麼辦?

藏色散人
發布: 2023-03-13 18:16:01
原創
2300 人瀏覽過

flock php鎖定不成功是因為在isRunning()方法退出後,$file_lock沒有繼續使用導致的,其解決方法就是確保在整個PHP生命期內,檔案句柄都不會被釋放即可。

flock php 鎖不成功怎麼辦?

本文操作環境:Windows7系統、PHP7.1版、DELL G3電腦

flock php 鎖定不成功怎麼辦?

php flock失效問題解決:

這兩天為自己的業餘專案寫了一個方法,用來避免crontab調度的PHP腳本並發執行。

做法

一般透過使用檔案鎖定flock方法,令相同的PHP腳本採用非阻塞鎖定同一個磁碟文件,如果檔案被佔用則會報錯,從而可以腳本立即退出。

現象

但實踐中發現,在controller檔案中直接flock是可以實現的,當把flock的邏輯封裝到其他檔案的一個函數中後就失效了。

原因

調試了半天,突然想起來以前就遇過這個神坑。 。

錯誤代碼如下:

class Crontab
{
    /**
     * 确保任务没有并发执行
     */
    public static function isRunning() {
        global $argv;
        $ident = [];
        foreach ($argv as $idx => $value) {
            $ident[] = $idx . '=' . urlencode($value);
        }
        $ident = md5(implode('&', $ident));
        $lockDir = \Yii::getAlias('@app/runtime/crontab/');
        @mkdir($lockDir, 0755, true);
        $file_lock = fopen($lockDir . $ident, 'w+');
        $wouldBlock = 0;
        flock($file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
        return $wouldBlock;
    }
}
登入後複製
class Crontab
{
    /**
     * 确保任务没有并发执行
     */
    public static function isRunning() {
        global $argv;
 
        $ident = [];
        foreach ($argv as $idx => $value) {
            $ident[] = $idx . '=' . urlencode($value);
        }
        $ident = md5(implode('&', $ident));
 
        $lockDir = \Yii::getAlias('@app/runtime/crontab/');
 
        @mkdir($lockDir, 0755, true);
 
        $file_lock = fopen($lockDir . $ident, 'w+');
 
        $wouldBlock = 0;
        flock($file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
 
        return $wouldBlock;
    }
}
登入後複製

根據命令列參數產生唯一hash值,代表該PHP任務。

建立鎖定文件,執行flock非阻塞鎖,返回wouldBlock標識鎖是否已被佔用。

我在腳本入口呼叫了Crontab::isRunning()方法,發現並發啟動腳本後,總是能獲得鎖定。

錯誤原因是:isRunning()方法退出後,$file_lock沒有繼續使用,被PHP垃圾回收,$fp檔案句柄關閉導致鎖定自動釋放。

解決

class Crontab
{
    /**
     * 保存起来避免被php作为垃圾回收
     * @var null
     */
    static $file_lock = null;
    /**
     * 确保任务没有并发执行
     */
    public static function isRunning() {
        global $argv;
        $ident = [];
        foreach ($argv as $idx => $value) {
            $ident[] = $idx . '=' . urlencode($value);
        }
        $ident = md5(implode('&', $ident));
        $lockDir = \Yii::getAlias('@app/runtime/crontab/');
        @mkdir($lockDir, 0755, true);
        self::$file_lock = fopen($lockDir . $ident, 'w+');
        $wouldBlock = 0;
        flock(self::$file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
        return $wouldBlock;
    }
}
登入後複製
class Crontab
{
    /**
     * 保存起来避免被php作为垃圾回收
     * @var null
     */
    static $file_lock = null;
 
    /**
     * 确保任务没有并发执行
     */
    public static function isRunning() {
        global $argv;
 
        $ident = [];
        foreach ($argv as $idx => $value) {
            $ident[] = $idx . '=' . urlencode($value);
        }
        $ident = md5(implode('&', $ident));
 
        $lockDir = \Yii::getAlias('@app/runtime/crontab/');
 
        @mkdir($lockDir, 0755, true);
 
        self::$file_lock = fopen($lockDir . $ident, 'w+');
 
        $wouldBlock = 0;
        flock(self::$file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
 
        return $wouldBlock;
    }
}
登入後複製

確保在整個PHP生命期內,檔案句柄都不會被釋放即可,所以保存在類別靜態成員變數裡。

推薦學習:《PHP影片教學

以上是flock php 鎖不成功怎麼辦?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板