致命错误 php

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1142096/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 01:12:45  来源:igfitidea点击:

Fatal error php

phperror-handling

提问by Granit

Is there a way to make the code continue (not exit) when you get a fatal error in PHP? For example I get a timeout fatal error and I want whenever it happens to skip this task and the continue with others. In this case the script exits.

当您在 PHP 中遇到致命错误时,有没有办法让代码继续(而不是退出)?例如,我收到一个超时致命错误,我希望每当它碰巧跳过此任务并继续执行其他任务时。在这种情况下,脚本退出。

回答by Greg

There is a hack using output buffering that will let you log certain fatal errors, but there's no way to continue a script after a fatal error occurs - that's what makes it fatal!

有一个使用输出缓冲的技巧,可以让您记录某些致命错误,但是在发生致命错误后无法继续执行脚本 - 这就是它致命的原因!

If your script is timing out you can use set_time_limit()to give it more time to execute.

如果您的脚本超时,您可以使用set_time_limit()它来给它更多时间来执行。

回答by Pascal MARTIN

"Fatal Error", as it's name indicates, is Fatal : it stop the execution of the script / program.

顾名思义,“致命错误”是致命的:它停止执行脚本/程序。

If you are using PHP to generate web pages and get a Fatal error related to max_execution_timewhich, by defaults, equals 30 seconds, you are certainly doing something that really takes too mych time : users won't probably wait for so long to get the page.

如果您正在使用 PHP 生成网页并获得与max_execution_time默认情况下等于 30 秒相关的致命错误,那么您肯定正在做一些真正需要太多时间的事情:用户可能不会等待这么长时间才能获得该页面.

If you are using PHP to do some heavy calculations, not in a webpage (but via CLI, or a cron, or stuff like that), you can set another (greater)value for max_execution_time. You have two ways of doing that :

如果您使用的是PHP做一些繁重的计算,而不是在一个网页(但可通过CLI或一个cron或者类似的东西),你可以设置其他(较大)的价值max_execution_time。你有两种方法可以做到这一点:

First is to modify php.ini, to set this value (it's already in the file ; just edit the property's value). Problem is it'll modify it also for the web server, which is bad (this is a security measure, after all). Better way is to create a copy of php.ini, called, for instance, phpcli.ini, and modify this file. Then, use it when invoking php :

首先是修改php.ini,设置这个值(它已经在文件中;只需编辑属性的值)。问题是它也会为 Web 服务器修改它,这很糟糕(毕竟这是一种安全措施)。更好的方法是创建 php.ini 的副本,例如,名为 phpcli.ini,并修改此文件。然后,在调用 php 时使用它:

php -c phpcli.ini myscript.php

This'll work great if you have many properties you need to configure for CLI execution. (Like memory_limit, which often has to be set to a higher value for long-running batches)

如果您需要为 CLI 执行配置许多属性,这将非常有用。(例如memory_limit,对于长时间运行的批次,通常必须将其设置为更高的值)

The other way is to define a different value for max_execution_timewhen you invoke php, like this :

另一种方法是max_execution_time在调用 php 时定义不同的值,如下所示:

php -d max_execution_time=60 myscript.php

This is great if you launch this via the crontab, for instance.

例如,如果您通过 crontab 启动它,那就太好了。

回答by DespairTyre

If you have a suitable PHP version (PHP>=5.2 for error_get_last) you can try the technique described herewhich uses register_shutdown_function and error_get_last.

如果您有合适的 PHP 版本(对于 error_get_last,PHP>=5.2),您可以尝试使用此处描述的使用 register_shutdown_function 和 error_get_last 的技术。

This won't allow you to "continue" when you get a fatal error, but it at least allows you to log the error (and perhaps send a warning email) before displaying a custom error page to the user.

这将不允许您在遇到致命错误时“继续”,但它至少允许您在向用户显示自定义错误页面之前记录错误(并可能发送警告电子邮件)。

It works something like this:

它的工作原理是这样的:

function fatalErrorHandler()
{
    $lastError = error_get_last();
    if (isset($lastError["type"]) && $lastError["type"]==E_ERROR) {
      // do something with the fatal error
    }
}
...
register_shutdown_function('fatalErrorHandler');


A few points:


几点:

  • you can use ob_clean() to remove any content that was generated prior to the fatal error.
  • it's a reallybad idea to do anything to intensive in the shutdown handler, this technique is about graceful failure rather than recovery.
  • whatever you do, don't try to log the error to a database ... what if it was a database timeout that caused the fatal error?
  • for some reason I've had problems getting this technique to work 100% of the time when developing in Windows using WAMP.
  • 您可以使用 ob_clean() 删除在致命错误之前生成的任何内容。
  • 在关闭处理程序中做任何密集的事情是一个非常糟糕的主意,这种技术是关于优雅的失败而不是恢复。
  • 无论您做什么,都不要尝试将错误记录到数据库中……如果是数据库超时导致了致命错误怎么办?
  • 出于某种原因,在使用 WAMP 在 Windows 中进行开发时,我遇到了让这种技术 100% 工作的问题。

回答by Sander Marechal

It depends on the exact error type. You can catch errors by creating your own error handler. See the documentation on set_error_handler(), but not all types of errors can be caught. Look at the timeout error you get and see what type it is. If it is one of E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR or E_COMPILE_WARNING then you cannot catch it with an error handler. If it another type then you can. Catch it with the error handler and simply return.

这取决于确切的错误类型。您可以通过创建自己的错误处理程序来捕获错误。请参阅有关set_error_handler()的文档,但并非所有类型的错误都可以捕获。看看你得到的超时错误,看看它是什么类型。如果它是 E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR 或 E_COMPILE_WARNING 之一,那么你不能用错误处理程序捕获它。如果它是另一种类型,那么你可以。使用错误处理程序捕获它并简单地返回。

回答by Granit

Is there a way then to limit the execution time of an function but not all script? For example

那么有没有办法限制函数的执行时间而不是所有脚本的执行时间?例如

function blabla()
{
return "yes";
}

to make it so that if it is not executed in 25 seconds to return no;

使其在 25 秒内未执行时返回 no;

回答by andho

The most simple answer I can give you is this function: http://php.net/manual/en/function.pcntl-fork.php

我可以给你的最简单的答案是这个函数:http: //php.net/manual/en/function.pcntl-fork.php

In more detail, what you can do is:

更详细地说,您可以做的是:

  • Fork the part of the process you think might or might not cause a fatal error (i.e. the bulk of your code)
  • The script that forks the process should be a very simple script.
  • 分叉您认为可能会或可能不会导致致命错误的流程部分(即大部分代码)
  • fork 进程的脚本应该是一个非常简单的脚本。

For example this is something that I would do with a job queue that I have:

例如,这是我对我拥有的作业队列所做的事情:

<?php
// ... load stuff regarding the job queue

while ($job = $queue->getJob()) {
    $pid = pcntl_fork();
    switch ($pid) {
        case -1:
            echo "Fork failed";
            break;
        case 0:
            // do your stuff here
            echo "Child finished working";
            break;
        default:
            echo "Waiting for child...";
            pcntl_wait($status);
            // check the status using other pcntl* functions if you want
            break;
    }
}