1)前言
在CentOS7下,可以使用yum直接安装Nginx,但官方编译不具备第三方模块,比如常用的下列第三方模块:
a)nginx-sticky-module-ng:基于Cookie的会话保持模块
b)nginx_upstream_check_module:检查后端服务器健康模块
c)nginx-upstream-fair:比内建的负载均衡更加智能的负载均衡模块
因此,如果需要使用这些功能模块,我们通常需要基于源代码编译安装Nginx。
下面的安装过程使用的CentOS版本为CentOS 7.4.1708,即CentOS-7-x86_64-DVD-1708.iso
2) 删除已安装的Nginx
如果是通过yum或rpm非源码安装,删除命令如下:
# systemctl stop nginx
# systemctl disable nginx
# yum -y remove nginx
# rm -rf /usr/share/augeas/lenses/dist/nginx.aug
# rm -rf /usr/lib64/nginx
# rm -rf /var/lib/nginx
# rm -rf /var/log/nginx
# rm -rf /etc/nginx
# rm -rf /usr/share/nginx
# rm -rf /usr/local/lib64/perl5/auto/nginx
# rm -rf /usr/local/lib64/perl5/nginx.pm
# rm -rf /usr/lib/systemd/system/nginx.service
# rm -rf /etc/init.d/nginx
# rm -rf /usr/sbin/nginx
# rm -rf /run/nginx.pid
如果是通过源代码编译安装,删除命令如下:
如果编译源代码文件夹存在,进入源代码文件夹运行,
# make uninstall
如果不存在,则需要手动删除nginx,运行下面命令找到nginx安装了哪些文件及所在文件夹:
# find / | grep nginx
通常使用非源码安装中的rm命令即可删除。
3)下载编译安装所需的程序包和源代码
a)安装下载和编译基础程序包:
# yum -y install wget tar git gcc make pcre pcre-devel zlib zlib-devel
b)安装OpenSSL(如果是已经通过源代码编译安装了的OpenSSL,则不需安装):
# yum -y install openssl openssl-devel
c)安装Nginx附加模块所需依赖程序包:
# yum -y install GeoIP GeoIP-devel libxslt-devel gd gd-devel perl-ExtUtils-Embed
d)创建源代码文件夹并下载源代码:
# mkdir /usr/src/nginx
# cd /usr/src/nginx
# git clone https://github.com/gnosek/nginx-upstream-fair.git
# git clone https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng.git
# git clone https://github.com/yaoweibin/nginx_upstream_check_module.git
# wget http://nginx.org/download/nginx-1.14.0.tar.gz
# tar -xvzf nginx-1.14.0.tar.gz
# cd /usr/src/nginx/nginx-1.14.0
上面Nginx稳定版本是1.14.0(本人测试使用1.15.2也编译安装通过)
e)确认编译Nginx所需openssl库文件所在文件夹:
# find / | grep '\/ssl\.h\|\/libssl\.a\|\/libcrypto\.a'
通过yum或rpm安装的openssl(本人使用yum安装,OpenSSL版本为:OpenSSL 1.0.2k-fips,使用命令openssl version可查看版本信息),通常在 /usr/local 文件夹会找到ssl.sh、libssl.a和libcrypto.a三个文件(即确认了编译参数--with-openssl=/usr/local)。
f)修改源代码中配置文件:
# vi /usr/src/nginx/nginx-1.14.0/auto/lib/openssl/conf
找到:
CORE_INCS="$CORE_INCS $OPENSSL/.openssl/include"
CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h"
CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a"
CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a"
CORE_LIBS="$CORE_LIBS $NGX_LIBDL"
CORE_LIBS="$CORE_LIBS $NGX_LIBPTHREAD"
替换为:
CORE_INCS="$CORE_INCS $OPENSSL/include"
CORE_DEPS="$CORE_DEPS $OPENSSL/include/openssl/ssl.h"
CORE_LIBS="$CORE_LIBS $OPENSSL/lib64/libssl.a"
CORE_LIBS="$CORE_LIBS $OPENSSL/lib64/libcrypto.a"
CORE_LIBS="$CORE_LIBS $NGX_LIBDL"
CORE_LIBS="$CORE_LIBS $NGX_LIBPTHREAD"
(或者,编译时可以不使用--with-openssl参数,而是直接将配置文件中的$OPENSSL使用实际路径替换)
4)执行下面命令编译并安装
# ./configure --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -m64 -Wl,-E' --user=nginx --group=nginx --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --pid-path=/var/run/nginx.pid --lock-path=/var/lock/subsys/nginx --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --with-openssl=/usr/local --with-debug --with-compat --with-file-aio --with-http_auth_request_module --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_sub_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-http_geoip_module=dynamic --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_slice_module --with-http_perl_module=dynamic --add-module=/usr/src/nginx/nginx-sticky-module-ng --add-module=/usr/src/nginx/nginx_upstream_check_module
# make
# make install
# openssl dhparam -out /etc/nginx/dhparams.pem 2048
创建Nginx运行所需文件夹及权限设置:
# mkdir /etc/nginx/conf.d
# mkdir /etc/nginx/default.d
# mkdir /usr/share/nginx/logs
# mkdir -p /var/lib/nginx/tmp/client_body
# mkdir -p /var/lib/nginx/tmp/proxy
# mkdir -p /var/lib/nginx/tmp/fastcgi
# mkdir -p /var/lib/nginx/tmp/uwsgi
# mkdir -p /var/lib/nginx/tmp/scgi
# chown -R nginx.nginx /var/lib/nginx/
# chmod -R 770 /var/lib/nginx/
5)创建自启动脚本
a)使用systemd服务方式(Nginx执行程序支持,强烈建议):
# vi /usr/lib/systemd/system/nginx.service
内容如下:
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
启用nginx.service:
# systemctl enable nginx.service
启动Nginx:
# systemctl start nginx
停止Nginx:
# systemctl stop nginx
b)使用init.d脚本:
# vi /etc/init.d/nginx
内容如下:
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin
#
# chkconfig: - 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /etc/nginx/nginx.conf
# pidfile: /var/run/nginx.pid
# user: nginx
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
nginx="/usr/sbin/nginx"
prog=$(basename $nginx)
NGINX_CONF_FILE="/etc/nginx/nginx.conf"
lockfile=/var/run/nginx.lock
start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
echo -n $"Starting $prog: "
daemon $nginx -c $NGINX_CONF_FILE
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
killproc $prog -QUIT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
configtest || return $?
stop
start
}
reload() {
configtest || return $?
echo -n $"Reloading $prog: "
killproc $nginx -HUP
RETVAL=$?
echo
}
force_reload() {
restart
}
configtest() {
$nginx -t -c $NGINX_CONF_FILE
}
rh_status() {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
exit 2
esac
启用nginx:
# chkconfig --add nginx
# chkconfig --level 345 nginx on
启动Nginx:
# service nginx start
停止Nginx:
# service nginx stop
检查Nginx版本及支持的模块:
# nginx -V
检查Nginx配置文件是否正确:
# nginx -t
6)常见问题及解决办法
a)自动跳转至80端口
Nginx默认反向后的端口为80,因此存在被代理后的端口为80的问题,这就导致访问出错。主要原因在Nginx的配置文件的host配置时没有设置响应的端口。
错误的配置文件如下:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
如上,Host配置只有host,没有对应的port,这就导致在被代理的地方取得错误的端口。本文以java为例:
String scheme = httpRequest.getScheme();
String serverName = httpRequest.getServerName();
int port = httpRequest.getServerPort();
//服务请求地址
String requestURI = scheme+"://"+serverName+":"+port+"/index.jsp";
这时,取得的port为80,虽然nginx监听的端口为8080。于是,修改nginx的配置文件,将Host后面的改为 $host:$server_port即可,正确的配置文件如下:
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
b)Nginx无法启动或停止
通常以systemd服务方式配置Nginx自启动时,如果 /etc/nginx/nginx.conf 文件中配置了:
pid logs/nginx.pid;
将可能导致使用命令systemctl start nginx和systemctl stop nginx无法启动或停止Nginx服务,因此需要删除该配置行。
c)使用Cookie会话保持
首先确认Nginx编译包含了nginx-sticky-module-ng第三方模块(命令为:nginx -V),在 /etc/nginx/nginx.conf 文件中的upstream片段中增加sticky配置,如:
upstream bim-server.backend {
#ip_hash;
sticky name=myapp_route hash=md5;
server 192.168.0.1:8080 weight=1 max_fails=3 fail_timeout=60s;
server 192.168.0.2:8080 weight=1 max_fails=3 fail_timeout=60s;
server 192.168.0.3:8080 weight=1 max_fails=3 fail_timeout=60s;
}
(ip_hash和sticky不要同时使用,参考:https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng)
d)如何查看已安装程序包信息(包括版本),如:查看OpenSSL程序包
使用yum查看:
# yum list installed | grep 'openssl'
使用rpm查看:
# rpm -qa | grep 'openssl'
如果是源代码编译安装的,只能手动确认可执行文件是否存在。如果是以root用户安装的,可执行程序通常都在/sbin或/usr/bin目录下。
7)资源参考
a)Nginx第三方模块列表:https://www.nginx.com/resources/wiki/modules/
b)Nginx动态模块清单:https://www.nginx.com/products/nginx/modules/