在上一篇的文章中,
學習如何安裝 echo-nginx-module
這個第三方模組。
今天就來試試看第二種動態安裝模組的方式。
首先安裝相關依賴 pcre2
zlib
openssl
apk add pcre2-dev
apk add zlib-dev
apk add openssl
這邊我們選擇下載 echo-nginx-module
這個第三方模組與 Nginx 原始碼。
wget -P ~ https://github.com/openresty/echo-nginx-module/archive/refs/tags/v0.63.tar.gz
tar zxf v0.63.tar.gz
wget -P ~ https://nginx.org/download/nginx-1.26.1.tar.gz
tar zxf nginx-1.26.1.tar.gz
cd ~/nginx-1.26.1
注意這邊設定的時候就不需要添加 --add-module
參數了 --with-compat
這個新的參數可以讓之後編譯模組時能夠比較方便添加到 Nginx 內部,
建議之後編譯 Nginx 都添加上去。
./configure \
--prefix=/var/lib/nginx \
--modules-path=/usr/lib/nginx/modules \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--pid-path=/run/nginx/nginx.pid \
--lock-path=/run/nginx/nginx.lock \
--with-http_ssl_module \
--with-compat
設定完後進行安裝,到這邊就是一般的編譯與安裝流程。
make && make install
現在開始就是編譯動態模組的流程了,這邊使用 --add-dynamic-module
並不是使用 --add-module
參數
./configure \
--with-compat \
--add-dynamic-module=/root/echo-nginx-module-0.63
另外如果編譯 Nginx 時並沒有使用 --with-compat
參數的話,下個設定編譯動態模組的步驟就可以不用帶入 --with-compat
,
取額代之的是要把當初編譯的參數全部帶進來,之後載入模組才能正常運作。
因為編譯Nginx 跟編譯模組可能是不同人或電腦進行操作的所以可以使用 -V
參數查看編譯時所帶入的參數,也就是最底下的 configure arguments
。
$ nginx -V
nginx version: nginx/1.26.1
built by gcc 12.2.1 20220924 (Alpine 12.2.1_git20220924-r10)
built with OpenSSL 3.1.4 24 Oct 2023
TLS SNI support enabled
configure arguments: --prefix=/var/lib/nginx --modules-path=/usr/lib/nginx/modules --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/run/nginx/nginx.pid --lock-path=/run/nginx/nginx.lock --with-http_ssl_module
所以我們編譯的時候沒有使用 --with-compat
參數就需要輸入以下命令之後模組才能正常運作。
./configure \
--prefix=/var/lib/nginx --modules-path=/usr/lib/nginx/modules --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/run/nginx/nginx.pid --lock-path=/run/nginx/nginx.lock --with-http_ssl_module \
--add-dynamic-module=/root/echo-nginx-module-0.63
也可以使用以下命令自動去抓 configure arguments
內容。
./configure \
$(nginx -V 2>&1 | egrep "^configure" | cut -d: -f2) \
--add-dynamic-module=/root/echo-nginx-module-0.63
最後使用以下命令來編譯模組,編譯的結果會輸出到 objs
這個資料夾內部。
make modules
注意到 ngx_http_echo_module.so
這個副檔名為 so
的檔案就是我們編譯後的結果。
$ ls -lh ~/nginx-1.26.1/objs/
total 5M
-rw-r--r-- 1 root root 46.1K Aug 7 08:29 Makefile
drwxr-xr-x 3 root root 17 Aug 7 08:29 addon
-rw-r--r-- 1 root root 19.6K Aug 7 08:29 autoconf.err
-rwxr-xr-x 1 root root 4.3M Aug 7 08:28 nginx
-rw-r--r-- 1 root root 5.4K Aug 7 08:28 nginx.8
-rw-r--r-- 1 root root 8.1K Aug 7 08:29 ngx_auto_config.h
-rw-r--r-- 1 root root 657 Aug 7 08:29 ngx_auto_headers.h
-rwxr-xr-x 1 root root 433.0K Aug 7 08:29 ngx_http_echo_module.so
-rw-r--r-- 1 root root 339 Aug 7 08:29 ngx_http_echo_module_modules.c
-rw-r--r-- 1 root root 18.3K Aug 7 08:29 ngx_http_echo_module_modules.o
-rw-r--r-- 1 root root 5.9K Aug 7 08:29 ngx_modules.c
-rw-r--r-- 1 root root 26.6K Aug 7 08:28 ngx_modules.o
drwxr-xr-x 9 root root 91 Aug 7 08:27 src
完成後參考 --modules-path
的路徑把這個 ngx_http_echo_module.so
複製過去。
mkdir -p /usr/lib/nginx/modules
cp ~/nginx-1.26.1/objs/ngx_http_echo_module.so /usr/lib/nginx/modules
到此為止只剩下最後一個步驟就是編輯 nginx.conf
並使用 load_module
指令通知 Nginx 有新的模組需要載入。
vi /etc/nginx/nginx.conf
worker_processes 1;
load_module /usr/lib/nginx/modules/ngx_http_echo_module.so;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /echo {
default_type text/plain;
echo hello, world!$arg_text1$arg_text2;
}
location /echo_with_sleep {
echo hello;
echo "sleep 3 second";
echo_flush;
echo_sleep 3;
echo world;
}
location /echo_with_timer {
echo_reset_timer;
echo_sleep 3; # in sec
echo hello world;
echo "'hello world' takes about $echo_timer_elapsed sec.";
}
location /echo_with_exec {
echo_exec /hello text1=$arg_mytext1&text2=$arg_mytext2;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
最後重啟 Nginx 並測試,能看到回傳代表我們的模組已經動態加載成功。
nginx -s reload
$ curl "127.0.0.1/echo"
hello, world!
Problem
- 這個錯誤代表編譯的動態模組參數有問題。
nginx: [emerg] module "/usr/lib/nginx/modules/ngx_http_echo_module.so" is not binary compatible in /etc/nginx/nginx.conf:11
正確的流程如下列:
- 編譯 Nginx 有帶入
--with-compat
參數,編譯動態模組時需要帶入--with-compat
參數,並且可以省略configure arguments
。 - 編譯 Nginx 沒有帶入
--with-compat
參數,編譯動態模組時不能帶入--with-compat
參數,並且要添加configure arguments
。
會跳出錯誤如下列:
- 編譯 Nginx 有帶入
--with-compat
參數,編譯動態模組時沒有帶入--with-compat
參數。 - 編譯 Nginx 有帶入
--with-compat
參數,編譯動態模組時沒有帶入--with-compat
參數並且添加configure arguments
。 - 編譯 Nginx 沒有帶入
--with-compat
參數,編譯動態模組時帶入--with-compat
參數。 - 編譯 Nginx 沒有帶入
--with-compat
參數,編譯動態模組時帶入--with-compat
參數並且添加configure arguments
。
- 這個錯誤代表添加
load_module
指令時位置不對,只需要把load_module
提升到最上方即可。
nginx: [emerg] "load_module" directive is specified too late in /etc/nginx/nginx.conf:16
Alpine
最後來看看使用 --add-dynamic-module
的好處,這裡可以看一下 Alpine 是怎麼處理的,
我們先安裝 Alpine 打包的 Nginx。
可以看到 Alpine 在編譯 Nginx 時就已經把 --add-dynamic-module
帶入進來了,並且沒有使用 --with-compat
參數
apk add nginx
$ nginx -V
nginx version: nginx/1.24.0
built with OpenSSL 3.1.3 19 Sep 2023 (running with OpenSSL 3.1.4 24 Oct 2023)
TLS SNI support enabled
configure arguments:
--prefix=/var/lib/nginx
--sbin-path=/usr/sbin/nginx
--modules-path=/usr/lib/nginx/modules
--conf-path=/etc/nginx/nginx.conf
--pid-path=/run/nginx/nginx.pid
--lock-path=/run/nginx/nginx.lock
--http-client-body-temp-path=/var/lib/nginx/tmp/client_body
--http-proxy-temp-path=/var/lib/nginx/tmp/proxy
--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-perl_modules_path=/usr/lib/perl5/vendor_perl
--user=nginx
--group=nginx
--with-threads
--with-file-aio
--without-pcre2
--with-http_ssl_module
--with-http_v2_module
--with-http_realip_module
--with-http_addition_module
--with-http_xslt_module=dynamic
--with-http_image_filter_module=dynamic
--with-http_geoip_module=dynamic
--with-http_sub_module
--with-http_dav_module
--with-http_flv_module
--with-http_mp4_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_auth_request_module
--with-http_random_index_module
--with-http_secure_link_module
--with-http_degradation_module
--with-http_slice_module
--with-http_stub_status_module
--with-http_perl_module=dynamic
--with-mail=dynamic
--with-mail_ssl_module
--with-stream=dynamic
--with-stream_ssl_module
--with-stream_realip_module
--with-stream_geoip_module=dynamic
--with-stream_ssl_preread_module
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/njs-0.7.11/nginx
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_devel_kit-0.3.2/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/traffic-accounting-nginx-module-2.0/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/array-var-nginx-module-0.06/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-auth-jwt-0.2.1/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_brotli-1.0.0rc/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_cache_purge-2.5.3/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx_cookie_flag_module-1.1.0/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-dav-ext-module-3.0.0/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/echo-nginx-module-0.63/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/encrypted-session-nginx-module-0.09/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx-fancyindex-0.5.2/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_http_geoip2_module-3.4/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/headers-more-nginx-module-0.34/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-keyval-0.1.0/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-log-zmq-1.0.0/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/lua-nginx-module-0.10.24/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/lua-upstream-nginx-module-0.07/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/naxsi-1.3/naxsi_src
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nchan-1.3.6/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/redis2-nginx-module-0.15/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/set-misc-nginx-module-0.33/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-http-shibboleth-2.0.1/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_http_untar_module-1.1/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-upload-module-2.3.0/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-upload-progress-module-0.9.2/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-upstream-fair-0.1.3/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/ngx_upstream_jdomain-1.4.0/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-vod-module-1.31/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-module-vts-0.2.1/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/mod_zip-1.3.0/
--add-dynamic-module=/home/buildozer/aports/main/nginx/src/nginx-rtmp-module-1.2.2/
沒有使用 --with-compat
參數就會造成一個問題,那就是如果我今天想要添加模組到 Alpine 打包的 Nginx 的話我就必須參考他當初編譯模組的
路徑也就是 /home/buildozer/aports/main/nginx/src
這個路徑底下,操作起來會比較麻煩。
接下來編譯完動態模組後 Alpine 會進行上傳,所以我們可以使用 apk install
直接下載動態模組,先使用 apk list
尋找所有 Nginx 模組。
[node1] (local) root@192.168.0.8 ~
$ apk list nginx-mod*
nginx-mod-devel-kit-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-accounting-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-array-var-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-auth-jwt-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-brotli-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-cache-purge-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-cookie-flag-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-dav-ext-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-echo-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-encrypted-session-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-fancyindex-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-geoip-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-geoip2-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-headers-more-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-image-filter-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-js-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-keyval-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-log-zmq-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-lua-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-lua-upstream-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-naxsi-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-nchan-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-perl-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-redis2-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-set-misc-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-shibboleth-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-untar-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-upload-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-upload-progress-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-upstream-fair-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-upstream-jdomain-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-vod-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-vts-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-xslt-filter-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-http-zip-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-mail-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-rtmp-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-stream-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-stream-geoip-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-stream-geoip2-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
nginx-mod-stream-js-1.24.0-r7 x86_64 {nginx} (BSD-2-Clause)
接下來使用 apk 安裝 echo 模組
apk add nginx-mod-http-echo
可以使用模組管理網頁來查看這個包裡面有什麼內容
- /etc/nginx/modules/10_http_echo.conf #只有一段指令
load_module "modules/ngx_http_echo_module.so";
- /usr/lib/nginx/modules/ngx_http_echo_module.so #編譯後的 so 模組檔案
這樣重啟 Nginx 後就動態模組就載入成功了。
Summary
今天學習如何動態載入第三方的模組,這種方式可以快速載入新的功能,也可以避免重新編譯 Nginx,
如果當初規劃就已經確定要使用某個第三方模組那麼使用 --add-module
參數也是不錯的選擇。