0

该脚本应该使用文件锁等写入日志文件,以确保同时运行的脚本没有任何读/写并发症。我从 php.net 上的某个人那里得到了它。当我尝试同时运行它两次时,我注意到它完全忽略了锁定文件。但是,当我连续运行它们时,锁定文件工作得很好。

这没有任何意义。该脚本仅检查文件是否存在,并据此采取行动。另一个脚本是否正在运行,根本不应该影响它。我仔细检查以确保在这两种情况下都创建了锁定文件;它是。

所以我开始做一些测试。

第一个实例从11:21:00输出开始:

Started at: 2012-04-12 11:21:00 
Checking if weblog/20120412test.txt.1.wlock exists
Got lock: weblog/20120412test.txt.1.wlock
log file not exists, make new
log file was either appended to or create anew
Wrote: 2012-04-12 11:21:00 xx.xx.xx.xxx "testmsg" 
1

第二个实例从11:21:03输出开始:

Started at: 2012-04-12 11:21:00 
Checking if weblog/20120412test.txt.1.wlock exists
Got lock: weblog/20120412test.txt.1.wlock
log file not exists, make new
log file was either appended to or create anew
Wrote: 2012-04-12 11:21:00 xx.xx.xx.xxx "testmsg" 
1

所以这里有两件事是错误的。时间戳和脚本说锁定文件的事实不存在,即使它肯定存在。

几乎就像脚本的第二个实例只是输出第一个实例所做的一样。

<?php
function Weblog_debug($input)
{
    echo $input."<br/>";
}
function Weblog($directory, $logfile, $message)
{
    // Created 15 september 2010: Mirco Babin
    $curtime = time();

    $startedat = date('Y-m-d',$curtime) . "\t" . date('H:i:s', $curtime) .  "\t";
    Weblog_debug("Started at: $startedat");

    $logfile = date('Ymd',$curtime) . $logfile;

    //Set directory correctly
    if (!isset($directory) || $directory === false)
    $directory = './';
    if (substr($directory,-1) !== '/')
    $directory = $directory . '/';

    $count = 1;
    while(1)
    {
        //*dir*/*file*.*count*
        $logfilename = $directory . $logfile . '.' . $count;

        //*dir*/*file*.*count*.lock
        $lockfile = $logfilename . '.wlock';
        $lockhandle = false;
        Weblog_debug("Checking if $lockfile exists");
        if (!file_exists($lockfile))
        {
            $lockhandle = @fopen($lockfile, 'xb'); //lock handle true if lock file opened
            Weblog_debug("Got lock: $lockfile");
        }
        if ($lockhandle !== false) break; //break loop if we got lock

        $count++;
        if ($count > 100) return false;
    }

    //log file exists, append
    if (file_exists($logfilename))
    {
        Weblog_debug("log file exists, append");
        $created   = false;
        $loghandle = @fopen($logfilename, 'ab');
    }
    //log file not exists, make new
    else
    {
        Weblog_debug("log file not exists, make new");
        $loghandle = @fopen($logfilename, 'xb');
        if ($loghandle !== false) //Did we make it?
        {
            $created = true;

            $str = '#version: 1.0' . "\r\n" .
            '#Fields: date time c-ip x-msg' . "\r\n";
            fwrite($loghandle,$str);
        }
    }

    //was log file either appended to or create anew?
    if ($loghandle !== false)
    {
        Weblog_debug("log file was either appended to or create anew");
        $str = date('Y-m-d',$curtime) . "\t" . 
        date('H:i:s', $curtime) .  "\t" .
        (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '-') . "\t" .
        '"' . str_replace('"', '""', $message) . '"' . "\r\n";
        fwrite($loghandle,$str);

        Weblog_debug("Wrote: $str");

        fclose($loghandle);
        //Only chmod if new file
        if ($created) chmod($logfilename,0644); // Read and write for owner, read for everybody else

        $result = true;
    }
    else
    {
        Weblog_debug("log file was not appended to or create anew");
        $result = false;
    }

    /**
    Sleep & disable unlinking of lock file, both for testing purposes.
    */
    //Sleep for 10sec to allow other instance(s) of script to run while this one still in progress.
    sleep(10);
    //fclose($lockhandle);
    //@unlink($lockfile);

    return $result;
}

echo Weblog("weblog", "test.txt", "testmsg");
?>

更新:

这是一个仅显示时间戳的简单脚本。我在不同的主机上尝试过,所以我认为这不是我的服务器的问题;

<?php
function Weblog_debug($input)
{
    echo $input."<br/>";
}
$curtime = time();
$startedat = date('Y-m-d',$curtime) . "\t" . date('H:i:s', $curtime) .  "\t";
Weblog_debug("Started at: $startedat");

$timediff = time() - $curtime;
while($timediff < 5)
{
    $timediff = time() - $curtime;
}

Weblog_debug("OK");
?>

同样,如果我在第一个脚本在 while 循环中时启动脚本的第二个实例,则第二个脚本将声明它与第一个脚本同时启动。

4

1 回答 1

0

我自己都不敢相信,但事实证明这只是 Opera 中的一个“功能”。该脚本在 Firefox 中按预期工作。我有点希望在我全力以赴之前测试一下,但是你去吧。

于 2012-04-13T14:34:53.010 回答