应该很多人都在为mod_perl的调试方法发愁吧。通常只能使用print,或者输出到syslog中, 但都需要猜测错误位置并添加相应的日志输出,然后重启服务器,刷新,看结果…… 虽然使用Apache::Reload能减少重启服务器的麻烦,但Apache::Reload用多了就会出错,而必须重启, 何况打日志总不像交互式调试器方便。

mod_perl的官方文档中写明了如何使用调试器来调试, 不过这个方法在RHEL4下似乎不太好用(自己编译mod_perl的同学就应该没这个问题)。 查看了一下,原来RHEL4自带的mod_perlmod_perl-1.99_16-4, 而在官方的mod_perl的下载页面上最高版本只有 1 系的 1.30 和2系的2.0.4,并没有所谓的1.99版。 看这个mod_perl-1.99的内容,应该是1系和2系的混合体吧。 Apache::DB这个包与mod_perl-1.99不兼容,于是就无法正常调试了。

不过办法总是有的——自己改!方法如下。

  1. 安装Apache::DB。去CPAN搜索Apache::DB安装即可。这里的例子使用的是Apache-DB-0.13。 安装方法不用多说,直接 perl Makefile.PL && make && make install。

  2. 修改Apache::DB:

    打开/usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi/Apache/DB.pm,注释掉72-74行:

     69     else {
     70         if (ref $r) {
     71         $SIG{INT} = \&DB::catch;
     72 #       $r->register_cleanup(sub {
     73 #           $SIG{INT} = \&DB::ApacheSIGINT();
     74 #       });
     75         }
     76     }
    
  3. 然后修改httpd.conf,加载调试模块:

     <IfDefine PERLDB>
         <Perl>
           use Apache::DB ();
           Apache::DB->init;
         </Perl>
         <Location />
           PerlFixupHandler Apache::DB
         </Location>
     </IfDefine>
     <IfDefine !PERLDB>
         PerlInitHandler Apache::Reload
     </IfDefine>
    

    这里定义了一个环境变量PERLDB,这个变量存在时即启动Apache::DB供交互调试使用, 不存在则加载Apache::Reload用于通常的开发。

  4. 停止Apache

     # /etc/init.d/httpd stop
    
  5. 以调试方式启动Apache

     # httpd -X -D PERLDB
     [notice] Apache::DB initialized in child 11135
    
  6. 从浏览器访问要调试的页面。这时即可进入调试器。

     Loading DB routines from perl5db.pl version 1.27
     Editor support available.
        
     Enter h or `h h' for help, or `man perldebug' for more help.
        
     DB<1> 
    

然后就可以使用尽情地调试了。

一般的调试方法都是,先 use 你要调试的模块,然后设置断点,执行,再单步。 写成命令就是:

DB<1> use Your::Module;         # 先use一下避免添加断点时找不到函数(不是必须的)
DB<2> b Your::Module::foo;      # 在foo函数开始处设置断点
DB<3> c                         # 执行到断点
DB<4> n                         # 单步执行(要step in就用s)
DB<5> x $bar;                   # 查看变量的详细内容

最后,想结束调试时,再开个终端然后 killall httpd 就行了。