本文目录
1.1 下载和解决依赖关系
1.2 httpd编译选项
1.3 模块动静态编译
1.4 动静态编译的优先级规则
1.5 MPM的安装
1.6 关于"--enable-so"
1.7 开始编译httpd
1.8 编译后的规范操作
以httpd 2.4.27为例。
资源下载:
apache自己的站点提供了基金会下所有的(包括所有版本)资源,包括httpd。
地址:http://archive.apache.org/dist/
httpd下载地址:http://archive.apache.org/dist/httpd
清华大学有一个httpd归档的镜像站点,里面提供最新测试版和最新稳定版的下载,还提供一些依赖包或模块的下载。
地址:http://mirrors.tuna.tsinghua.edu.cn/apache/httpd/
apache基金会下所有资源地址:http://mirrors.tuna.tsinghua.edu.cn/apache/
httpd同样使用"./configure"、"make && make install"的编译流程编译。但是它有一些依赖包需要提前装好。官方上指定的依赖环境有:apr、apr-util、pcre、pcre-devle,此外还需要expat-devel包。其中pcre、pcre-devel和expat.devel可以直接使用yum安装,apr和apr-util需要编译安装。下载地址可以从站点 http://mirrors.tuna.tsinghua.edu.cn/apache/ap/ 找到。
- yum - y install pcre pcre - devel expat - devel
以下是编译apr和apr-util的过程。
- tar xf apr-1.6.2.tar.gz
- tar xf arp-1.6.0.tar.gz
- cd apr-1.6.0
- ./configure --prefix=/usr/local/apr
- make
- make install
- cd ../apr-util-1.6.2
- ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr
- make
- make install
然后是编译httpd,httpd编译对刚接触的人来说可能有些麻烦,因为编译选项太多,其中的一些"潜规则"也不太熟悉。所以下面详细地说明说明。
httpd的编译选项非常多。以下是截取
中的一部分,使用"......"表示省略了一堆信息。
- ./configure -h
- Configuration: -h,
- --help display this help and exit--help = short display options specific to this package--help = recursive display the short help of all the included packages - V,
- --version display version information and exit - q,
- --quiet,
- --silent do not print`checking...' messages
- --cache-file=FILE cache test results in FILE [disabled]
- -C, --config-cache alias for `--cache-file=config.cache' - n,
- --no - create do not create output files--srcdir = DIR find the sources in DIR[configure dir or`..']
- Installation directories:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [/usr/local/apache2]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [PREFIX]
- By default, `make install'will install all the files in ` / usr / local / apache2 / bin ', `/usr/local/apache2/lib'etc.You can specify an installation prefix other than` / usr / local / apache2 ' using `--prefix',
- for instance`--prefix = $HOME '.
- For better control, use the options below.
- Fine tuning of the installation directories:
- --bindir=DIR user executables [EPREFIX/bin]
- --sbindir=DIR system admin executables [EPREFIX/sbin]
- --libexecdir=DIR program executables [EPREFIX/libexec]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data [PREFIX/var]
- --libdir=DIR object code libraries [EPREFIX/lib]
- ........................................
- System types:
- --build=BUILD configure for building on BUILD [guessed]
- --host=HOST cross-compile to build programs to run on HOST [BUILD]
- --target=TARGET configure for building compilers for TARGET [HOST]
- Optional Features:
- --disable-option-checking ignore unrecognized --enable/--with options
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --enable-layout=LAYOUT
- --enable-dtrace Enable DTrace probes
- --enable-hook-probes Enable APR hook probes
- --enable-exception-hook Enable fatal exception hook
- --enable-load-all-modules
- Load all modules
- --enable-maintainer-mode
- Turn on debugging and compile time warnings and load
- all compiled modules
- --enable-debugger-mode Turn on debugging and compile time warnings and turn
- off optimization
- --enable-pie Build httpd as a Position Independent Executable
- --enable-modules=MODULE-LIST
- Space-separated list of modules to enable | "all" |
- "most" | "few" | "none" | "reallyall"
- --enable-mods-shared=MODULE-LIST
- Space-separated list of shared modules to enable |
- "all" | "most" | "few" | "reallyall"
- --enable-mods-static=MODULE-LIST
- Space-separated list of static modules to enable |
- "all" | "most" | "few" | "reallyall"
- .........................................
- Optional Packages:
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --with-included-apr Use bundled copies of APR/APR-Util
- --with-apr=PATH prefix for installed APR or the full path to
- apr-config
- --with-apr-util=PATH prefix for installed APU or the full path to
- apu-config
- --with-pcre=PATH Use external PCRE library
- ....................'
以下是一个编译配置:
- . / configure--prefix = /usr/local / apache--sysconfdir = /etc/apache--enable - so--enable - ssl--enable - cgi--enable - rewrite--enable - modules = most--enable - mpms - shared = all--with - z--with - pcre--with - apr = /usr/local / apr--with - apr - util = /usr/local / apr - util--with - mpm = event
但这个配置中有些项是多余的,以下是等价编译配置:
- . / configure--prefix = /usr/local / apache--sysconfdir = /etc/apache--enable - mpms - shared = all--with - z--with - pcre--with - apr = /usr/local / apr--with - apr - util = /usr/local / apr - util--with - mpm = event
具体哪些项多余,看完下面的1.3-1.6就知道了。
httpd是高度模块化的程序,各个功能通过加载各个模块来实现。但前提是将功能对应的模块先编译好,以供httpd加载。
httpd对模块有两种编译方式:静态编译和动态编译。
httpd的一个优点是可以实现动态模块的热插拔。因为httpd是独立于终端的守护进程,可以通过发送HUP信号给httpd让其重读配置文件。而是否加载动态编译模块正是由httpd配置文件中的LoadModule指令决定的。当想要加载某个模块A时(即模块热插),使用LoadModule指定A模块的链接地址,再发送HUP信号重读配置文件即可。而想要停止某个模块A时(即模块热拔),只需将对应模块的LoadModule指令行给注释,再重读配置文件即可。
甚至,可以随时动态编译某个外部模块到httpd中,然后再热插。因为何时编译需要动态加载的模块对httpd来说是无关紧要的,它只需LoadModule和重读配置文件两个过程对模块进行控制。
在编译选项中,有几种类型的选项:
- --disable-FEATURE:禁用某特性,等价于--enable-FEATURE=no
- --enable-FEATURE[=ARG]:启用某特性,默认参数值为YES
- --enable-Module_Name=shared:指定的模块Module_Name以动态编译方式安装
- --enable-Module_Name=static:指定的模块Module_Name以静态编译方式安装
对于
中给定的选项,如果该选项是--disable的,那么表示该选项默认是启用的,需要显式使用--disable选项禁用;如果该选项是--enable的,那么表示该选项默认是禁用的,需要使用--enable选项来启用。例如:
- ./configure --help
- --disable-authz-user :表示authz-user特性默认启用,编译时无需指定该项。如果要禁用,编译时需显式指定--disable-authz-user
- --enable-echo :表示echo特性默认是禁用的,如果要启用,则编译时需显式指定--enable-echo
模块名的书写是有规则的,一般模块的全称类似于"mod_BASENAME.so"格式,例如"mod_charset_lite.so",但在编译选项中指定模块时,只需指定BASENAME,且如果basename中包含下划线时,需要转换为短横线。例如"--enable-echo"表示编译的模块是"mod_echo.so"。
此外,还支持3种列表方式的动静态编译选项:列表项之间使用空格分隔,但要使用单引号包围。
- --enable-modules='Module_Name1 Moduel_Name2'
- --enable-mods-shared='Module_Name1 Module_Name2'
- --enable-mods-statics='Module_Name1 Module_Name2'
列表部分还可以使用关键字"all/few/most/reallyall"。分别表示编译所有、少量、大多数、真正的所有模块。
"--enable-modules"基本等价于"--enable-mods-shared",都是动态编译给定列表中的模块,但"--enable-modules"可以额外使用一个关键字"none",表示不编译所有模块。
httpd动静态模块编译有一套规则,各种动静态便宜选项之间有优先级的存在。例如,某个非核心模块既指定了动态编译,同时又指定了静态编译,那到底是静态还是动态编译?
以下是我总结的一些优先级规则。
如果某个模块既显式指定了动态,又显式指定了静态编译,则静态编译优先级更高。例如:
- --enable-Module_Name=shared
- --enable-Module_Name=static
- --enable-mods-shared='Module_Name1 Module_Name2'
- --enable-mods-statics='Module_Name1 Module_Name2'
- --enable-modules='Module_Name1 Moduel_Name2'
那么,mod_echo模块将被静态编译。
- --enable-echo=shared
- --enable-echo=static
对于下面的例子,authn-file和echo这两个模块既指定了动态编译又指定了静态编译,静态优先级高于动态,所以这两个模块静态被静态编译。由于没有使用关键字,所以会使用默认的"--enable-mods-shared=most"配置。即动态编译大部分,但指定的这两个模块被静态编译。
- ./configure --prefix=/tmp/apache --enable-mods-static=few
- ./configure --prefix=/tmp/apache --enable-mods-static=few --enable-mods-shared=all
而下面这个例子由于额外指定了使用"--enable-mods-static=few"选项,其优先级高于默认的"--enable-mods-shared=most",所以结果是静态编译few,且显式指定的两个模块也被静态编译。
- ./configure --prefix=/tmp/apache \
- --enable-mods-static='authn-file echo' --enable-mods-shared='authn-file echo'
- ./configure --prefix=/tmp/apache \
- --enable-mods-static='authn-file echo' \
- --enable-mods-shared='authn-file echo' \
- --enable-mods-static=few
下面的配置如何编译的?由于默认的是"--enable-mods-shared=most"编译方式,所以模块"data"将以动态的方式编译。
- . / configure--prefix = /tmp/apache--enable - mods - static = few--enable - data
再看下面的例子,配置中出现了"--enable-mods-static=few"和"--enable-mods-shared"(未给定值时也是默认为most),static的优先级高于shared,所以没有指定编译方式的模块"data"使用静态编译方式编译,而显式指定了编译方式的模块"echo"其优先级最强,所以动态编译"echo"。
- . / configure--prefix = /tmp/apache--enable - data
- ./configure --prefix=/tmp/apache \
- --enable-mods-static=few --enable-mods-shared --enable-data --enable-echo=shared
编译mpm模块(prefork/worker/event)和其他模块差不多,唯一的区别是必须至少编译一个mpm模块,且必须有且仅有一个加载被httpd加载。
编译安装时默认的mpm是event模式(和发行版有关)。但可以通过"--with-mpm=MPM_NAME"来指定被加载的mpm模块。以下是几个相关编译选项:
- --with-mpm=MPM_Name:用于指定默认的mpm模块,它所指定的模块会被静态编译,并在httpd启动时加载。
- --enable-mpms-shared=MPM-LIST:指定动态编译安装的MPM列表,动态编译的MPM必须使用LoadModule指令加载才能使用。
如果定"--with-mpm"选项指定了某个mpm,则默认该模块被静态编译,但如果同时使用"--enable-mpms-shared"指定了该mpm,则该mpm模块被动态编译。
如果某个mpm模块被静态编译,在httpd启动时会加载它,如果想要切换到其他mpm模块,只有一种方法:重新编译httpd。
而动态编译mpm模块时,则可以通过LoadModule来切换到其他mpm模块。由于编译时自带默认mpm模块,还可以使用"--with-mpm"指定默认mpm模块,所以动态编译mpm模块无疑比静态编译要好。
"--enable-mpms-shared"可以指定动态编译的mpm列表,使用空格分隔,但需要使用单引号包围。还可以使用关键字"all"表示动态编译所有mpm模块。 例如:
- --enable-mpms-shared='prefork worker'
- --enable-mpms-shared=all
一个模块被动态编译,在需要加载的时候使用LoadModule指令指定该模块,并重读配置文件即可。但httpd为什么能加载该动态模块?这就是mod_so的能力。实际上,LoadModule和LoadFile指令就是该模块提供的。
该选项使得httpd有加载某动态模块的能力(DSO,Dynamic Shared Object),也因此它只能使用静态编译方式随httpd启动被加载。只要不显式指定"--enable-so=shared"或者将其加入显式编译列表,它都会默认以静态方式编译。实际上,只要显式指定了动态方式编译该选项,编译时会报错。
至此,就可以开始编译httpd了。过程如下:
- cd
- tar xf httpd-2.4.27.tar.gz
- cd httpd-2.4.27
- ./configure --prefix=/usr/local/apache --sysconfdir=/etc/apache --with-z --with-pcre --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util --with-mpm=event --enable-mpms-shared=all
其中安装路径为/usr/local/apache,配置文件路径为/etc/apache。
- [root@xuexi ~]# ls /usr/local/apache/
- bin build cgi-bin error htdocs icons include logs man manual modules
bin目录为二进制程序存放位置,如启动脚本apachectl、httpd、htpasswd、ab(压力测试工具)等;htdocs目录存放网页文件,默认里面有index.html;logs目录存放了日志文件,除了日志文件,默认还有httpd运行的pid文件httpd.pid,这个建议修改到/var/run目录下(方便判断);modules存放了编译后的模块;man目录为帮助文档路径。
使用httpd的启动脚本bin/apahcectl启动httpd,然后测试其是否正常。
- [root@xuexi apache]# bin/apachectl start
- [root@xuexi apache]# netstat -tnlp | grep httpd
- tcp 0 0 :::80 :::* LISTEN 38798/httpd
在浏览器中输入IP地址即可访问。
- echo "MANPATH /usr/local/apache/man" >> /etc/man.config
- echo 'PATH=/usr/local/apache/bin:$PATH' >/etc/profile.d/apache.sh
- source /etc/profile.d/apache.sh
- ln - s / usr / include / usr / local / apache / include
提供不提供没多大所谓,因为apachectl或httpd命令自身可以管理进程的启停,但自身管理启停时不提供lock文件。
如果要提供的话,从yum安装的httpd提供的/usr/lib/systemd/system/httpd.service(systemd)或/etc/init.d/httpd(sysV)拷贝后稍作修改就可以了。以下是按照我上面编译的环境做了修改后的systemd和sysV服务管理脚本。
以下是httpd的systemd服务管理脚本/usr/lib/systemd/system/httpd.service。
- [Unit]
- Description=The Apache HTTP Server
- After=network.target remote-fs.target nss-lookup.target
- Documentation=man:httpd(8)
- Documentation=man:apachectl(8)
- [Service]
- Type=notify
- EnvironmentFile=/etc/sysconfig/httpd
- ExecStart=/usr/local/apache/bin/httpd $OPTIONS -DFOREGROUND
- ExecReload=/usr/local/apache/bin/httpd $OPTIONS -k graceful
- ExecStop=/bin/kill -WINCH ${MAINPID}
- # We want systemd to give httpd some time to finish gracefully, but still want
- # it to kill httpd after TimeoutStopSec if something went wrong during the
- # graceful stop. Normally, Systemd sends SIGTERM signal right after the
- # ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
- # httpd time to finish.
- KillSignal=SIGCONT
- PrivateTmp=true
- [Install]
- WantedBy=multi-user.target
说明:上面的脚本中使用了"kill -WINCH"信号,它是graceful stop的信号。如不明白,见我的另一篇文章:进程和信号。
以下是httpd的sysV服务管理脚本/etc/rc.d/init.d/httpd。
- #!/bin/bash
- #
- # httpd Startup script for the Apache HTTP Server
- #
- # chkconfig: - 85 15
- # description: The Apache HTTP Server is an efficient and extensible \
- # server implementing the current HTTP standards.
- #
- ######################################################################
- # 若httpd配置文件中指定了PidFile,则修改此脚本中的pidfile变量 #
- ######################################################################
- . /etc/rc.d/init.d/functions
- if [ -f /etc/sysconfig/httpd ]; then
- . /etc/sysconfig/httpd
- fi
- # Start httpd in the C locale by default.
- HTTPD_LANG=${HTTPD_LANG-"C"}
- # This will prevent initlog from swallowing up a pass-phrase prompt if
- # mod_ssl needs a pass-phrase from the user.
- INITLOG_ARGS=""
- # Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server
- # with the thread-based "worker" MPM; BE WARNED that some modules may not
- # work correctly with a thread-based MPM; notably PHP will refuse to start.
- # Path to the apachectl script, server binary, and short-form for messages.
- apachectl=/usr/local/apache/bin/apachectl
- httpd=/usr/local/apache/bin/apachectl
- prog=httpd
- pidfile=${PIDFILE-/var/run/httpd/httpd.pid}
- lockfile=${LOCKFILE-/var/lock/subsys/httpd}
- RETVAL=0
- STOP_TIMEOUT=${STOP_TIMEOUT-10}
- config=/etc/apache/httpd.conf
- # The semantics of these two functions differ from the way apachectl does
- # things -- attempting to start while running is a failure, and shutdown
- # when not running is also a failure. So we just do it the way init scripts
- # are expected to behave here.
- start() {
- echo -n $"Starting $prog: "
- LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd -f $config $OPTIONS
- RETVAL=$?
- echo
- [ $RETVAL = 0 ] && touch ${lockfile}
- return $RETVAL
- }
- # When stopping httpd, a delay (of default 10 second) is required
- # before SIGKILLing the httpd parent; this gives enough time for the
- # httpd parent to SIGKILL any errant children.
- stop() {
- status -p ${pidfile} $httpd > /dev/null
- if [[ $? = 0 ]]; then
- echo -n $"Stopping $prog: "
- killproc -p ${pidfile} -d ${STOP_TIMEOUT} $httpd
- else
- echo -n $"Stopping $prog: "
- success
- fi
- RETVAL=$?
- echo
- [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
- }
- reload() {
- echo -n $"Reloading $prog: "
- if ! LANG=$HTTPD_LANG $httpd $OPTIONS -t >&/dev/null; then
- RETVAL=6
- echo $"not reloading due to configuration syntax error"
- failure $"not reloading $httpd due to configuration syntax error"
- else
- # Force LSB behaviour from killproc
- LSB=1 killproc -p ${pidfile} $httpd -HUP
- RETVAL=$?
- if [ $RETVAL -eq 7 ]; then
- failure $"httpd shutdown"
- fi
- fi
- echo
- }
- # See how we were called.
- case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status -p ${pidfile} $httpd
- RETVAL=$?
- ;;
- restart)
- stop
- start
- ;;
- condrestart|try-restart)
- if status -p ${pidfile} $httpd >&/dev/null; then
- stop
- start
- fi
- ;;
- force-reload|reload)
- reload
- ;;
- graceful|help|configtest|fullstatus)
- $apachectl $@
- RETVAL=$?
- ;;
- *)
- echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest}"
- RETVAL=2
- esac
- exit $RETVAL
来源: http://www.cnblogs.com/f-ck-need-u/p/7605563.html