为何Nginx按日期命名日志时access日志生效而error日志无效?
解决Nginx error_log变量未解析的问题
问题原因
Nginx的error_log和access_log初始化时机存在差异:
access_log会在第一个请求到达时才打开并写入日志,此时请求相关的变量(如$time_iso8601、map生成的变量)已完成解析,因此能正常生成带日期的文件名。- 若
error_log配置在http块,它会在Nginx启动阶段就尝试初始化文件,此时尚无请求上下文,请求级别的变量无法被解析,最终直接输出变量名(如error.$year-$month.log)。
解决办法
方法1:将error_log移到server块,用set指令提取日期
在server块内部通过if指令从$time_iso8601中提取日期变量,再配置error_log:
server { listen 80; server_name example.com; # 从$time_iso8601提取年-月(如需按天分割,调整正则为^(\d{4})-(\d{2})-(\d{2})) set $log_date ""; if ($time_iso8601 ~ "^(\d{4})-(\d{2})") { set $log_date "$1-$2"; } # 配置带日期的日志文件 error_log /var/log/nginx/error.$log_date.log; access_log /var/log/nginx/access.$log_date.log; # 其他server配置... }
当第一个请求到达该server时,$log_date变量会被解析,error_log会自动创建正确命名的日志文件。
方法2:保留http块的map指令,将error_log移到server块
如果习惯用map统一管理日期变量,只需把error_log的配置从http块移到server块即可:
http { # 从$time_iso8601提取年-月变量 map $time_iso8601 $log_yearmonth { ~^(\d{4}-\d{2}) $1; default ""; } # 其他http配置... server { listen 80; server_name example.com; # 在server块中使用map生成的变量 error_log /var/log/nginx/error.$log_yearmonth.log; access_log /var/log/nginx/access.$log_yearmonth.log; # 其他server配置... } }
注意事项
- 日志文件会在当天第一个请求到来时创建,而非提前生成;若需按天分割,调整正则表达式提取到日即可(如
~^(\d{4}-\d{2}-\d{2}) $1)。 - 确保Nginx进程对日志目录(如
/var/log/nginx/)有写入权限。 - 若有多台server,每台server的
error_log会独立生成对应日期的文件;若需全局统一的error日志,可将所有server的error_log指向同一个带变量的路径。
内容的提问来源于stack exchange,提问作者stack92
相关产品推荐
相关产品推荐

