我有一个带有 PHP 的 cronjob 系统。我有一个名为 cron.php 的文件,想检查它是否未加载,请加载它。对我来说非常重要的是这个文件只运行一次,我需要定义它已经运行的方式。我不能使用任何系统功能,如 exec,system,... 你有什么解决方案吗?
注意:我通过 CURL 运行我的脚本,并且 include_one 和 require_once 不适用于这种情况。
我有一个带有 PHP 的 cronjob 系统。我有一个名为 cron.php 的文件,想检查它是否未加载,请加载它。对我来说非常重要的是这个文件只运行一次,我需要定义它已经运行的方式。我不能使用任何系统功能,如 exec,system,... 你有什么解决方案吗?
注意:我通过 CURL 运行我的脚本,并且 include_one 和 require_once 不适用于这种情况。
您可以使用flock()
锁定 php 文件本身,如下所示:
<?php
class Lock{
private $fp;
function __construct(){
$this->fp=fopen(__FILE__,'r');
if (!flock($this->fp,LOCK_EX|LOCK_NB)) {
die('already running !'.PHP_EOL);
}
}
function __destruct(){
flock($this->fp,LOCK_UN);
fclose($this->fp);
}
}
$lock=new Lock();
// simulate some processing
sleep(60);
echo "END";
?>
If you are using cURL then I believe your are using cURL to request a page such as http://domain.com/cron.php
. The machine requesting the script via cURL/wget/browser/etc has no way of knowing if the script is already being executed on the server. However, you can configure your cron.php
script to run only once:
<?php
// attempt to obtain a lock
$fp = fopen(basename(__FILE__) . ".lock", "w");
if (flock($fp, LOCK_EX | LOCK_NB) === false) {
echo basename(__FILE__) . ": already running\n";
exit(-1);
}
// code goes here
echo date("Y-m-d H:i:s") . ": cron job started\n";
sleep(30);
echo date("Y-m-d H:i:s") . ": cron job ended\n";
// release the lock
flock($fp, LOCK_UN);
fclose($fp);
The sample code uses PHP flock
function. The LOCK_EX
flag tells PHP that it needs to obtain an exclusive lock; i.e. no other process is allowed to access the file. The LOCK_NB
tells PHP that it should not block (wait for the lock to be released) and return false
immediately. Together, the two switches assure that a second process cannot lock the file while the first one has it locked.
如果我对您的理解正确,您想防止您的 cron.php 脚本被 cron 再次启动,它不是从另一个 PHP 脚本调用的吗?(在这种情况下, require_once 将是正确的答案)
据我了解,您需要存储一个指示您的脚本正在运行的标记,并在脚本末尾删除该标记。
根据您的环境,您可以创建一个小文件,即.lock
在您的数据库中存储一个 status = locked 条目。
编辑:这是一个使用文件方法的小代码示例:
<?php
// cron.php
$path = '/path/to/your/data/directory/';
if (file_exists($path . '.lock') {
die('cron.php is already running');
}
// if script reaches this point, it is not locked -> create a lock
file_put_contents($path . '.lock', 'lockfile created at ' . now());
//... your code....
//unlocking
unlink($path . '.lock');
?>
你可以只使用require_once或include_once吗?
require_once
如果无法评估文件,将抛出 PHP 致命错误(将停止执行)。
include_once
将引发 PHP 警告(可能会继续执行)。
// Require tasks.php to run once
require_once 'path/to/tasks.php';
// Attempt to run tasks.php and only once
include_once 'path/to/tasks.php';
you can use require_once
or include_once
The general syntax of both the include and require statements are as follows:
include "file_to_load.php";
include_once "file_to_load.php";
When the include_once/require_once
statements are used, the file cannot be loaded or executed multiple times. If an attempt is made to load a file twice using one of these two methods, it will be ignored. Because it is unacceptable to define the same function multiple times within a script, these functions allow the developer to include a script as needed without having to check whether it has been previously loaded.
NOTE The capability to return values from external files is limited only to the include_once
statements. The require_once
statements cannot be used in this fashion.
include_once('class.php');
php.net states
The include_once statement includes and evaluates the specified file during the execution of the script. This is a behavior similar to the include statement, with the only difference being that if the code from a file has already been included, it will not be included again. As the name suggests, it will be included just once.
您可以使用 require_once 或 include_once。
如果您对使用什么感到困惑,那么这两者之间的区别在于
require_once 将停止执行前面的代码,trwos 致命错误,如果没有找到提到的文件,所以如果你想要前面的代码继续即使文件没有找到,那么不要使用它。
其中 include_once 将继续执行前面的代码。
在这种情况下,您可以使用数据库,在数据库和第二列中输入页面以检查它是否已加载(例如,'0'
如果尚未加载并且'1'
已加载)。最初保留该行的值,因为'0'
在加载页面时将该列更新为'1'
.