这让我发疯了。我有一个标准例程来编写工作得很好的日志文件,我几乎忘记了代码中的内容。将其转移到一个新项目中,进行了一次更改,它表现得非常奇怪。错误消息表明fopen()无法打开日志文件,但条目仍在日志文件中。我不喜欢任何描述的错误或警告,所以我不打算忽略这个错误,只是因为它似乎在错误的情况下正常工作。
我所做的更改是设置$ _SESSION [' base_dir_prefix']的方式。在以前的项目中,已在主页的上下文中设置,并设置为该目录的绝对路径。这有一个弱点,你无法通过index.php直接进入页面。我在这个项目中无法做到这一点,所以我将它设置为相对路径 - 例如$ _SESSION [' base_dir_prefix'] =" ../" ;据我所知,前缀设置正确。事实上,据我所见,一切都设置正确,但显然有一根针需要另外一双眼睛才能看到!
我最大的一个问题是,如果fopen()无法打开文件,那么为什么要写入?
图表1 - 实际writelog函数的源代码。请注意,echo语句纯粹是出于调试目的而不是正常执行的一部分。
function writelog($str=" ")
{
if (isset($_SESSION['base_dir_prefix']))
{
$prepend = $_SESSION['base_dir_prefix'] ;
}
else
{
$prepend = $_SERVER['DOCUMENT_ROOT'] ;
}
if ( substr($prepend, -1, 1) <> DIRECTORY_SEPARATOR )
{
$prepend .= DIRECTORY_SEPARATOR ;
}
$fname = $prepend."log/log.txt" ;
$mode = "a" ;
echo getcwd(). "\n" ; // debug code
echo $fname." Files exists?:".file_exists($fname) ."\n";
echo $str."\n" ;
$fp = fopen($fname, $mode) ;
fwrite( $fp, date("Y-m-d H:i:s").": " ) ;
fwrite( $fp, $str."\n" ) ;
fclose( $fp ) ;
}
图表2 - 调用函数的代码
$u->writelog ("SA OLU entering Option List Users function") ;
$u->writelog ("Current dir:".getcwd()." ") ;
$usr_list = array(array( "None", "None") );
$sc->user_list($usr_list) ;
$i = 0 ;
$res = "" ;
$actv_flag = strtoupper($active) ;
if ($usr_list[0][0] != "None" )
{
while ($i < count($usr_list))
{
if ((bool)$usr_list[$i][2] == true && $actv_flag == "YES") //only active users
{
$i++ ;
continue ;
}
$res .= sprintf( "<option value=\"%s\"> %s (%s) </option> \n",
$usr_list[$i][0],
$usr_list[$i][1],
$usr_list[$i][0]
);
$i++ ;
}
} else
{
$res = sprintf( "<option value=\"no_recs\"> No Program Records </option> \n" ) ;
}
$u->writelog ("SA OLU leaving Option List Users function") ;
图表3 - 日志文件本身。由展览创建的条目1.请注意,此文件的时间戳比实际时间晚1小时。不知道为什么,因为我是唯一一个看过这个文件的人,所以我并没有过分担心。
2014-11-21 16:29:58: SA OLU entering Option List Users function
2014-11-21 16:29:58: Current dir:/srv/www/dev/gillies/security
2014-11-21 16:29:58: SA OLU leaving Option List Users function
2014-11-21 16:29:58: SA OLU entering Option List Users function
2014-11-21 16:29:58: Current dir:/srv/www/dev/gillies/security
2014-11-21 16:29:58: SA OLU leaving Option List Users function
2014-11-21 16:29:58: SA OLU entering Option List Users function
2014-11-21 16:29:58: Current dir:/srv/www/dev/gillies/security
2014-11-21 16:29:58: SA OLU leaving Option List Users function
图表4 - Apache错误日志文件
[Fri Nov 21 15:29:25.047732 2014] [:error] [pid 20588] [client 192.168.0.19:62116] PHP Warning: fwrite() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 72
[Fri Nov 21 15:29:25.047746 2014] [:error] [pid 20588] [client 192.168.0.19:62116] PHP Warning: fclose() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 73
[Fri Nov 21 15:29:58.721627 2014] [:error] [pid 17084] [client 192.168.0.19:62141] PHP Warning: fopen(../log/log.txt): failed to open stream: No such file or directory in /srv/www/dev/gillies/php/utilities.php on line 69
[Fri Nov 21 15:29:58.721698 2014] [:error] [pid 17084] [client 192.168.0.19:62141] PHP Warning: fwrite() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 71
[Fri Nov 21 15:29:58.721711 2014] [:error] [pid 17084] [client 192.168.0.19:62141] PHP Warning: fwrite() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 72
[Fri Nov 21 15:29:58.721720 2014] [:error] [pid 17084] [client 192.168.0.19:62141] PHP Warning: fclose() expects parameter 1 to be resource, boolean given in /srv/www/dev/gillies/php/utilities.php on line 73
图表5 - 生成的html代码片段,显示回显的结果。图表2创建的条目。这仅用于诊断目的,不属于生产文件。
</h4><select name="users" size="5">
/srv/www/dev/gillies/security
../log/log.txt Files exists?:1
SA OLU entering Option List Users function
/srv/www/dev/gillies/security
../log/log.txt Files exists?:1
Current dir:/srv/www/dev/gillies/security
/srv/www/dev/gillies/security
../log/log.txt Files exists?:1
SA OLU leaving Option List Users function
<option value="loginid"> name (loginid) </option>
图表6 - 日志文件的目录结构
darryl@thedoctor:/srv/www/dev/gillies/log$ pwd
/srv/www/dev/gillies/log
darryl@thedoctor:/srv/www/dev/gillies/log$ ls -l
total 8
-rw-rw-rw- 1 www-data www-data 4743 Nov 21 15:33 log.txt
有人提出任何线索吗? 感谢。
答案 0 :(得分:1)
我找到了答案,它是在提供给fopen()的相对路径中。我重写了代码来创建一个绝对而不是相对的前缀,并且所有错误都消失了。我需要做一些字符串操作才能获得正确的目录,新代码现在看起来像这样:
$here = getcwd() ;
$posn = strrpos($here, "/") ;
if($posn === false) {
$_SESSION['base_dir_prefix'] = "../" ;
}
else {
$_SESSION['base_dir_prefix'] = substr($here, 0, $posn) ;
}
感谢Darren的想法。我一直在试图弄清楚还有什么可以尝试。
新代码获取层次结构中第二级目录的绝对路径,并将路径修剪回一级,使其指向文档根目录。
对于那些可能想知道为什么所有这些麻烦来获取目录的人来说,这使代码完全可重定位。当网站进入开发,测试,验收和生产阶段时,无法保证文档根目录与Web服务器文档根目录处于同一级别。这允许将网站放在目录层次结构中的任何位置,而不必更改对文件等的引用。