动态加载apache模块
工作中往往随着业务的改变和新功能的添加,会使用到不同的模块,但是我们编译apache的时候却没有指定。我们可以重新编译apache指定相应模块,可是大多数情况是不允许重新编译的,也很麻烦。所以大部分人都会使用动态加载模块,下面来说一下apache如何动态添加模块。
一、环境介绍
想要动态加载模块,必须要有同一版本的apache源码包
可以使用
/usr/local/apache/bin/apachectl -v 查看当前版本
Server version: Apache/2.2.22 (Unix)
我的版本为2.2.22,那么就需要apache2.2.22 版本的源码包 httpd-2.2.22.tar.gz
源码包中有一个modules目录,里面放着各种未编译的源码程序
编译这些程序的时候需要 gcc 支持,可以使用
rpm -qa | grep gcc 命令查看是否已经安装
gcc-4.1.2-54.el5
libgcc-4.1.2-54.el5
gcc-gfortran-4.1.2-54.el5
gcc-c++-4.1.2-54.el5
我这里已经装过了,没有安装可使用
yum install gcc* -y 进行安装
如果安装mod_rewrite模块,是需要gdb支持的,可以使用下面命令安装
yum install gdb* -y 进行安装
二、编译模块
对apache的模块如果动态编译通常可以使用 /path/apxs -c *.c来完成
下面以mod_rewrite和mod_ssl模块为例,讲解下安装过程
首先安装mod_rewrite模块,我们进入源码包的modules/mappers/目录,因为mod_rewrite模块的源码在这个目录下面,注意不是安装目录
cd httpd-2.2.22/modules/mappers/
查看里面是否包含mod_rewrite模块源码
ls | grep mod_rewrite
mod_rewrite.c
mod_rewrite.dep
mod_rewrite.dsp
mod_rewrite.exp
mod_rewrite.h
mod_rewrite.mak
果然在这里,使用下面命令编译
/usr/local/apache/bin/apxs -c mod_rewrite.c -lgdbm (如果不是mod_rewrite模块不需要加 -lgdbm)
gcc -shared -o mod_rewrite.so mod_rewrite.o
这样在当前目录下(即:httpd-2.2.22/modules/mappers/)就会生成一个名为mod_rewrite.so的模块
我们可以手动将这个模块移动到apache默认的模块目录下
mv mod_rewrite.so /usr/local/apache/modules/
然后修改httpd.conf文件,加入下面内容
LoadModule rewrite_module modules/mod_rewrite.so
当然也可以使用命令直接将mod_rewrite.so添加到/usr/local/apache/modules/目录下,并且在httpd.conf中写入
LoadModule rewrite_module modules/mod_rewrite.so
使用下面命令即可
/usr/local/apache/bin/apxs -i -a -n rewrite /http-2.2.22/modules/mappers/mod_rewrite.so
检测下语法,可使用命令
/usr/local/apache/bin/apachectl -t
如果返回值为Syntax OK,那么恭喜添加成功
如果返回值为不能定位API”之类的错误,那就是说明LoadModule后面的模块名的语法要根据您的apache版本加以改变。一般apache的配置文件中会写一个例子,按照它的格式写就好。
例如这种格式
#LoadModule mod_rewrite_module modules/mod_rewrite.so
如果没有错误重启apache
/usr/local/apache/bin/apachectl restart
查看是否加载成功,可使用下面的命令
/usr/local/apache/bin/apachectl -M
如果显示内容中包含rewrite_module 则成功,不包含则失败。
其他模块也可按同一方法编译安装,但不包括mod_ssl模块,我在编译mod_ssl模块时遇到了其他问题
再来看一下mod_ssl模块
先进入mod_ssl模块所在目录
cd httpd-2.2.22/modules/ssl/
使用下面命令编译
/usr/local/apache/bin/apxs -c mod_rewrite.c
报错
mod_ssl.c:553: 错误:expected ‘{’ at end of input
apxs:Error: Command failed with rc=65536
谷歌之后加上了-DHAVE_OPENSSL参数
/usr/local/apache/bin/apxs -c -DHAVE_OPENSSL mod_ssl.c
没有报错,继续执行
gcc -shared -o mod_ssl.so mod_ssl.o
/usr/local/apache/bin/apxs -i -a -n ssl /httpd-2.2.22/modules/ssl/mod_ssl.so
检测语法
/usr/local/apache/bin/apachectl -t
出现undefined symbol: ssl_cmd_SSLMutex错误
谷歌了一下,搜到下面内容
undefined symbol: ssl_cmd_SSLMutex
或
undefined symbol: X509_free
通产是由于静态连接了 openssl的库照成的(默认)。
需要使用 -lcrypto -lssl -ldl
命令如下:
/path/apxs -I/path/openssl/include -L/path/openssl/lib -c *.c -l crypto -l ssl -l dl
openssl 编译的时候需要增加 shared参数
/usr/local/apache/bin/apxs -a -i -c -D HAVE_OPENSSL=1 -I /usr/include/openssl/ -L /usr/lib/openssl/engines/lib ./mod_ssl.c
于是重新编译,问题依旧。
搞了两天,还是同样的错误,没有办法,最后在虚拟机上重新编译了相同版本的apache,并且使用了--enable-mods-shared=all参数,动态编译了所有的模块。
这样在apache的modules目录下就生成了所有的apache模块,也就包括了mod_ssl模块,复制到线上服务器
检测语法OK,问题解决
/usr/local/apache/bin/apachectl -t
Syntax OK
虽然这不是一个好方法,但也算是一个办法,也希望直接编译成功的大神不吝指点。
重启apache
/usr/local/apache/bin/apachectl restart
查看是否加载成功
/usr/local/apache/bin/apachectl -M
显示内容中包含ssl_module
三、大功告成