1

我有一个带有 PHP 的 cronjob 系统。我有一个名为 cron.php 的文件,想检查它是否未加载,请加载它。对我来说非常重要的是这个文件只运行一次,我需要定义它已经运行的方式。我不能使用任何系统功能,如 exec,system,... 你有什么解决方案吗?

注意:我通过 CURL 运行我的脚本,并且 include_one 和 require_once 不适用于这种情况。

4

9 回答 9

7

您可以使用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";
?>
于 2012-05-08T08:06:32.427 回答
2

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.

于 2012-05-08T08:23:09.223 回答
2

您的问题本质上等同于“检查 php 脚本是否仍在运行”

请参考这里

检查 php 脚本是否仍在运行

于 2012-05-08T07:35:42.913 回答
2

如果我对您的理解正确,您想防止您的 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');
?>
于 2012-05-08T07:36:31.970 回答
2

你可以只使用require_onceinclude_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';
于 2012-05-08T07:24:45.193 回答
1

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.

于 2012-05-08T07:29:43.090 回答
1
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.

于 2012-05-08T07:29:56.703 回答
0

您可以使用 require_once 或 include_once。

如果您对使用什么感到困惑,那么这两者之间的区别在于

require_once 将停止执行前面的代码,trwos 致命错误,如果没有找到提到的文件,所以如果你想要前面的代码继续即使文件没有找到,那么不要使用它。

其中 include_once 将继续执行前面的代码。

于 2012-05-08T07:31:40.030 回答
0

在这种情况下,您可以使用数据库,在数据库和第二列中输入页面以检查它是否已加载(例如,'0'如果尚未加载并且'1'已加载)。最初保留该行的值,因为'0'在加载页面时将该列更新为'1'.

于 2012-05-08T08:18:06.037 回答