从PHP外部打印PHP运行调用堆栈

问题描述:

PHP中是否有任何运行时堆栈跟踪功能?
(对于谁也写Java,我的意思是jstack。)

Is there any runtime stack trace feature in PHP, by a given PID of it? (For whom also write Java, I mean jstack.)

我有几个PHP后台进程,他们在一些未知的行上冻结了一会儿。我可以简单地杀死他们,重新启动,但是不要再阻止它再次发生。

I got few PHP background process that they are freeze once a while on some unknown lines. I can simply kill them all and restart but that don't prevent it happen again.

是否有一个API可以监视堆栈并告诉?像JDK提供的jstack工具?

Is there a API able to spy the stack and tell? like the jstack utility provided from JDK?

您有几个可以调试未知错误的选项。

You have a few options in terms of debugging unknown errors.


  • 第一种方法很容易,但需要安装PHP扩展名。

  • 第二种方法提供了一个更难实践的方法,但如果您进入PHP解释器的低级内部工作,绝对值得。此外,这将需要使用 - 启用调试配置Linux和PHP。

  • 第三个,在我个人看来最简单的方法不需要使用任何外部程序或添加的PHP扩展。

  • The first method is easy, but requires a PHP extension to be installed.
  • The second method offers a more difficult hands-on approach, but is definitely worth it if you're into the low-level inner-workings of the PHP interpreter. Also, this will require linux and PHP to be configured with --enable-debug.
  • The third and, in my personal opinion the easiest, method doesn't require the use of any external programs or added PHP extensions.

  1. Xdebug


  • 这是一个PHP扩展,您可以安装和可用于任何网站/页面。

  • 网站功能的快速列表:


    • 自动堆栈跟踪

    • 函数调用记录

    • 显示增强的var_dump()输出和代码覆盖信息等功能。


    • 如果看到自己需要调试脚本很多,这可能是最好的选择。漂亮的错误显示也是我书中的好主意。



    • This is a PHP extension you can install and have available for any site/page.
    • A quick-list of features from the website:
      • Automatic stack trace upon error
      • Function call logging
      • Display features such as enhanced var_dump() output and code coverage information.

      使用 gdb 运行崩溃并分析回溯的文件。

      Use gdb to run the file that crashes and analyze the backtrace.


      • 这是一种中间到高级的方法,需要PHP配置为 - enable-debug ,运行 Apache 的linux机器,以及对软件在较低级别上的工作方式的强烈愿望/能力。

      • 运行 gdb Apache

        gdb / usr / lib / httpd

      • 然后,您有两个选项:

        • 将apache作为服务器并加载文件通过浏览器正常:

          (gdb)run -X

          ...现在,在浏览器中 - 访问正常崩溃的页面并切换回 gdb
          (gdb)backtrace

          ...将打印完整的追溯

        • 或者使用 gdb 运行脚本t本身:

          (gdb)运行/path/to/the/script.php

          (gdb)backtrace

          ...将打印完整的追溯

        • This is an intermediate-to-advanced approach that requires PHP to be configured with --enable-debug, a linux machine running Apache, and a strong desire/ability to understand the way software works on a lower-level.
        • Run gdb with Apache:
          gdb /usr/lib/httpd
        • Then, you have two options.:
          • Run apache as a server and load the file through a browser, as normal:
            (gdb) run -X
            ... now, in your browser - access the page that crashes as normal and switch back to gdb: (gdb) backtrace
            ... the full backtrace will be printed
          • Or, use gdb to run the script itself:
            (gdb) run /path/to/the/script.php
            (gdb) backtrace
            ... the full backtrace will be printed

          创建一个自定义错误处理程序,当抛出错误时打印堆栈跟踪。

          Create a custom error handler that prints the stack trace when an error is thrown.


          • 为了确保捕获所有错误,您可以捕获错误,异常和PHP的关闭事件。

          • 要调试单个页面,就像创建一个函数来处理错误一样简单,然后将该函数粘贴到您遇到问题的页面顶部。一步一步,我有一个错误处理类在一个单独的文件,只需要包含它(在下面的简化版本)。您可以调整每种方法以适应您的显示需求,甚至可以根据每个错误数量处理错误!

          • 然后,要使用此选项,只需添加 require ('ErrorHandler.php'); 到页面顶部,它应该自动注册自己来处理任何错误。当然,请务必更新包含路径以指向实际的文件。

          • To be sure to catch all errors, you can catch Errors, Exceptions, and PHP's Shutdown events.
          • To debug a single page, it's as simple as creating a function to handle the error and then pasting that function into the top of the page you're having issues on. One step further, I have an "error handling" class that's in a separate file and just include it whenever needed (simplified-version below). You can tweak each method to suit your display needs, or even handle errors on a per-error-number basis!
          • Then, to use this, just add require('ErrorHandler.php'); to the top of your page and it should auto-register itself to handle any errors. Be sure to update the include-path to point to the actual file, of course.

          ErrorHandler.php:

          ErrorHandler.php:

          <?php
          class ErrorHandler {
              public static function captureError($err_no, $message, $file, $line) {
                  echo '<strong>Error (#' . $err_no . '):</strong> ' . $message . ' in ' . $file . ' on line #' . $line . '<br />';
                  debug_print_backtrace();
              }
          
              public static function captureException($exception) {
                  echo '<pre>' . print_r($exception, true) . '</pre>';
              }
          
              public static function captureShutdown() {
                  if (($error = error_get_last()) !== null) {
                      debug_print_backtrace();
                  }
              }
          }
          set_error_handler(array('ErrorHandler', 'captureError'));
          set_exception_handler(array('ErrorHandler', 'captureException'));
          register_shutdown_function(array('ErrorHandler', 'captureShutdown'));
          ?>