内容


用 syslog 改进和调试 PHP 应用程序

PHP 版古老 UNIX syslog 提供了简单有效的调试工具

Comments

用计算机编程是一件单调乏味的事情,但是它也很有趣。编程有趣的一面在于了解使用旧工具的新方法。最近,我签了一份合同帮助解决基于 Linux®、Apache、MySQL 和 Linux、Apache、MySQL、PHP/Perl (LAMP) 的大型复杂内容管理系统 (CMS) 中的若干个错误。该 CMS 的架构是标准的 LAMP 模型,使用运行 Apache V2.0 的 Enterprise Red Hat Linux。驱动 Web 站点的代码由分布在 Apache 文档根目录的 30 个子目录中的几百个 PHP 源模块组成。系统的 Apache 和 MySQL 部分不需要更改,因为我的所有纠错操作都是在 PHP 工作区中进行的。

在研究了该 CMS 的工作原理一段时间之后,我渐渐开始欣赏该系统优雅的设计并且意识到在大多数成熟的编程环境中,此系统只依赖于少量的可用 PHP 函数(在这里想起了旧的 80/20 法则,其中 80% 的工作是用 20% 的可用函数来完成的)。本文将展示如何调试未知的复杂系统,以帮助您了解那些很少使用的函数,并提供如何使用 syslog() 函数的丰富功能来应用新知识的示例。

调试程序

虽然表面上 PHP 编程语言有成百上千个函数可用,但是在读到与本文类似的文章之前,您可能从未使用过某些函数(或许大多数函数)。另一种深入学习语言的方法是调试别人已经用该语言编写的程序。我总是对程序员用具有创造性的方法使用工具印象深刻。

调试像计算机编程一样,一半是科学,一半是艺术。在不是由您创建的系统中跟踪并不明显的错误时,需要能够很快地定位这些错误在代码中的位置。由于要处理的代码模块有成百上千个,因此最佳起点是显示找到错误的输出位置,然后从该位置开始逆向查找来隔离问题。

例如,如果知道输出的计算值不正确,则必须设计一种方法来查看导致出现问题的中间值。通过重要的数据库查询得到的错误数据可以证明存在其他问题。您必须能够查看生成(并由代码提交给 MySQL 引擎)的 SQL 语句以查看问题是不是出在语句里。

完成此操作的一项古老技术是插入可以打印这些字符串和值的代码。不幸的是,使用诸如 PHP 之类的工具或任何基于 Web 的应用程序,您不希望在这样的系统固有输出(即,被发送给浏览器的 HTML 代码)中掺入调试信息,尤其是在要检验的系统是一台生产服务器时。

您可以创建自定义日志记录文件并向其中写入日志消息,但是为什么不使用已经提供给您的工具呢?请始终记住:不要把工具尘封起来。您值得花一些时间查看语言创建者是否已经提供了一种库例程或函数,可以执行您通常需要的功能。实际上,只要您觉得某些内容很明显应当是编程包的一部分,那么它很可能就包含在其中。

我意识到需要使用类似于 UNIX® 的 syslog 的工具。我想 PHP 很有可能有 syslog 功能,因此在快速查看了 PHP 文档后,我找到了它!PHP syslog() 函数是我多年来没注意到的函数,直到我签约来做这个项目。使用 syslog(),我可以搜索直至找到并消除生产系统中的大多数错误,除了需要几分钟时间执行各个函数之外,不会引入其他副作用。

随着知识的积累并且在专业领域中越来越有经验,显然可以采用不同的方法来做事情,并且某种方法将最终成为执行必要任务的首选方法。必须始终牢记的是您认为很明显的事情对其他人来说并不一定是明显的。对您来说很简单的事情对于其他人来说可能非常复杂。

使用诸如 syslog() 函数之类的工具可以控制复杂度,并允许通过配置文件(例如 syslog.conf)来轻松地进行自定义。例如,可以插入代码来设定 SQL 语句的格式,将它记录到 syslog() 中并将其传递给 MySQL 来执行。随后,对 syslog.conf 文件稍微修改一下,把文本发送给另一个日志文件或者可能就发送给位桶(bit bucket)。几个星期或几个月之后,如果有必要再次查看发生的情况,则再对 syslog.conf 文件进行简单更改将还原该功能。

syslog

syslog 在 UNIX 世界中有着丰富多彩的历史。syslog 最初是作为 Sendmail 项目的一部分开发的,实践证明它非常有用,因此许多其他工具引入了 syslog 功能,证明了最简单的想法有时最有效。

简要地说,syslog 允许应用程序将带有标记的消息写入一组公共系统日志文件中,这些日志文件可以驻留在程序员和网络管理员能够轻松访问的位置。这意味着,例如,您可以配置 Web 服务器上的 syslog 以记录另一台服务器上的系统消息 —— 这台服务器可能是在安全防火墙后面几层并且更易于让前述管理员访问。但是按照我的目的,我只接受将文件写入 /var/log 目录的默认行为。

syslog 机制是在启动时启动的,并且其初始行为是由 syslog.conf 文件中的规则定义的。这些规则使您可以很好地调整使用该机制记录的内容 —— 在一台高容量而且工作繁重的服务器上使用 syslog 机制可以转换为可改变大小的日志文件。

每条规则都包含两个字段:selectoraction。基本上,selector 字段选择要记录的工具(例如,kern、user、mail、lpr)和工具拥有的优先级。优先级字段包含一个关键字,例如 debug、info、notice 或者 warning。而规则的 action 字段用于定义对匹配 selector 字段的那类消息执行的操作。规则可以指定记录消息的文件,将记录消息发送给哪台计算机,将消息发送给什么用户(以控制台消息的形式)等。

日志记录

研究与 syslog 工具相关的信息和手册页以了解如何根据需要配置系统。在我的例子中,我需要知道在生产 CMS 系统每次运行时各个 PHP 变量的值是什么。我还需要知道某些模块何时启动及何时停止以及各个中间变量值。在说明需要记录哪些信息的细节之前,让我们先来设置日志的基本信息。

使用您最喜欢用的编辑器,创建清单 1 中所示的文件,将其命名为 test.php 并把它放在 Apache 文档根目录中(在我的系统中,它是 /var/www)。

清单 1. test.php
<html>
  <head>
    <title>PHP Test Page</title>
  </head>
  <body>
    <?php
  syslog(LOG_NOTICE, "{$_SERVER['REMOTE_ADDR']}: test.php - PHP Index page accessed.");
  echo '<p>PHP Test Page</p>';
    ?>
  </body>
</html>

您同样应当安装并配置了 PHP。如果没有,请查看 参考资料 以获得介绍如何安装和配置的链接。如果一切配置正确,那么当您访问 URL 为 http://localhost/test.php 的页面时应当会在浏览器中看到以下文本:

PHP Test Page

接下来,打开一个 X 终端窗口并键入以下命令来查看记录到 /var/log/messages 文件中的内容:

tail /var/log/messages

如果一切运行正常,您应当会在接近清单末尾的位置看到下面一行:

Jul 23 14:43:42 localhost apache2: 127.0.0.1: test.php - PHP Index page accessed.

如果您看到了,那很好。您现在已经准备好开始详细调试所使用的复杂系统。

我发现了一个优秀实践:对所有 PHP/MySQL 调用使用 syslog(),这样每次都与 Web 站点交互,可以看到实时生成了哪些 SQL 查询以构建返回给您的页面。一种简单的实现方法是打开另一个 X 终端窗口并结合使用 tail 命令与 -f 选项来 “实时” 查看消息日志:

tail -f /var/log/messages

记录的内容

现在您已经检验了日志可以正常工作并且可以看到记录机制的结果,下面的提示介绍了如何使用这些工具尽可能快速地缩短学习陌生系统的过程。

必须知道哪些模块执行了超出其文档所述范围的操作。由于这个原因,我喜欢记录标记模块开头和结尾的日志消息。这样,您可以对 Web 站点的页面进行操作,同时监视运行 tail -f /var/log/messages 命令的另一个 X 终端窗口。这样可以看到哪些模块在执行并且浏览器每次请求新页面时的顺序。

我还需要记录在 PHP 代码运行期间被调用的各个程序之间的边界。例如,查询数据库时调用 MySQL,或者修改数据格式时调用外部程序(例如,Extensible Stylesheet Language Transformation(XSLT)引擎)。系统地把这些检查点插入每个 PHP 代码模块中,这种实践将帮助您熟悉模块的名称和位置。当浏览各个页面时代码把您在另一个 X 终端中看到的消息发送给您时,您将获得推动和增强系统知识的重要反馈。

结束语

syslog 工具是调试由其他人编写的应用程序的强大工具。它允许您查看哪些模块正被执行,哪些 SQL 语句正在执行,以及在您浏览 Web 站点时哪些变量值发生更改。这有助于查找可能会发生问题的模块。


相关主题

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文
  • 了解关于 syslog() 函数的更多信息。
  • 在 Wikipedia 中探索 syslog 的历史
  • PHP.net 是 PHP 开发者的重要资源。
  • 查看 “PHP 推荐读物列表”。
  • 浏览 developerWorks 上的全部 PHP 文章PHP 教程
  • 查看 IBM developerWorks 的 PHP 项目资源 以扩展 PHP 技巧。
  • 收听针对软件开发人员的有趣访谈和讨论,一定要访问 developerWorks podcast
  • 要将数据库与 PHP 结合使用?查看 Zend Core for IBM,它是一个无缝的、可以立即使用、易于安装、支持 IBM DB2 V9 的 PHP 开发和生产环境。
  • 访问 developerWorks 开放源码专区,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。
  • 使用 IBM 试用软件 改进您的下一个开发项目,这些软件可以通过下载或从 DVD 中获得。
  • 下载 IBM 产品评估版,并开始使用 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。

评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source
ArticleID=277641
ArticleTitle=用 syslog 改进和调试 PHP 应用程序
publish-date=10162007