用map指令动态设置access_log路径是最稳定可扩展的海量域名日志管理方式,通过清洗$host、提取$time_iso8601日期、拼接扁平化路径并配合logrotate实现自动归档清理。

用 map 指令动态设置 access_log 路径,是应对海量域名日志管理最稳定、可扩展性最强的方式。核心不靠脚本或外部工具,而是在 Nginx 配置层完成变量提取与路径拼接,让每个域名、每天的日志自动落入独立文件,无需为新增站点反复改配置。
安全提取域名作为目录名
直接用 $host 做路径有风险:含下划线、点号、特殊字符或恶意构造的 host 可能导致写入失败甚至越权。必须先做清洗:
- 用
map匹配合法子域名结构,只保留字母、数字和短横线 - 对通配符泛域名(如
*.example.com)统一映射为wildcard或按主域归类 - 兜底设
default _invalid,避免空值或非法值导致日志写入根目录
示例:
将 WCAG 2 AA 无障碍标准应用于设计系统、UI 组件和网页——通过可运行的验证器进行对比度计算,采用设计 token 模式使颜色天生可访问,设定排版和焦点状态规则,并提供语义检查清单。适用于构建或审查 UI。
map $host $safe_host {
default _invalid;
~^([a-zA-Z0-9\-]+)\.example\.com$ $1;
~^([a-zA-Z0-9\-]+)\.myapp\.io$ $1;
~^api\.(?<d>[a-z0-9\-]+)\.com$ api_$d;
}</d>从时间变量中稳定提取日期
$time_iso8601 格式固定(如 2026-04-30T12:45:22+08:00),适合正则提取;$time_local 易受时区/格式化影响,不推荐。
- 用命名捕获组提取年、月、日,组合成
2026/04/30或20260430格式 - 必须设
default值,确保变量始终有输出(Nginx 不允许日志路径为空) - 避免在
if中用set提取——它不能出现在http块,且无默认回退机制
示例:
map $time_iso8601 $log_day {
"~^(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})" "$y/$m/$d";
default "unknown";
}</d></m></y>拼接路径并启用日志写入
路径需满足两个前提:目录可写、层级存在。Nginx 不会自动创建多级目录,所以建议用较扁平结构(如按域名+年月日),或配合 systemd/timer 定期创建目录。
- 最终路径形如:
/var/log/nginx/sites/$safe_host/$log_day/access.log - 注意:路径中不能出现 shell 语法(如
$(date +...)),所有变量必须由 Nginx 原生支持 - 若启用了
open_log_file_cache,需确认缓存 key 是否包含动态变量(建议关闭缓存或增大min_uses)
server 块内配置示例:
access_log /var/log/nginx/sites/$safe_host/$log_day/access.log main; error_log /var/log/nginx/sites/$safe_host/error.log warn;
配套 logrotate 实现自动归档与清理
仅靠 Nginx 动态路径只能做到“按天分文件”,但不会自动压缩、轮转或删除旧日志。必须搭配 logrotate:
- 配置
daily+dateext,与 Nginx 日志名保持一致(如access.log-20260430) - 用
prerotate创建当天目录(如mkdir -p /var/log/nginx/sites/example/2026/04/30) - 设
maxage 30自动清理 30 天前的归档日志
logrotate 配置片段:
/var/log/nginx/sites/*/*/access.log {
daily
dateext
dateformat -%Y%m%d
missingok
rotate 30
compress
delaycompress
notifempty
create 0644 www-data www-data
sharedscripts
prerotate
mkdir -p $(dirname $1)/$(date -d 'today' +\%Y/\%m/\%d) 2>/dev/null || true
endscript
}










