开篇——这看起来是一个很简单的问题,但又绝不同于以往的任何一个类似的问题,即便搜遍全网,可能也找不到答案,但这篇会带领您一窥究竟
- 先按国际惯例,安装好 apache2 和php7,以及 apache2-mod_php7
zypper install apache2
zypper install php7
//这时 apache2-mod_php7可能已经自动安装上了,如果没装,手动安装一下就好
zypper install apache2-mod_php7
- 查看 apache 配置文件中 web 目录位置,然后新建 phpinfo.php
openSUSE的 apache 的配置文件分得很散,一个配置文件可以搞定的事全部打散成各个小的配置文件位于 /etc/apache2 下,主配置文件是 /etc/apache2/httpd.conf,但是 web 目录位置配置又在 /etc/apache2/default-server.conf 里,这种体验很不友好,尤其是对新手
DocumentRoot "/srv/www/htdocs"
我们在 /srv/www/htdocs 下新建一个 phpinfo.php文件
<?php
echo phpinfo();
?>
- 好玩的来了,当我打开浏览器访问 localhost/phpinfo.php 的时候,浏览器怎么也解析不了php文件,始终提示我下载文件
按理说,如果是 CentOS,到这一步PHP环境基本就已经配置成功了
开始解决问题
- 一开始我的直觉是没有加载mod_php7模块,后来证明也的确如此,于是乎我根据 http.conf 的配置顺藤摸瓜,发现 openSUSE 的 apache 把模块加载配置专门放到了一个 /etc/apache2/loadmodule.conf 文件里,我喜出望外,马上加上
LoadModule php7_module /usr/lib64/apache2/mod_php7.so
然后重启
service apache2 restart
呵呵,我还是太轻敌了,发现还是不行,但是诡异的是,明明执行 httpd -M 可以看到加载了 mod_php7
httpd -M
....
reqtimeout_module (shared)
authn_core_module (shared)
authz_core_module (shared)
php7_module (shared)
- 从错误日志入手
打开 /var/log/apache2/error_log,发现大有乾坤
[Sat Jun 26 04:02:53.190028 2021] [core:notice] [pid 9492] AH00094: Command line:
'/usr/sbin/httpd-prefork -D SYSCONFIG -C PidFile /var/run/httpd.pid -C
Include /etc/apache2/sysconfig.d//loadmodule.conf -C
Include /etc/apache2/sysconfig.d//global.conf -f /etc/apache2/httpd.conf -c
Include /etc/apache2/sysconfig.d//include.conf -D SYSTEMD -D FOREGROUND'
这是怎么回事,怎么是 /etc/apache2/sysconfig.d//loadmodule.conf 这个模块加载配置文件,不是 /etc/apache2/loadmodule.conf 这个吗?
原来 service apache2 restart 这个服务启动的配置和直接使用httpd命令执行apache使用的配置不一样,这就是为什么使用 httpd -M 可以看到加载了 mod_php7 模块,但使用 service 启动后浏览器却无法解析
那么我在 /etc/apache2/sysconfig.d//loadmodule.conf 里加上 mod_php7 的配置不就可以了吗,我再次喜出望外,当我加上之后,再次启动 apache ,发现这个 loadmodule.conf 居然又被重置了,也就是说,这个并不是一个真正的配置文件,而是通过其他的程序生成的一个缓存文件罢了
- 再次顺藤摸瓜
需要找到这个 loadmodule.conf 是怎么生成的,先找到 service 启动脚本所在 /usr/lib/systemd/system/apache2.service
//apache2.service的内容
[Unit]
Description=The Apache Webserver
After=network.target nss-lookup.target time-sync.target remote-fs.target
Before=getty@tty1.service plymouth-quit.service xdm.service
PartOf=apache2.target
[Service]
Type=notify
PrivateTmp=true
ExecStart=/usr/sbin/start_apache2 -DSYSTEMD -DFOREGROUND -k start
ExecReload=/usr/sbin/start_apache2 -DSYSTEMD -DFOREGROUND -k graceful
ExecStop=/usr/sbin/start_apache2 -DSYSTEMD -DFOREGROUND -k graceful-stop
KillMode=mixed
TasksMax=infinity
NotifyAccess=all
[Install]
WantedBy=multi-user.target
Alias=httpd.service apache.service
原来真正的启动脚本是 /usr/sbin/start_apache2 ,再次打开这个文件,在143行处可以看到调用了 get_module_list 这个函数,但是这个函数的实现却没有在这个脚本里,肯定在某个引用脚本里
#!/bin/sh
#
# Copyright (c) 1996, 1997, 1998 S.u.S.E. GmbH
# Copyright (c) 1998, 1999, 2000, 2001 SuSE GmbH
# Copyright (c) 2002, 2003, (2004?) SuSE Linux AG
# Copyright (c) 2004(?), 2005, 2006, 2007, 2008 SUSE Linux Products GmbH
#
# Authors: Rolf Haberrecker <apache@suse.de>, 2001
# Peter Poeml <apache@suse.de>, 2002, 2003, 2004, 2005, 2006, 2007,
# 2008, 2009, 2010
#
#
. /usr/share/apache2/script-helpers
看脚本开头引入了 script-helpers 这么一个脚本,打开它
//大概64行处
function get_module_list
{
load_sysconfig
find_mpm
for module in $APACHE_MODULES; do
# special case
# remove or add 'd' on in cgi module name
case $module in mod_cgid|cgid)
case $HTTPD_MPM in prefork) module=${module%d};; esac;;
esac
case $module in mod_cgi|cgi)
case $HTTPD_MPM in event|worker) module=${module}d;; esac;;
esac
......
果不其然,这个函数的实现在这里,根据代码看得出是根据 $APACHE_MODULES 这个变量循环得出最后要加载那些模块,于是目光落在 $APACHE_MODULES 这个变量上,毫无疑问,这是个数组,而且也是通过某个配置文件读取加载的,看到 get_module_list 函数第一行就调用了 load_sysconfig,没错就是它了,它的函数实现在 script-helpers 的开头
#!/bin/bash
HTTPD_SBIN_BASE="/usr/sbin/httpd"
#
# loads sysconfig variables into environment
#
# return value in: APACHE_*
#
function load_sysconfig
{
[ -n "$sysconfig_loaded" ] && return
[ ! -f "$SYSCONFIG_FILE" ] && return
. $SYSCONFIG_FILE
//在这里输出 SYSCONFIG_FILE 的路径
echo $SYSCONFIG_FILE
exit
export ${!APACHE_*} sysconfig_loaded=true
}
.....
在 load_sysconfig 函数里打印 $SYSCONFIG_FILE 的值,然后停掉 apache2服务,直接使用命令调用 apache2
service apache2 stop
/usr/sbin/start_apache2
最后输出
/etc/sysconfig/apache2
哈哈,最后抽丝剥茧,终于发现它了,打开这个文件
# fairly minimal
# APACHE_MODULES="authz_host alias auth dir log_config mime setenvif"
#
# apache's default installation
# APACHE_MODULES="authz_host actions alias asis auth autoindex cgi dir imap include log_config mime negotiation setenvif status userdir"
# your settings
APACHE_MODULES="actions alias auth_basic authn_core authn_file authz_host authz_groupfile authz_core authz_user autoindex cgi dir env expires include log_config mime negotiation setenvif ssl socache_shmcb userdir reqtimeout"
在80行,APACHE_MODULES变量就位于此处,将 php7 加上,修改后
APACHE_MODULES="actions alias auth_basic authn_core authn_file authz_host authz_groupfile authz_core authz_user autoindex cgi dir env expires include log_config mime negotiation setenvif ssl socache_shmcb userdir reqtimeout php7"
再次重启 apache 服务
service apache2 restart
终于看到了熟悉的 phpinfo 界面
- openSUSE的开发环境体验还有待提升
网友评论