我有一个php脚本,我在CentOS上每隔10分钟通过cron执行这个脚本。
问题是如果cron作业需要10分钟以上,那么同一个cron作业的另一个实例将会启动。
我尝试了一个技巧,那就是:
但是,当由于任何原因未通过脚本删除或删除锁定文件时,可能存在一个问题。 cron永远不会重新开始。
如果cron作业已经在运行,使用Linux命令或类似的话,我有什么办法可以再次停止执行它?
答案 0 :(得分:45)
咨询锁定正是出于此目的。
您可以使用flock()
完成咨询锁定。只需将该函数应用于先前打开的锁定文件,以确定其他脚本是否有锁定。
$f = fopen('lock', 'w') or die ('Cannot create lock file');
if (flock($f, LOCK_EX | LOCK_NB)) {
// yay
}
在这种情况下,我正在添加LOCK_NB
以防止下一个脚本等到第一个脚本完成。由于您使用的是cron,因此总会有下一个脚本。
如果当前脚本过早终止,则操作系统将释放任何文件锁。
答案 1 :(得分:15)
如果您可以配置代码,可能最好不要编写代码:
https://serverfault.com/questions/82857/prevent-duplicate-cron-jobs-running
答案 2 :(得分:12)
flock()
对我很有用 - 我有一个cron作业,每5分钟安排一次数据库请求,所以不能同时运行几个是至关重要的。这就是我所做的:
$filehandle = fopen("lock.txt", "c+");
if (flock($filehandle, LOCK_EX | LOCK_NB)) {
// code here to start the cron job
flock($filehandle, LOCK_UN); // don't forget to release the lock
} else {
// throw an exception here to stop the next cron job
}
fclose($filehandle);
如果你不想杀死下一个预定的cron作业,只是暂停它直到正在运行的作业完成,那么只需省略LOCK_NB
:
if (flock($filehandle, LOCK_EX))
答案 3 :(得分:1)
这是一个非常简单的解决方案的常见问题:cronjoblock
一个简单的8行shellcript包装器使用flock应用锁定:
https://gist.github.com/coderofsalvation/1102e56d3d4dcbb1e36f
顺便说一句。
cronjoblock
也会阻止cron的垃圾邮件行为:只有在出现问题时才会输出内容。这对于cron的MAILTO变量来说很方便。 stdout / stderr输出将被抑制(因此cron不会发送邮件)除非给定进程有一个exitcode> 0
答案 4 :(得分:0)
flock在php 5.3.3中无效,因为删除了文件资源句柄关闭时的自动解锁。现在解锁总是必须手动完成。
答案 5 :(得分:0)
我用这个::
<?php
// Create a PID file
if (is_file (dirname ($_SERVER['SCRIPT_NAME']) . "/.processing")) { die (); }
file_put_contents (dirname ($_SERVER['SCRIPT_NAME']) . "/.processing", "processing");
// SCRIPT CONTENTS GOES HERE //
@unlink (dirname ($_SERVER['SCRIPT_NAME']) . "/.processing");
?>
答案 6 :(得分:0)
#!/bin/bash
ps -ef | grep -v grep | grep capture_12hz_sampling_track.php
if [ $? -eq 1 ];
then
nohup /usr/local/bin/php /opt/Apache/htdocs/cmsmusic_v2/script/Mp3DownloadProcessMp4/capture_12hz_sampling_track.php &
else
echo "Already running"
fi
答案 7 :(得分:0)
另一种选择:
<?php
/**
* Lock manager to ensure our cron doesn't run twice at the same time.
*
* Inspired by the lock mechanism in Mage_Index_Model_Process
*
* Usage:
*
* $lock = Mage::getModel('stcore/cron_lock');
*
* if (!$lock->isLocked()) {
* $lock->lock();
* // Do your stuff
* $lock->unlock();
* }
*/
class ST_Core_Model_Cron_Lock extends Varien_Object
{
/**
* Process lock properties
*/
protected $_isLocked = null;
protected $_lockFile = null;
/**
* Get lock file resource
*
* @return resource
*/
protected function _getLockFile()
{
if ($this->_lockFile === null) {
$varDir = Mage::getConfig()->getVarDir('locks');
$file = $varDir . DS . 'stcore_cron.lock';
if (is_file($file)) {
$this->_lockFile = fopen($file, 'w');
} else {
$this->_lockFile = fopen($file, 'x');
}
fwrite($this->_lockFile, date('r'));
}
return $this->_lockFile;
}
/**
* Lock process without blocking.
* This method allow protect multiple process runing and fast lock validation.
*
* @return Mage_Index_Model_Process
*/
public function lock()
{
$this->_isLocked = true;
flock($this->_getLockFile(), LOCK_EX | LOCK_NB);
return $this;
}
/**
* Lock and block process.
* If new instance of the process will try validate locking state
* script will wait until process will be unlocked
*
* @return Mage_Index_Model_Process
*/
public function lockAndBlock()
{
$this->_isLocked = true;
flock($this->_getLockFile(), LOCK_EX);
return $this;
}
/**
* Unlock process
*
* @return Mage_Index_Model_Process
*/
public function unlock()
{
$this->_isLocked = false;
flock($this->_getLockFile(), LOCK_UN);
return $this;
}
/**
* Check if process is locked
*
* @return bool
*/
public function isLocked()
{
if ($this->_isLocked !== null) {
return $this->_isLocked;
} else {
$fp = $this->_getLockFile();
if (flock($fp, LOCK_EX | LOCK_NB)) {
flock($fp, LOCK_UN);
return false;
}
return true;
}
}
/**
* Close file resource if it was opened
*/
public function __destruct()
{
if ($this->_lockFile) {
fclose($this->_lockFile);
}
}
}
答案 8 :(得分:0)
我正在运行一个php cron作业脚本,专门用于使用现有API发送文本消息。在我的本地方框上,cron工作正常,但在我的客户的盒子上,它发送了双重消息。虽然这对我没有意义,但我仔细检查了负责发送邮件的文件夹的权限,并将权限设置为root。一旦我将所有者设置为www-data(Ubuntu),它就开始正常运行。
这可能是你的问题,但如果它是一个简单的cron脚本,我会仔细检查权限。