为什么fopen在注册关闭功能中失败? [英] Why does fopen fail within a register shutdown function?

查看:142
本文介绍了为什么fopen在注册关闭功能中失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在共享主机中的一个站点上工作。我无法访问PHP ini文件或PHP ini_set 函数,而且我无法使用 php_flag php_value 指令。



我使用 set_error_handler 函数来记录大多数错误,并尝试使用 register_shutdown_function 记录致命的。我已经尝试了几个解决方案来捕获致命错误:如何我遇到一个PHP致命错误
。我可以成功地使用这里的解决方案来显示屏幕上的错误或打开自定义错误页面,并记录非致命错误,但我似乎无法记录致命错误。



这是我尝试的最简单的版本:

  function errorHandler $ num,$ str,$ file,$ line){

$ now = strftime(%B%d,%Y at%I:%M%p,time());
$ text ={$ now}→{$ file} {{$}} {{$}} {{}
$ errorlog =my_path / my_log;

$ new = file_exists($ errorlog)?假:真
if($ handle = fopen($ errorlog,'a')){
fwrite($ handle,$ text);
fclose($ handle);
if($ new){chmod($ errorlog,0755); }
} else {
print(无法打开日志文件进行写入); //我正在使用它来测试
}

}

函数fatalHandler(){
$ error = error_get_last();
if($ error){
errorHandler($ error [type],$ error [message],$ error [file],$ error [line]);
}
}

set_error_handler(errorHandler);
register_shutdown_function(fatalHandler);

当我使用非致命错误进行测试时,如 echo $ undefined_variable ,它的工作原理和错误记录正确。但是,如果我测试一个致命的错误,如 undefined_function(),它不记录任何内容,打印无法打开日志文件。如果我测试了两个错误,它记录非致命的,但不是致命的。



您的问题已被确定为可能的副本另一个问题。如果答案没有解决您的问题,请编辑以详细解释问题的部分是唯一的。



@Vic Seedoubleyew-Well,最明显的一点是,你提到的问题提到的无法打开流:...等... / code>与我的情况无关。那个警告从未发生过。测试消息:无法打开日志文件进行写入是我自己我自己写的消息,所以我有一些证据表明 if 语句正在处理中。我发出了这个消息。我的问题很清楚地注意到,这个消息是我自己做的。任何遇到问题的人都永远不会收到消息无法打开流...等,所以他们不会帮助解决他们从未得到的消息的问题。我假设这一切都是为了真正帮助像我这样的虚拟人物。



标题:为什么 fopen 在注册关闭功能中失败不是我的标题。那是别人的编辑。我的问题是为什么我无法写入 register_shutdown_function 中的日志。我不知道 fopen 是否失败或还有其他问题。我正在尝试从功能中记录某些东西,它不工作。从问题中删除规定的目标(注销功能),并添加别人的评估为什么 fopen 失败,实际上对于任何人来说都不太有用以解决我遇到的情况。如果已经有一个问题出现了,在关闭功能中写入一个文件,我会发现它。 为什么 fopen fail太具体,无法在不知道为什么不能写入函数中的文件的人的搜索中有用。



我不会对编辑发表任何意见,但是由于您要求我解释,我正在解释。我意识到每个人都可能得到点数进行编辑,但是请花一点时间来考虑你的编辑对这个问题的有用性的影响。

解决方案

您是否使用自定义错误日志的相对路径?如果是,请参阅 register_shutdown_function 页面可能是相关的:


脚本的工作目录可以在某些Web服务器的关闭功能内部更改,例如Apache的。


其实第二个评论说:


如果要使用register_shutdown_function()中注册的功能中的文件执行某些操作,请使用ABSOLUTE路径到文件而不是relative。因为脚本处理完成当前工作目录到ServerRoot(请参阅httpd.conf)


其他事情我会提到: p>

您的变量 $ error ,逻辑 if($ error){... 有误导性。请注意,当您使用 register_shutdown_function 注册一个函数时,您会告诉PHP每次您的脚本完成执行时都调用该函数,无论是否没有错误。这意味着即使您的脚本以非致命错误完成,甚至没有任何错误也可以调用 fatalHandler



由于您有一种处理非致命错误的替代方法(使用 set_error_handler ),您应该具体检查致命错误 code> fatalHandler

  function fatalHandler(){
if($错误!== NULL&& $错误['type'] == E_ERROR){
errorHandler($ error [type],$ error [message],$ error [file] ,$ error [line]);
标头(HTTP / 1.1 500内部服务器错误);
exit();
}
}

查看PHP错误级别列表 here



你可能不会意识到这一点,但是PHP有一个内置的错误记录功能 。默认情况下,它写入 php.ini 中为 error_log 指定的文件。



如果您对更高级的日志记录感兴趣,并且通常将您的PHP-fu提升到一个新的水平,我建议您查看 Monolog 包。它或多或少被认为是登录专业PHP社区的通用标准。


I am working on a site in a shared host. I don't have access to the PHP ini file, or the PHP ini_set function, and I can't use php_flag or php_value directives.

I'm using the set_error_handler function to log most errors, and trying to use the register_shutdown_function to log fatal ones. I've tried several of the solutions for catching fatal errors here: How do I catch a PHP Fatal Error . I can successfully use the solutions there to either display the errors on screen or bring up a custom error page, and to log non-fatal errors, but I can't seem to log the fatal errors.

This is simplest version of my attempts:

    function errorHandler($num, $str, $file, $line) {

        $now        = strftime("%B %d, %Y at %I:%M %p", time());
        $text       = "{$now} → error {$num} in {$file}, line {$line}: {$str}\n";
        $errorlog   = "my_path/my_log";

        $new        = file_exists($errorlog) ? false : true;
        if($handle  = fopen($errorlog, 'a')) {
            fwrite($handle, $text);
            fclose($handle);
            if($new) { chmod($errorlog, 0755); }
        } else {
            print("Could not open log file for writing"); //I'm using this to test
        }

    }

    function fatalHandler() {
        $error  = error_get_last();
        if($error) {
            errorHandler($error["type"], $error["message"], $error["file"], $error["line"]);
        }
    }

    set_error_handler("errorHandler");
    register_shutdown_function("fatalHandler");    

When I test this with a non-fatal error, like echo $undefined_variable, it works and the error is logged properly. However if I test with a fatal error, like undefined_function(), it does not log anything and prints "could not open log file". If I test with both errors present, it logs the non-fatal one, but not the fatal one.

Your question has been identified as a possible duplicate of another question. If the answers there do not address your problem, please edit to explain in detail the parts of your question that are unique.

@Vic Seedoubleyew -Well, the most obvious thing is the warning addressed in the question you mentioned failed to open stream: ...etc has nothing to do with my situation. That warning never happened. The test message: "could not open log file for writing" is my own message that I wrote to myself, so I would have some evidence that the if statement was being processed. I made that message up. It's noted very clearly in my question that the message is of my own making. Anyone experiencing the problem I was will never get the message failed to open stream...etc, so they won't be helped by a question addressing a message they never got. I assume the point of all this is to actually help dummies like me.

The title: "Why does fopen fail within a register shutdown function" was not my title. That is someone else's edit. My question was why I couldn't write to a log within the register_shutdown_function. I didn't know whether fopen was failing or there was some other problem. I was trying to log something out of the function and it wasn't working. Removing the stated goal (logging out of the function) from the question, and adding someone else's assessment "why does fopen fail", actually makes it much less useful to anyone coming here for a solution to the situation I was experiencing. Had there already been a question present which addressed writing to a file within the shutdown function, I would have found it. "Why does fopen fail" is too specific to be useful in a search by someone who doesn't know why they can't write to a file in the function.

I wasn't going to say anything about the edit, but since you have asked me to explain, I'm explaining. I realize everyone probably gets points for edits, but take a minute to consider the effect your edit has on the usefulness of the question to someone who comes here with the situation I had.

解决方案

Are you using a relative path to your custom error log? If so, this note on the register_shutdown_function page might be relevant:

Working directory of the script can change inside the shutdown function under some web servers, e.g. Apache.

In fact, the second comment says:

If you want to do something with files in function, that registered in register_shutdown_function(), use ABSOLUTE paths to files instead of relative. Because when script processing is complete current working directory chages to ServerRoot (see httpd.conf)

Other things I'll mention:

Your variable $error, and the logic if ($error) { ... is misleading. See, when you register a function using register_shutdown_function, you are telling PHP to invoke that function every single time your script finishes executing - regardless of whether or not there was an error. This means that fatalHandler is invoked even when your script finishes with a non-fatal error, or even no error at all!

Since you have an alternative method for dealing with non-fatal errors (using set_error_handler), you should specifically check for fatal errors in fatalHandler:

function fatalHandler() {
    if( $error !== NULL && $error['type'] == E_ERROR) {
        errorHandler($error["type"], $error["message"], $error["file"], $error["line"]);
        header("HTTP/1.1 500 Internal Server Error");
        exit();
    }
}

See the list of PHP error levels here.

You may not be aware of this, but PHP has a built-in error-logging function. By default, it writes to the file specified for error_log in your php.ini.

If you are interested in more advanced logging, and generally taking your PHP-fu to the next level, I suggest looking into the Monolog package. It is more or less considered the universal standard for logging in professional PHP communities.

这篇关于为什么fopen在注册关闭功能中失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆