美文网首页
openSUSE15.3 apache无法解析php7的问题

openSUSE15.3 apache无法解析php7的问题

作者: 量U移动广告归因 | 来源:发表于2021-06-26 17:21 被阅读0次
    开篇——这看起来是一个很简单的问题,但又绝不同于以往的任何一个类似的问题,即便搜遍全网,可能也找不到答案,但这篇会带领您一窥究竟
    • 先按国际惯例,安装好 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的开发环境体验还有待提升

    相关文章

      网友评论

          本文标题:openSUSE15.3 apache无法解析php7的问题

          本文链接:https://www.haomeiwen.com/subject/ugszyltx.html