为什么 httpd 报告的活动模块比 apachectl 少?

为什么 httpd 报告的活动模块比 apachectl 少?

我正在尝试在 Apache2 中启用 mod-nss 模块。因此,在完成必要的操作后,我尝试验证模块是否确实已加载。

询问 apachectl

# apachectl -M | grep nss
 nss_module (shared)

询问守护进程本身:

/usr/sbin/httpd-prefork -M | grep nss
-> No output

所以,我得到两个不同的输出:

  • apachectl 声称 mod_nss 模块已加载。
  • httpd 声称 mod_nss 模块未加载。

之后,我决定列出这两个模块(而不是仅 grep 查找特定模块),对输出进行排序,然后比较它们。

# diff -Nur httpd_sorted_modules apachectl_sorted_modules 
--- httpd_sorted_modules        2016-09-01 13:59:16.297139860 +0200
+++ apachectl_sorted_modules    2016-09-01 13:59:26.680985223 +0200
@@ -15,11 +15,15 @@
  expires_module (shared)
  http_module (static)
  include_module (shared)
+ info_module (shared)
  log_config_module (shared)
  mime_module (shared)
  mpm_prefork_module (static)
  negotiation_module (shared)
+ nss_module (shared)
+ php5_module (shared)
  reqtimeout_module (shared)
+ rewrite_module (shared)
  setenvif_module (shared)
  so_module (static)
  socache_shmcb_module (shared)

正如您所看到的,与 httpd 相比,apachectl 显示了 4 个额外的模块。为什么会发生这种情况?我应该信任哪一个?

我试图看看它们之间有什么区别,但我失败了。以下是我的一些发现:

apachectl 似乎是一个独立的二进制文件

# ls -l `which apachectl`
-rwxr-xr-x 1 root root 3548 Aug 23 13:11 /usr/sbin/apachectl

来自 apache pkg:

# rpm -qf `which apachectl`
apache2-2.4.16-12.1.x86_64

这实际上是用来减轻对 httpd 的控制。显然,与 SystemD 或 SySVinit 一起使用是有区别的。以下是来自 man apachectl 页面的引用:

当以直通模式运行时,apachectl 可以获取 httpd 二进制文件可用的所有参数。

   apachectl [ httpd-argument ]

当在 SysV init 模式下运行时,apachectl 接受简单的单字命令,定义如下。

   apachectl command

因此,如果我请求 -h 帮助选项:

 # apachectl -h
Usage: /usr/sbin/httpd-prefork [-D name] [-d directory] [-f file]
                               [-C "directive"] [-c "directive"]
                               [-k start|restart|graceful|graceful-stop|stop]
                               [-v] [-V] [-h] [-l] [-L] [-t] [-T] [-S] [-X]
Options:
  -D name            : define a name for use in <IfDefine name> directives
  -d directory       : specify an alternate initial ServerRoot
  -f file            : specify an alternate ServerConfigFile
  -C "directive"     : process directive before reading config files
  -c "directive"     : process directive after reading config files
  -e level           : show startup errors of level (see LogLevel)
  -E file            : log startup errors to file
  -v                 : show version number
  -V                 : show compile settings
  -h                 : list available command line options (this page)
  -l                 : list compiled in modules
  -L                 : list available configuration directives
  -t -D DUMP_VHOSTS  : show parsed vhost settings
  -t -D DUMP_RUN_CFG : show parsed run settings
  -S                 : a synonym for -t -D DUMP_VHOSTS -D DUMP_RUN_CFG
  -t -D DUMP_MODULES : show all loaded modules 
  -M                 : a synonym for -t -D DUMP_MODULES
  -t                 : run syntax check for config files
  -T                 : start without DocumentRoot(s) check
  -X                 : debug mode (only one worker, do not detach)

所以看起来它正在使用/usr/sbin/httpd-prefork或者至少是它所说的。

但让我们尝试看看“httpd”在后台使用什么:

# which httpd
/usr/sbin/httpd

这似乎是一个符号链接:

# ls -l `which httpd`
lrwxrwxrwx 1 root root 23 Aug 25 13:28 /usr/sbin/httpd -> /usr/sbin/httpd-prefork

所以它使用的/usr/sbin/httpd-prefork是与 apachectl 似乎使用的相同的。例如,如果我请求 -h 帮助,我会得到:

# /usr/sbin/httpd-prefork -h
Usage: /usr/sbin/httpd-prefork [-D name] [-d directory] [-f file]
                               [-C "directive"] [-c "directive"]
                               [-k start|restart|graceful|graceful-stop|stop]
                               [-v] [-V] [-h] [-l] [-L] [-t] [-T] [-S] [-X]
Options:
  -D name            : define a name for use in <IfDefine name> directives
  -d directory       : specify an alternate initial ServerRoot
  -f file            : specify an alternate ServerConfigFile
  -C "directive"     : process directive before reading config files
  -c "directive"     : process directive after reading config files
  -e level           : show startup errors of level (see LogLevel)
  -E file            : log startup errors to file
  -v                 : show version number
  -V                 : show compile settings
  -h                 : list available command line options (this page)
  -l                 : list compiled in modules
  -L                 : list available configuration directives
  -t -D DUMP_VHOSTS  : show parsed vhost settings
  -t -D DUMP_RUN_CFG : show parsed run settings
  -S                 : a synonym for -t -D DUMP_VHOSTS -D DUMP_RUN_CFG
  -t -D DUMP_MODULES : show all loaded modules 
  -M                 : a synonym for -t -D DUMP_MODULES
  -t                 : run syntax check for config files
  -T                 : start without DocumentRoot(s) check
  -X                 : debug mode (only one worker, do not detach)

这与我得到的相同apachectl -h

然而,这个来自另一个包:

# rpm -qf /usr/sbin/httpd-prefork
apache2-prefork-2.4.16-12.1.x86_64

除此之外,我想不出当我查询加载的模块时得到不同输出的原因:/

对于那些想知道的人,我使用 OpenSUSE Leap 42.1 作为我的 Linux 发行版,并使用 Prefork MPM 运行 Apache。

答案1

鉴于您的清单:

# ls -l `which apachectl`
-rwxr-xr-x 1 root root 3548 Aug 23 13:11 /usr/sbin/apachectl

你的二进制文件不太可能apachectl是一个“独立的二进制文件”(它太小了:一个合理的二进制文件会大10-20倍)。其实就是一个shell脚本。当你执行

apachectl -M

shell 脚本首先从其配置文件中获取附加参数,并-M在执行 httpd 二进制文件时将这些参数放在 之前。

为了讨论的目的,我将参考Apache 的 git 镜像,以及模板脚本apachectl.in。当然,不同版本的 Apache 有所不同,但不同版本的共同点apachectl是脚本会检查配置设置,其中可能包括服务器模块的位置。在模板的当前版本中,它位于注释下方

# pick up any necessary environment variables

如果不设置这些变量就直接运行httpd-prefork,将无法正常运行。这解释了为什么它报告模块未加载。如果您没有grep输出,您可能会得到一份信息更丰富的报告,例如,可能根本没有列表。

相关内容