nginx tcp代理需启用stream模块并配置顶层stream块内log_format与access_log,否则日志为空;必须满足--with-stream编译支持、正确位置定义日志格式、确保权限与连接触发条件。

TCP 代理模式下,Nginx 默认不记录访问日志——因为 http 模块的日志机制对 stream 流量完全无效。想监控 MySQL、Redis 或自定义 TCP 服务的连接行为,必须启用并正确配置 stream 模块的日志功能,否则你看到的只有空文件或根本无日志输出。
启用 stream 日志需满足两个前提
缺一不可:
-
编译时包含 --with-stream:运行
nginx -V 2>&1 | grep --with-stream,确认输出中存在该参数;若没有,需重编译或换用支持 stream 的发行版包(如 Ubuntu 22.04+ 官方源默认含此模块) -
全局配置中开启 stream 日志开关:在
nginx.conf的顶层(不在 http 块内),添加stream { log_format ...; access_log ...; },否则即使写了日志指令也无效
配置 stream 访问日志格式与路径
stream 日志格式独立于 http,需在 stream 块内显式定义:
- 使用
log_format声明格式,支持变量如$remote_addr、$server_addr、$time_iso8601、$status(连接建立成功为 1,失败为 0)、$bytes_sent、$bytes_received - 通过
access_log /path/to/stream.log stream_format_name;指定日志文件和格式名 - 示例配置片段:
stream { log_format stream_log '$remote_addr:$remote_port → $server_addr:$server_port [$time_iso8601] ' 'status=$status bytes_sent=$bytes_sent bytes_received=$bytes_received'; access_log /var/log/nginx/stream.log stream_log; upstream db_backend { server 10.0.1.10:3306; server 10.0.1.11:3306; } server { listen 3307; proxy_pass db_backend; proxy_timeout 30s; } }
常见日志为空的三个原因及修复
配置后日志仍为空?大概率是以下问题:
-
日志路径权限不足:Nginx worker 进程用户(通常是
www-data或nginx)必须对日志目录有写权限,建议执行sudo chown www-data:www-data /var/log/nginx/并确保父目录可写 -
未 reload 而是 restart:stream 模块加载依赖完整重载(
nginx -s reload),单纯systemctl restart nginx可能因进程残留导致新配置未生效 -
客户端未真正建立 TCP 连接:stream 日志只在连接建立/断开时触发,不像 HTTP 那样每请求一条。可用
telnet 服务器IP 3307或nc -zv IP port主动建连测试是否触发日志写入
用命令行或工具做基础流量分析
stream 日志是纯文本,适合快速排查,无需复杂平台:
- 统计每分钟连接数:
awk '{print substr($3,2,16)}' /var/log/nginx/stream.log | sort | uniq -c | sort -nr - 查高频来源 IP:
awk '{print $1}' /var/log/nginx/stream.log | cut -d: -f1 | sort | uniq -c | sort -nr | head -10 - 筛选异常连接(如频繁失败):
grep 'status=0' /var/log/nginx/stream.log | head -20 - 配合
ngxtop(需指定日志格式):ngxtop -l /var/log/nginx/stream.log --format='$remote_addr:$remote_port → $server_addr:$server_port \[$time_iso8601\] status=$status'
不复杂但容易忽略:stream 日志不是“开了就能用”,它需要位置对、权限对、触发条件对。配好之后,每条连接就是一行真实可观测的数据,比抓包更轻量,比监控指标更具体。











