Apache mod_perl 配置参数详解

详解 Apache mod_perl 2.0.12 的关键配置指令(PerlModule、PerlResponseHandler、PerlSetVar、PerlSwitches、PerlOptions、PerlRequire、PerlChildInitHandler 等),说明作用域与生效时机,并给出生产配置模板

Apache mod_perlApache mod_perl2026/10/11

Apache mod_perl 配置参数详解

目标:详解 Apache mod_perl 2.0.12 的关键配置指令(PerlModule、PerlResponseHandler、PerlSetVar、PerlSwitches、PerlOptions、PerlRequire、PerlChildInitHandler 等),说明各指令的作用域、生效时机与常见用法,并给出生产配置模板;已在 Apache/2.4.52 + Perl v5.34.0 实测。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Apache HTTP Server:Apache/2.4.52 (Ubuntu)
  • Perl:v5.34.0
  • mod_perl:2.0.12(apt 包 libapache2-mod-perl2 2.0.12-1build1)
  • 配置体系:/etc/apache2/(mods-available / conf-available / sites-available)
  • 服务控制:apache2ctl -k restart(本环境未启用 systemd 服务托管)
  • 示例账号:root

二、前置条件

  • 已安装 apache2 与 libapache2-mod-perl2,且 perl 模块已启用(a2enmod perl)。
  • 模块确认:apache2ctl -M | grep -i perl 输出 perl_module (shared)。

三、参数查看与修改方式

3.1 查看已加载模块

apache2ctl -M

回显(节选,perl 模块行):

perl_module (shared)

3.2 配置文件位置

文件/目录说明
/etc/apache2/mods-available/perl.loadperl 模块加载指令(LoadModule perl_module /usr/lib/apache2/modules/mod_perl.so),a2enmod perl 后与 mods-enabled/ 同步
/etc/apache2/conf-available/perl-switches.conf全局 PerlSwitches -I<目录> 片段(a2enconf 启用)
/etc/apache2/sites-available/000-default.conf站点级 <Location>/<Directory> 段内使用 PerlResponseHandler、PerlOptions 等
/etc/apache2/apache2.conf全局主配置(可放 PerlModule、PerlSwitches)

3.3 修改与生效

  • a2enmod/a2dismod 启用/停用模块;a2enconf/a2disconf 启用/停用配置片段。
  • apache2ctl configtest(等价 apache2ctl -t)做语法检查,回显 Syntax OK。
  • apache2ctl -k restart 完整重启。启动期生效的指令(PerlSwitches、PerlModule、PerlRequire 等)修改后必须完整重启,reload 不生效。

四、参数总览

指令作用域生效时机用途
SetHandler perl-scriptDirectory/Location请求期让路径请求走 mod_perl 的 perl-script 处理器
PerlResponseHandlerDirectory/Location请求期(响应阶段)指定响应阶段处理器(模块名或 模块::handler)
PerlModule服务器级启动期启动时预加载 Perl 模块
PerlRequire服务器级启动期启动时执行指定 Perl 文件(可含初始化逻辑)
PerlSwitches服务器级启动期向解释器传命令行开关(-I 追加 @INC)
PerlOptionsDirectory/Location请求期段内选项(如 +ParseHeaders)
PerlSetVarDirectory/Location请求期设置模块级变量($r->dir_config() 读取)
PerlSetEnvDirectory/Location请求期设置传入 Perl 子进程的环境变量
PerlChildInitHandler服务器级子进程启动时子进程初始化阶段回调
PerlPostReadRequestHandler服务器级请求期(最早期)请求读取后立即执行
PerlFixupHandlerDirectory/Location请求期(响应前)响应前修正阶段
PerlLogHandlerDirectory/Location请求期(收尾)日志记录阶段
PerlCleanupHandlerDirectory/Location请求期(收尾)请求清理阶段

五、核心参数详解

5.1 SetHandler perl-script

启用 mod_perl 的 perl-script 处理器,是让 Perl 代码处理 HTTP 请求的前提,放在 <Location>/<Directory> 段内:

        <Location /hello>
                SetHandler perl-script
        </Location>

5.2 PerlResponseHandler

指定响应阶段的处理器,可写模块名(调用其中的 handler 子例程)或完整子例程路径:

PerlResponseHandler Hello
# 或显式指定子例程
PerlResponseHandler Hello::handler

对应源码(/var/www/perl/Hello.pm,实测):

package Hello;
use strict;
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Const -compile => qw(OK);
sub handler {
  my $r = shift;
  $r->content_type('text/html');
  $r->print("Hello from mod_perl!");
  return Apache2::Const::OK;
}
1;

5.3 PerlModule

启动时预加载 Perl 模块(不必等首个请求才编译),默认仅用于主服务器上下文:

PerlModule Hello

与请求期按 @INC 懒加载相比,预加载可提前暴露编译错误、加速首个请求。注意该指令作用于服务器级。

5.4 PerlRequire

启动时执行指定 Perl 文件,适合加载含初始化逻辑的脚本(如注册处理器、连接池预热):

PerlRequire /var/www/perl/startup.pl

与 PerlModule 的区别:PerlModule 只加载模块(等价 use,按 @INC 找 .pm);PerlRequire 执行指定文件(等价 require,可给任意路径的 .pl/.pm),常用于启动期初始化。

5.5 PerlSwitches

启动期向 mod_perl 解释器传入命令行开关。最常用的是 -I 追加 @INC 搜索路径(解决自定义模块不在 @INC 导致的 500 错误,如 Can't locate Hello.pm in @INC),实测:

# /etc/apache2/conf-available/perl-switches.conf
PerlSwitches -I/var/www/perl

⚠️ 注意:仅在 Apache 启动时生效,修改后必须完整重启(apache2ctl -k restart),reload 不生效。

5.6 PerlOptions

段内(Directory/Location)选项,常用值:

  • +ParseHeaders:启用响应头解析。处理器直接 print 原始文本且不调用 $r->content_type() 时,需要该选项让 mod_perl 从输出中解析 HTTP 头;本例处理器显式设置 content_type,配合使用更稳妥。
  • +GlobalRequest:允许在无请求上下文的代码中使用全局请求对象。
  • -Enable / +Enable:控制该配置段是否启用 mod_perl 特性。
<Location /hello>
        SetHandler perl-script
        PerlResponseHandler Hello
        PerlOptions +ParseHeaders
</Location>

5.7 PerlSetVar

设置仅供 mod_perl 读取的模块级变量(类似 SetEnv,但通过 $r->dir_config() 获取,不注入进程环境):

PerlSetVar AppRoot /var/www/perl

读取方式:

my $root = $r->dir_config('AppRoot');

5.8 PerlSetEnv

设置传入 Perl 子进程的环境变量(与 SetEnv 行为类似,随请求环境可见):

PerlSetEnv APP_ENV production

5.9 生命周期阶段处理器

mod_perl 把 Apache 请求生命周期拆为多个阶段,各阶段处理器用独立指令注册,可在单个 <Location> 内同时挂多个:

PerlPostReadRequestHandler MyApp::post_read
PerlFixupHandler            MyApp::fixup
PerlResponseHandler         MyApp::handler
PerlLogHandler              MyApp::log
PerlCleanupHandler          MyApp::cleanup
  • PerlPostReadRequestHandler:请求行/头读取后最早执行;
  • PerlFixupHandler:响应处理前修正(如改写参数);
  • PerlResponseHandler:主响应阶段(本文示例所在阶段);
  • PerlLogHandler:请求结束写日志;
  • PerlCleanupHandler:请求清理(释放资源);
  • PerlChildInitHandler(服务器级):每个 Apache 子进程启动时执行一次,适合连接池等按进程的初始化。

六、生产配置模板

适用场景:4GB 内存、普通 SATA SSD 的中小型动态站点(Perl Web 应用,单站点)。

6.1 全局片段(/etc/apache2/conf-available/perl-global.conf)

# 追加自定义模块搜索路径(@INC)
PerlSwitches -I/var/www/perl

# 启动时预加载公共模块,加速首个请求
PerlModule Apache2::RequestRec
PerlModule Apache2::RequestIO

启用并重启:

a2enconf perl-global
apache2ctl configtest
apache2ctl -k restart

6.2 站点段(/etc/apache2/sites-available/000-default.conf)

        <Location /app>
                SetHandler perl-script
                PerlResponseHandler MyApp
                PerlOptions +ParseHeaders
                PerlSetVar AppRoot /var/www/perl
                PerlSetVar LogLevel info
        </Location>

6.3 上线与发布注意

  • 代码发布:将新版本模块放入 /var/www/perl 后完整重启 Apache 使其生效(reload 对启动期指令与模块重载不保证生效)。
  • 日志监控:持续跟踪 /var/log/apache2/error.log,出现 [perl:error] 即说明处理器执行异常。
  • 内存评估:mod_perl 将 Perl 解释器嵌入 Apache 子进程,每个子进程都携带解释器,内存占用随站点复杂度上升;按实测规模评估 MaxRequestWorkers。

七、常见问题(FAQ)

Q1:改了 PerlSwitches 并 reload 后仍报 Can't locate Hello.pm in @INC? PerlSwitches 仅在启动时生效,必须完整重启(apache2ctl -k restart)。

Q2:PerlModule 与 PerlRequire 怎么选? PerlModule 用于按 @INC 加载模块(等价 use);PerlRequire 用于启动时执行指定文件(等价 require,可含初始化逻辑)。两者都在启动期执行。

Q3:自定义目录的模块 500,怎么加搜索路径? 全局配置 PerlSwitches -I/var/www/perl(conf-available 片段 + a2enconf),完整重启。

Q4:PerlSetVar 设置的值怎么读取? 通过 $r->dir_config('AppRoot') 读取,不注入操作系统环境变量。

Q5:PerlOptions +ParseHeaders 什么时候必须加? 当处理器直接 print 原始响应文本、不显式调用 $r->content_type() 时,需要 +ParseHeaders 让 mod_perl 从输出解析 HTTP 头;显式设置 content_type 的处理器配合使用更稳妥。

Q6:如何确认版本与生效状态? /var/log/apache2/error.log 启动横幅 Apache/2.4.52 (Ubuntu) mod_perl/2.0.12 Perl/v5.34.0;包版本 dpkg -l libapache2-mod-perl2 显示 2.0.12-1build1。

八、参考链接