如果您使用动态模块,您可能会在升级到新的 NGINX 或 NGINX Plus 版本时看到如下错误:
设置 nginx-plus (1.11.10-1~xenial) ... nginx:[emerg] 模块“/etc/nginx/modules/ngx_http_geoip_module.so”版本 1011005 而不是 /etc/nginx/nginx.conf:7 中的 1011006 nginx:配置文件 /etc/nginx/nginx.conf 测试失败,invoke-rc.d:initscript nginx,操作“升级”失败。
最可能的原因是,您没有升级指定的动态模块( .so文件):
为了简洁起见,从现在开始我们将仅引用 NGINX Plus。
请放心,此错误消息并不表示您的 NGINX Plus 服务器已关闭。 NGINX Plus 升级是无缝的,因此当升级失败时,旧版本仍继续运行。 但是,升级不完整,并且您的系统处于不一致状态:
不要手动重启nginx
,或者重启系统。 这样做会导致停机,因为当动态模块与新的 NGINX Plus 版本不同步时,新的 NGINX Plus 进程无法启动。
请注意,错误消息仅与升级过程中发现的第一个不兼容模块有关,因此在配置中找到所有load_module
指令并确保每个模块都针对适当的 NGINX 版本进行编译非常重要。 每个 NGINX Plus 版本都提供了所有由 NGINX 编写和认证的第三方动态模块的正确版本,因此您只需重新编译未经认证的模块。本文介绍如何安全地完成升级过程。
NGINX 1.11.5 和NGINX Plus R11引入了针对 NGINX Open Source 编译动态模块并将其加载到 NGINX Plus 中的功能。 这种二进制兼容性要求模块和 NGINX Plus 共享相同的基础开源版本。 由于版本不匹配,在未先安装针对相应 NGINX 开源版本构建的动态模块的情况下升级 NGINX Plus 会失败。
如果您的动态模块是由第三方供应商提供的,那么您需要联系供应商获取新版本,该新版本与您打算升级到的 NGINX Plus 版本的 NGINX 版本相匹配。 如果您的动态模块是从源代码编译的(并且您可以访问源代码)那么继续阅读。
我们强烈建议您在单独的系统上编译动态模块,我们在此将其称为“构建环境”。 这样做可以最大限度地降低运行带有动态模块的 NGINX Plus 的系统的风险和复杂性(我们将其称为“生产环境”)。 构建环境必须与生产环境具有相同的操作系统和版本;此外,还必须安装以下组件:
为了确保您的构建环境已安装这些先决条件,请运行以下命令。
对于 Ubuntu/Debian:
buildenv$ sudo apt-get install unzip gcc make libpcre3-dev zlib1g-dev
对于 CentOS/RHEL/Oracle Linux:
buildenv$ sudo yum install unzip gcc make pcre-devel zlib-devel
在生产环境中,运行以下命令来识别与正在运行的 NGINX Plus 版本相对应的 NGINX 开源版本。 在此输出中它以橙色突出显示: NGINX 1.11.10,对应 NGINX Plus R12。
生产$ nginx -v nginx 版本:nginx/ 1.11.10(nginx-plus-r12)
在构建环境中,下载适当 NGINX 开源版本的源代码。
build-env$ wget -qO - http://nginx.org/download/nginx-1.11.10 .tar.gz | tar zxfv -
将动态模块的源代码复制到您选择的构建目录。 这里我们从 GitHub 存储库复制一个示例 NGINX“hello world”模块。
buildenv$ git clone https://github.com/perusio/nginx-hello-world-module.git克隆到‘nginx-hello-world-module’...
首先运行带有--with-compat
参数的 NGINX配置
脚本来编译动态模块,以使动态模块与 NGINX Plus 二进制兼容。 然后运行make
modules
来编译模块。
buildenv$ cd nginx-1.11.10/ buildenv$ ./configure --with-compat --add-dynamic-module=../nginx-hello-world-module buildenv$ make modules
验证构建过程是否已在objs子目录中将动态模块创建为.so文件。
buildenv$ ls objs/*.so objs/ngx_http_hello_world.so
创建模块文件的副本,文件名中包含 NGINX 开源版本。 这使得在生产环境中管理动态模块的多个版本变得更加简单。
buildenv$ cp objs/ngx_http_hello_world.so ./ngx_http_hello_world_1.11.10.so
因为我们创建了文件名中包含 NGINX 开源版本的动态模块,所以我们可以安全地将其复制到生产环境而不会影响操作。
buildenv$ scp ./ngx_http_hello_world_1.11.10.so 生产:/etc/nginx/modules
在生产环境中,用新的.so文件替换当前文件。 此时这样做是安全的,因为只有在nginx
重新启动或重新加载配置时,动态模块才会加载到内存中。
生产$ cd /etc/nginx/modules生产$ cp ngx_http_hello_world.so ngx_http_hello_world_ROLLBACK.so生产$ ln -fs ngx_http_hello_world_1.11.10.so ngx_http_hello_world.so生产$ ls -gG -rw-r--r-- 1 243576 Jan 31 16:18 ngx_http_hello_world_1.11.10.so -rw-r--r-- 1 243576 Oct 20 10:40 ngx_http_hello_world_ROLLBACK.so lrwxrwxrwx 1 24 Jan 31 16:26 ngx_http_hello_world.so -> ngx_http_hello_world_1.11.10.so
运行以下命令来测试模块版本是否正确以及 NGINX Plus 是否准备好完成升级过程。
production$ nginx -t nginx:配置文件/etc/nginx/nginx.conf语法正确 nginx:配置文件/etc/nginx/nginx.conf测试成功
完成升级过程,以便 NGINX Plus 使用新版本和动态模块。
生产$服务 nginx 升级启动新的主 nginx:[确定] 正常关闭旧 nginx:[确定]
下次升级 NGINX Plus 时,您可以在升级前按照这些说明进行操作,以节省时间并避免错误,以便在开始升级过程时更新的动态模块已经可用。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”