模块加载失败时错误日志为空,因错误发生在日志系统初始化前;必须用nginx -e stderr捕获终端输出,结合nginx -V核验编译参数、ldd检查动态库依赖,并区分静态编译与动态模块的依赖要求。

模块加载失败时,错误日志往往为空或不包含关键信息——因为依赖库缺失发生在日志系统初始化之前,error_log 文件根本不会被打开。必须绕过日志文件,直接捕获启动早期的原始错误输出。
用 -e stderr 强制终端输出真实错误
这是最可靠、最直接的方法。运行以下命令:
/usr/local/nginx/sbin/nginx -c /path/to/nginx.conf -e stderr
常见典型输出包括:
- dlopen() failed to load module "ngx_http_brotli_filter_module.so": libbrotlienc.so.1: cannot open shared object file → 动态库缺失或路径未加入 ldconfig
- unknown directive "brotli" → 模块未编译进二进制,或 .so 文件未被 load_module 正确引用
- failed to initialize Lua VM: dlopen() failed for ... libluajit-5.1.so.2 → 第三方模块依赖的底层库(如 LuaJIT)未安装或版本不匹配
确认模块是否真被编译或加载
先验证 Nginx 二进制本身是否支持该模块:
nginx -V 2>&1 | grep -E "(with-http_ssl_module|add-module|with-stream)"
若报错指令(如 lua_code_cache)对应模块不在输出中,说明未编译;若使用动态模块,则还需检查配置中是否有对应行:
load_module modules/ngx_http_lua_module.so;
并确认该 .so 文件存在、可读,且其依赖库可用:
ldd modules/ngx_http_lua_module.so | grep "not found"
检查依赖库是否真正就位
不能只看“是否装了包”,要看头文件、静态库、动态库三者是否齐全,尤其注意开发包(如 libbrotli-dev、libluajit-5.1-dev)是否安装:
- 查头文件:ls /usr/include/brotli/encode.h 或 ls /usr/local/include/lua.h
- 查动态库:find /usr -name "libbrotlienc.so*" 2>/dev/null
- 查运行时链接路径:echo $LD_LIBRARY_PATH,或确保库所在目录已加入 /etc/ld.so.conf.d/ 并执行 ldconfig
区分静态编译与动态模块的依赖逻辑
二者对依赖库的要求不同,容易混淆:
- 静态编译(
--add-module=../ngx_brotli):configure 阶段需找到libbrotlienc.a,否则链接失败 - 动态模块(
--add-dynamic-module=../ngx_brotli):运行时才加载,但要求.so及其所有依赖(如libbrotlidec.so.1)在系统库路径中可寻址 - 若动态模块报 “cannot open shared object file”,优先运行 ldd your_module.so 查缺项


















