我需要一种方法来防止在 symfony 1.4 上的进程多次运行。
比如:当一个用户正在运行这个进程时,另一个试图运行这个进程的用户会收到一条警告消息,通知该进程正在运行。
有没有办法在不使用数据库的情况下实现它?
我需要一种方法来防止在 symfony 1.4 上的进程多次运行。
比如:当一个用户正在运行这个进程时,另一个试图运行这个进程的用户会收到一条警告消息,通知该进程正在运行。
有没有办法在不使用数据库的情况下实现它?
kirugan 的方法可能在大多数情况下都有效,但它容易受到竞争条件的影响,并且在发生崩溃时可能会卡住。
这是一个更强大的解决方案。它使用 PHP 的文件锁定,因此您知道锁是原子的,如果您稍后忘记释放锁或您的进程崩溃,它会自动释放。默认情况下,获取锁是非阻塞的(即如果锁已经被另一个进程持有,getLock()
将立即返回 FALSE)。但是,如果您愿意,您可以设置调用块(即等到锁可用)。最后,您可以为代码的不同部分设置不同的锁。只需为锁使用不同的名称。
唯一的要求是返回的目录getLockDir()
必须是服务器可写的。随意更改锁定目录的位置。
注意:我认为flock () 在Windows 上的行为可能不同(我使用linux),所以请仔细检查它是否对您有问题。
myLock.class.php
class myLock
{
/**
* Creates a lockfile and acquires an exclusive lock on it.
*
* @param string $filename The name of the lockfile.
* @param boolean $blocking Block until lock becomes available (default: don't block, just fail)
* @return mixed Returns the lockfile, or FALSE if a lock could not be acquired.
*/
public static function getLock($name, $blocking = false)
{
$filename = static::getLockDir() . '/' . $name;
if (!preg_match('/\.lo?ck$/', $filename))
{
$filename .= '.lck';
}
if (!file_exists($filename))
{
file_put_contents($filename, '');
chmod($filename, 0777); // if the file cant be opened for writing later, getting the lock will fail
}
$lockFile = fopen($filename, 'w+');
if (!flock($lockFile, $blocking ? LOCK_EX : LOCK_EX|LOCK_NB))
{
fclose($lockFile);
return false;
}
return $lockFile;
}
/**
* Free a lock.
*
* @param resource $lockFile
*/
public static function freeLock($lockFile)
{
if ($lockFile)
{
flock($lockFile, LOCK_UN);
fclose($lockFile);
}
}
public static function getLockDir()
{
return sfConfig::get('sf_root_dir') . '/data/lock';
}
}
如何使用
$lockFile = myLock::getLock('lock-name');
if ($lockFile) {
// you have a lock here, do whatever you want
myLock::freeLock($lockFile);
}
else {
// you could not get the lock. show a message or throw an exception or whatever
}
这是我的功能:
function lock(){
$file = __DIR__ . '/file.lock';
if(file_exists($file)){
/* exit or whatever you want */
die('ALREADY LOCKED');
}
touch($file);
}
function unlock(){
$file = __DIR__ . '/parser.lock';
if(file_exists($file)){
unlink($file);
}else{
echoln("unlock function: LOCK FILE NOT FOUND");
}
}
function exitHandler(){
echoln('exitHandler function: called');
unlock();
}
开头使用lock
函数,设置exitHandler
函数在register_shutdown_function()
. 您可以使用相同的方法将此片段保存为类或将其保存为帮助文件