Kunci PHP Flock gagal kerana $file_lock tidak digunakan selepas kaedah isRunning() keluar.
Persekitaran pengendalian artikel ini: sistem Windows 7, PHP versi 7.1, komputer DELL G3
Apakah yang perlu saya lakukan jika kunci php kumpulan gagal?
Penyelesaian kepada masalah kegagalan kumpulan php:
Dalam dua hari lalu, saya menulis kaedah untuk projek masa lapang saya untuk mengelakkan pelaksanaan serentak skrip PHP dijadualkan oleh crontab .
Bagaimana untuk melakukannya
Secara amnya, dengan menggunakan kaedah kumpulan kunci fail, skrip PHP yang sama mengunci fail cakera yang sama tanpa menyekat , ralat akan dilaporkan, oleh itu Skrip boleh keluar serta-merta.
Fenomena
Tetapi dalam praktiknya, didapati bahawa ia adalah mungkin untuk terus berkumpul di dalam fail pengawal apabila logik kawanan dikapsulkan ke dalam fungsi dalam fail lain , Tidak sah.
Sebab
Setelah menyahpepijat untuk masa yang lama, tiba-tiba saya teringat bahawa saya pernah menghadapi perangkap ini sebelum ini. .
Kod ralat adalah seperti berikut:
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; } }
Jana nilai cincang unik berdasarkan parameter baris arahan, yang mewakili tugas PHP.
Buat fail kunci, laksanakan kunci bukan sekat kumpulan dan kembalikan wouldBlock untuk mengenal pasti sama ada kunci telah diduduki.
Saya memanggil kaedah Crontab::isRunning() pada entri skrip dan mendapati bahawa selepas memulakan skrip secara serentak, kunci sentiasa boleh diperolehi.
Sebab ralat ialah: selepas kaedah isRunning() keluar, $file_lock tidak digunakan lagi dan sampah dikumpul oleh PHP Pemegang fail $fp ditutup, menyebabkan kunci dilepaskan secara automatik.
Penyelesaian
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; } }
Cuma pastikan pemegang fail tidak akan dilepaskan semasa keseluruhan kitaran hayat PHP, jadi simpan dalam statik kelas pembolehubah ahli di dalam.
Pembelajaran yang disyorkan: "Tutorial Video PHP"
Atas ialah kandungan terperinci Apakah yang perlu saya lakukan jika kunci php flock gagal?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!