本文介绍如何在 Nginx 泛域名日志记录子域名
配置示例一:文本日志
NGINX 提供了 $host
变量。这个变量的值是客户端请求头 Host 字段的内容。例如,当用户访问 sub1.xiexianbin.cn 时,$host
的值就是 sub1.xiexianbin.cn。配置如下:
# 推荐将 log_format 定义在 http 块的顶层,以便多个 server 块可以复用
http {
# ... 其他 http 配置, 如 include, sendfile, keepalive_timeout 等 ...
# 1. 定义一个新的日志格式,命名为 'wildcard'
# 我们在标准的 combined 格式基础上,在最前面增加了 $host 变量。
# $host: 请求的主机名,例如 a.xiexianbin.cn
# $remote_addr: 客户端 IP 地址
# $remote_user: 用于 HTTP 认证的用户名
# $time_local: 服务器本地时间
# "$request": 原始请求行, e.g., "GET /index.html HTTP/1.1"
# $status: HTTP 响应状态码, e.g., 200, 404
# $body_bytes_sent: 发送给客户端的响应体大小(字节)
# "$http_referer": 请求的来源页面
# "$http_user_agent": 客户端的用户代理(浏览器)信息
# "$http_x_forwarded_for": 代理服务器传递的客户端真实 IP
log_format wildcard '$host - $remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 定义默认的访问日志,可以用于非泛域名的 server
access_log /var/log/nginx/access.log combined;
# ... 其他 http 配置 ...
# 2. 配置泛域名 server 块
server {
# 监听 80 端口
listen 80;
# listen [::]:80; # 如果需要监听 IPv6
# 关键配置:使用通配符或正则表达式来匹配所有子域名
# *.xiexianbin.cn 会匹配所有一级子域名,但不会匹配 xiexianbin.cn 本身
# 如果也想匹配主域名,可以写成 server_name .xiexianbin.cn; 或者 server_name xiexianbin.cn *.xiexianbin.cn;
server_name *.xiexianbin.cn;
# 3. 指定此 server 块的访问日志
# 路径:/var/log/nginx/wildcard.access.log
# 格式:使用我们上面定义的 wildcard 格式
access_log /var/log/nginx/wildcard.access.log wildcard;
# 网站根目录
root /var/www/html;
index index.html index.htm;
# 一个简单的 location 块,用于响应请求
location / {
try_files $uri $uri/ =404;
# 你也可以在这里根据 $host 变量做不同的处理
# 例如:proxy_pass http://$host;
}
# 错误日志
error_log /var/log/nginx/wildcard.error.log;
}
}
配置说明:
-
log_format wildcard ...
- 这行代码定义了一个名为
wildcard
的新日志格式。
- 它基于 NGINX 预设的
combined
格式,并在最前面添加了 $host
变量。当日志被写入时,$host
会被替换为实际请求的域名(如 sub1.xiexianbin.cn
或 another.xiexianbin.cn
)。
- 我将这个指令放在了
http
块的顶层,这是一个好习惯,因为它允许你在多个 server
块中重复使用这个格式。
-
server_name *.xiexianbin.cn;
- 这是泛域名配置的核心。星号
*
是一个通配符,代表任意字符串。
- 这行配置告诉 NGINX,任何以
.xiexianbin.cn
结尾的域名请求(例如 www.xiexianbin.cn
, api.xiexianbin.cn
, test.xiexianbin.cn
)都应该由这个 server
块来处理。
- 注意:
*.xiexianbin.cn
不会匹配根域名 xiexianbin.cn
。如果你也想让这个 server
块处理根域名,应该写成 server_name xiexianbin.cn *.xiexianbin.cn;
。
-
access_log /var/log/nginx/wildcard.access.log wildcard;
- 这行代码指定了此
server
块的访问日志。
- 第一个参数是日志文件的存放路径。建议为泛域名使用一个单独的日志文件,以方便管理。
- 第二个参数
wildcard
是我们之前用 log_format
定义的日志格式的名称。这使得 NGINX 使用包含 $host
的格式来记录日志。
配置示例二:json 日志
## 2\. 更新后的完整 NGINX 配置
现在我们将新的 `wildcard_json` 格式应用到泛域名 `server` 块中。
```nginx
http {
# ... 其他 http 配置 ...
# 1. 定义 JSON 日志格式
log_format wildcard_json escape=json
'{'
'"timestamp": "$time_iso8601",'
'"domain": "$host",'
'"client_ip": "$remote_addr",'
'"x_forwarded_for": "$http_x_forwarded_for",'
'"request": "$request",'
'"status": $status,'
'"body_bytes_sent": $body_bytes_sent,'
'"request_time": $request_time,'
'"referer": "$http_referer",'
'"user_agent": "$http_user_agent",'
'"remote_user": "$remote_user"'
'}';
# ... 其他 http 配置 ...
server {
listen 80;
server_name *.example.com;
# 2. 在 access_log 指令中使用新的 JSON 格式
access_log /var/log/nginx/wildcard.json.log wildcard_json;
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
error_log /var/log/nginx/wildcard.error.log;
}
}
关键点说明:
escape=json
: 这是 NGINX 1.11.8 版本及以后提供的关键功能。它会自动转义变量值中不符合 JSON 字符串规范的字符(例如 "
会被转义为 \"
),确保最终输出的是一行一个有效的 JSON 对象。
$time_iso8601
: 我们使用 ISO 8601 格式的时间戳(例如 2025-08-05T21:30:00+09:00
),这是机器可读的标准时间格式,比之前的 $time_local
更适合日志分析系统。
$request_time
: 一个非常有用的变量,记录了从接收到请求的第一个字节到发送完最后一个字节所花费的总时间(秒),可以用于性能监控和分析慢请求。
- 数值与字符串: 注意,在格式定义中,像
$status
, $body_bytes_sent
, $request_time
这些本身就是数值的变量,我们没有用引号包裹。这样在生成的 JSON 中它们就是数字类型,便于进行数值计算和统计。而其他变量则用引号包裹,成为 JSON 字符串。