该脚本应该使用文件锁等写入日志文件,以确保同时运行的脚本没有任何读/写并发症。我从 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 循环中时启动脚本的第二个实例,则第二个脚本将声明它与第一个脚本同时启动。