web-dev-qa-db-ja.com

エラー時にバックトレースを生成するには、どうすればPHPを取得できますか?

デフォルトの現在の行のみのエラーメッセージを使用してPHPをデバッグしようとするのは恐ろしいことです。エラーが発生したときに、PHPを取得してバックトレース(スタックトレース)を生成するにはどうすればよいですか?

48
chaos

Xdebug エラー時にバックトレーステーブルを出力します。これを実装するためにPHPコードを記述する必要はありません。

マイナス面は、PHP拡張機能としてインストールする必要があることです。

45
patcoll

バックトレースを生成するエラーハンドラーをインストールするための私のスクリプト:

<?php
function process_error_backtrace($errno, $errstr, $errfile, $errline, $errcontext) {
    if(!(error_reporting() & $errno))
        return;
    switch($errno) {
    case E_WARNING      :
    case E_USER_WARNING :
    case E_STRICT       :
    case E_NOTICE       :
    case E_USER_NOTICE  :
        $type = 'warning';
        $fatal = false;
        break;
    default             :
        $type = 'fatal error';
        $fatal = true;
        break;
    }
    $trace = array_reverse(debug_backtrace());
    array_pop($trace);
    if(php_sapi_name() == 'cli') {
        echo 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ':' . "\n";
        foreach($trace as $item)
            echo '  ' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()' . "\n";
    } else {
        echo '<p class="error_backtrace">' . "\n";
        echo '  Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ':' . "\n";
        echo '  <ol>' . "\n";
        foreach($trace as $item)
            echo '    <li>' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()</li>' . "\n";
        echo '  </ol>' . "\n";
        echo '</p>' . "\n";
    }
    if(ini_get('log_errors')) {
        $items = array();
        foreach($trace as $item)
            $items[] = (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()';
        $message = 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ': ' . join(' | ', $items);
        error_log($message);
    }
    if($fatal)
        exit(1);
}

set_error_handler('process_error_backtrace');
?>

警告:Zendは、さまざまな 'PHP致命的エラー' に影響を与えることはできません。Zendの判断では、これらはset_error_handler()を無視すると判断したためです。そのため、これらを使用しても、最終的な場所のみの無駄なエラーが発生します。

47
chaos

PHPエラー

これは、PHPで記述されたPHPのエラーレポートです。追加の拡張機能は不要です!

通常のAJAXy要求(一時停止状態)ですべてのエラーがブラウザーに表示される場所を使用するのは簡単です。すべてのエラーは、関数引数、サーバー変数を含むスタックトレース全体にわたるバックトレースとコードコンテキストを提供します。

あなたがする必要があるのは、単一のファイルをインクルードし、関数を(コードの先頭で)呼び出すことです。

_require('php_error.php');
\php_error\reportErrors();
_

スクリーンショットをご覧ください:

PHP Error | Improve Error Reporting for PHP - screenshot of backtracePHP Error | Improve Error Reporting for PHP - screenshot of backtracePHP Error | Improve Error Reporting for PHP - screenshot of backtrace

GitHub: https://github.com/JosephLenton/PHP-Error

私のフォーク(追加の修正あり): https://github.com/kenorb-contrib/PHP-Error

PHPのデバッグ クラス

完全なPHPデバッガークラス。例外、エラー、アラート(ユーザーから)、コード行、ハイライトフラグをサポートしています。

使用例:

_ <?php
        include( dirname(dirname(__FILE__))  . '/src/Debug.php' );
        //Catch all
        Debug::register();

        //Generate an errors
        if( this_function_does_not_exists( ) )
        {
            return false;
        }
    ?>
_

PHPでのエラー処理

以下の例は、エラーをトリガーし、ユーザー定義関数でエラーを処理することによる内部例外の処理を示しています。

より短い方法(PHP):

_<?php
function e($number, $msg, $file, $line, $vars) {
   print_r(debug_backtrace());
   die();
}
set_error_handler('e');
_

長い道のり(PHP):

_// set to the user defined error handler
$old_error_handler = set_error_handler("myErrorHandler");

// error handler function
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
    if (!(error_reporting() & $errno)) {
        // This error code is not included in error_reporting
        return;
    }

    switch ($errno) {
    case E_USER_ERROR:
        echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
        echo "  Fatal error on line $errline in file $errfile";
        echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
        echo "Aborting...<br />\n";
        var_dump(debug_backtrace());
        exit(1);
        break;

    case E_USER_WARNING:
        echo "<b>My WARNING</b> [$errno] $errstr<br />\n";
        break;

    case E_USER_NOTICE:
        echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";
        break;

    default:
        echo "Unknown error type: [$errno] $errstr<br />\n";
        break;
    }

    /* Don't execute PHP internal error handler */
    return true;
}
_

参照: http://www.php.net/manual/en/function.set-error-handler.php

注:一度に1つのエラー例外のみを持つことができます。 set_error_handler()関数を呼び出すと、古いエラーハンドラーの名前が返されます。これを保存して、エラーハンドラから自分で呼び出すことができます。これにより、複数のエラーハンドラを持つことができます。


XDebug

より高度なソリューションについては、PHPの XDebug 拡張機能を使用できます。

デフォルトでは、XDebugがロードされると、致命的なエラーが発生した場合に自動的にバックトレースが表示されます。または、ファイル(xdebug.auto_trace)にトレースして、要求全体の非常に大きなバックトレースを取得するか、プロファイリング(xdebug.profiler_enable)または その他の設定 を実行します。トレースファイルが大きすぎる場合は、xdebug_start_trace()およびxdebug_stop_trace()を使用して部分的なトレースをダンプできます。

インストール

PECLの使用:

_pecl install xdebug
_

Linuxの場合:

_Sudo apt-get install php5-xdebug
_

Mac(Homebrewを使用)の場合:

_brew tap josegonzalez/php
brew search xdebug
php53-xdebug
_

鉱山構成の例:

_[xdebug]

; Extensions
extension=xdebug.so
; zend_extension="/YOUR_PATH/php/extensions/no-debug-non-zts-20090626/xdebug.so"
; zend_extension="/Applications/MAMP/bin/php/php5.3.20/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so" ; MAMP

; Data
xdebug.show_exception_trace=1       ; bool: Show a stack trace whenever an exception is raised.
xdebug.collect_vars = 1             ; bool: Gather information about which variables are used in a certain scope.
xdebug.show_local_vars=1            ; int: Generate stack dumps in error situations.
xdebug.collect_assignments=1        ; bool: Controls whether Xdebug should add variable assignments to function traces.
xdebug.collect_params=4             ; int1-4: Collect the parameters passed to functions when a function call is recorded.
xdebug.collect_return=1             ; bool: Write the return value of function calls to the trace files.
xdebug.var_display_max_children=256 ; int: Amount of array children and object's properties are shown.
xdebug.var_display_max_data=1024    ; int: Max string length that is shown when variables are displayed.
xdebug.var_display_max_depth=3      ; int: How many nested levels of array/object elements are displayed.
xdebug.show_mem_delta=0             ; int: Show the difference in memory usage between function calls.

; Trace
xdebug.auto_trace=0                 ; bool: The tracing of function calls will be enabled just before the script is run.
xdebug.trace_output_dir="/var/log/xdebug" ; string: Directory where the tracing files will be written to.
xdebug.trace_output_name="%H%R-%s-%t"     ; string: Name of the file that is used to dump traces into.

; Profiler
xdebug.profiler_enable=0            ; bool: Profiler which creates files read by KCacheGrind.
xdebug.profiler_output_dir="/var/log/xdebug"  ; string: Directory where the profiler output will be written to.
xdebug.profiler_output_name="%H%R-%s-%t"      ; string: Name of the file that is used to dump traces into.
xdebug.profiler_append=0            ; bool: Files will not be overwritten when a new request would map to the same file.

; CLI
xdebug.cli_color=1                  ; bool: Color var_dumps and stack traces output when in CLI mode.

; Remote debugging
xdebug.remote_enable=off            ; bool: Try to contact a debug client which is listening on the Host and port.
xdebug.remote_autostart=off         ; bool: Start a remote debugging session even GET/POST/COOKIE variable is not present.
xdebug.remote_handler=dbgp          ; select: php3/gdb/dbgp: The DBGp protocol is the only supported protocol.
xdebug.remote_Host=localhost        ; string: Host/ip where the debug client is running.
xdebug.remote_port=9000             ; integer: The port to which Xdebug tries to connect on the remote Host.
xdebug.remote_mode=req              ; select(req,jit): Selects when a debug connection is initiated.
xdebug.idekey="xdebug-cli"          ; string: IDE Key Xdebug which should pass on to the DBGp debugger handler.
xdebug.remote_log="/var/log/xdebug.log" ; string: Filename to a file to which all remote debugger communications are logged.
_

Drupal 6&7

Develを有効にした場合:

_/**
 * Implements hook_watchdog().
 */
function foo_watchdog($log_entry) {
  if ($log_entry['type'] == 'php' && $log_entry['severity'] <= WATCHDOG_WARNING) {
    function_exists('dd') && dd(debug_backtrace());
  }
}
_

上記の関数は、各エラーのバックトレースを一時ファイル(デフォルトでは_/tmp/drupal_debug.txt_)に記録します。

または、drush eval "echo file_directory_temp() . '/drupal_debug.txt'でファイルを見つけます。

Develが有効になっていない場合は、var_dump(debug_backtrace());の代わりにdd()のオールドスクールアプローチを使用します。

27
kenorb

問題のある行でdebug_backtrace()の内容を含むセッション変数を設定してから、register_shutdown_function()を使用して出力しようとしました。魅力のように働いた。

7
Tim

debug_backtrace を使用できます

3
Mythica

PHPデバッグ拡張機能として、 Xdebug および PHP DBG があります。それぞれに長所と短所があります。

2
T0xicCode

これがあなたのやり方です:

set_error_handler(function($errorType){
    if(error_reporting() & $errorType){
        ?><pre><?
        debug_print_backtrace();
        ?></pre><?
    }
}) ;

クロージャーを使用するため、PHP 5.3+が必要です。下部のPHPサポートが必要な場合は、クロージャーを通常の関数に変換するだけです。

2
GetFree
$backtrace = debug_backtrace();

バックトレースに関する小さな記事 しばらく前に書いた

1
smoove

set_error_handler() + debug_backtrace() + debug_print_backtrace() PHP5で

1

デバッガをインストールできない場合、この関数を使用して致命的なエラーを回避し、「致命的なスタック」を取得します。使用方法をよりよく説明する以下のコードと例を確認してください。

// Give an extra parameter to the filename
// to save multiple log files
function _fatalog_($extra = false)
{
    static $last_extra;

    // CHANGE THIS TO: A writeable filepath in your system...
    $filepath = '/var/www/html/sites/default/files/fatal-'.($extra === false ? $last_extra : $extra).'.log';

    if ($extra===false) {
        unlink($filepath);
    } else {
        // we write a log file with the debug info
        file_put_contents($filepath, json_encode(debug_backtrace()));
        // saving last extra parameter for future unlink... if possible...
        $last_extra = $extra;
    }
}

以下に使用方法の例を示します。

// A function which will produce a fatal error
function fatal_example()
{
    _fatalog_(time()); // writing the log
    $some_fatal_code = array()/3; // fatality!
    _fatalog_(); // if we get here then delete last file log
}

最後に、ログの内容を読み取ります...

var_dump(json_decode(file_get_contents('/path/to-the-fatal.log')));

お役に立てば幸いです!

1
Beto Aveiga

PHP DeBugger は、PHPその他のオプションのエラーと同様のバックトレースも行います。
必要な場合は、set_error_handlerおよびdebug_backtrace

set_error_handler ($error_handler, error_reporting);
/**
 * @var int $errno the error number
 * @var string $errstr the error message
 * @var string $errfile the error file
 * @var int $errline the line of the error
 */
$error_handler = function($errno, $errstr, $errfile, $errline){
    $trace = debug_backtrace();
    array_shift($backtrace);//remove the stack about this handler
    foreach($trace as $k => $v){
        //parse your backtrace
    }
}

また、バックトレースの内部スタックでは、キーの一部が設定されないことに注意してください。すべてのエラーが発生している場合は、キーを使用する前に必ずキーが存在するかどうかを確認してください:)

0
Yamiko