首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Log4j 日誌時間偏移 8 小時與重複輸出問題排查解決實錄

     編輯:Java 綜合教學

Log4j 日誌時間偏移 8 小時與重複輸出問題排查解決實錄

生產環境日誌系統常遇到兩類「看似玄學、實則配置/環境問題」:日誌時間與系統時間相差 8 小時 (時區問題)、同一日誌重複打印多次 (Appender 重複引用)。本文記錄真實排查過程與根因修復方案。

一、 問題 1:日誌時間比系統時間少 8 小時

現象描述

  • Eclipse 控制台輸出時間正確 (北京時間 UTC+8)。
  • Log4j 寫入文件的日誌時間比系統時間**慢 8 小時** (顯示為 UTC 時間)。
  • JVM 參數未顯式設置 -Duser.timezone。

根因分析

Log4j (log4j 1.x / log4j2) 獲取時間戳最終依賴 java.util.Date 或 System.currentTimeMillis(),格式化時使用 TimeZone.getDefault()。若 JVM 啟動時未檢測到正確時區,會回退到 **GMT (UTC)**。Tomcat 作為獨立進程,其啟動腳本未傳遞時區參數,導致 JVM 默認時區為 GMT,而 Eclipse 啟動時繼承了 IDE/系統環境時區 (Asia/Shanghai),故控制台正常、文件異常。

解決方案:在 Tomcat 啟動腳本中強制設置 JVM 時區

Windows 環境 (catalina.bat)
rem 在 set _EXECJAVA=... 等變量定義之後、執行啟動命令之前插入
set JAVA_OPTS=%JAVA_OPTS% -Duser.timezone=Asia/Shanghai

或直接在 set _EXECJAVA=... 後添加:

set _EXECJAVA=%_EXECJAVA% -Duser.timezone=Asia/Shanghai
Linux 環境 (catalina.sh / setenv.sh)

建議創建 bin/setenv.sh (Tomcat 會自動加載):

#!/bin/bash
export JAVA_OPTS="$JAVA_OPTS -Duser.timezone=Asia/Shanghai"

賦予執行權限:chmod +x bin/setenv.sh。

驗證

重啟 Tomcat,日誌時間恢復北京時間。也可在應用啟動時打印驗證:log.info("JVM Default TimeZone: {}", TimeZone.getDefault().getID()); 應輸出 Asia/Shanghai。

注意:網上流傳的 -Duser.timezone=GMT+08 寫法**不標準**,Java 時區 ID 必須使用 IANA 時區數據庫格式 (如 Asia/Shanghai、America/New_York),GMT+08 可能在某些 JDK 版本無法正確識別夏令時規則。

二、 問題 2:日誌重複輸出 (每條日誌打印兩次)

現象描述

2016-04-22 01:51:28,427 [DEBUG] ... HouseKeeper - Testing connection 2: True
2016-04-22 01:51:28,427 [DEBUG] ... HouseKeeper - Testing connection 2: True  <-- 重複行

配置片段 (log4j.properties)

log4j.rootLogger=ERROR, stdout, R, proxool
log4j.logger.org.logicalcobwebs.proxool=DEBUG, proxool

根因分析:Logger 繼承性導致 Appender 重複引用

  1. rootLogger 關聯了 proxool Appender。
  2. org.logicalcobwebs.proxool Logger 顯式設置級別為 DEBUG,**並再次關聯了同一個 proxool Appender**。
  3. 該 Logger 繼承自 rootLogger,默認 additivity=true (繼承父 Logger 的 Appender)。
  4. 結果:該包下的日誌事件**同時被發送給兩個相同的 proxool Appender** → 重複寫入文件。

解決方案:移除重複引用或關閉繼承

方案 A (推薦):rootLogger 移除 proxool,僅在專用 Logger 掛載
log4j.rootLogger=ERROR, stdout, R
log4j.logger.org.logicalcobwebs.proxool=DEBUG, proxool
方案 B:保持 rootLogger 掛載,專用 Logger 關閉繼承
log4j.rootLogger=ERROR, stdout, R, proxool
log4j.logger.org.logicalcobwebs.proxool=DEBUG, proxool
log4j.additivity.org.logicalcobwebs.proxool=false
原則:一個 Appender 只應被一個 Logger 直接引用,避免通過繼承鏈重複接收事件。同理,Log4j2 XML 配置中 <Logger additivity="false"> 同樣適用。

三、 總結避坑清單

問題核心原因修復要點
日誌時間偏移 8hTomcat JVM 默認時區為 GMT啟動腳本強制 -Duser.timezone=Asia/Shanghai
日誌重複輸出Logger 繼承 + 重複引用同一 Appender移除重複引用 或 設置 additivity=false
日誌亂碼文件編碼與 JVM file.encoding 不一致統一 UTF-8,啟動參數 -Dfile.encoding=UTF-8
日誌丟失/不輸出級別過高 / Appender 閾值過高 / 路徑無權限檢查 Logger/Root 級別、Appender Threshold、磁盤權限

日誌系統是系統的「黑匣子」,時間準確、輸出唯一、編碼正確是其可用性的底線。將時區參數固化在啟動腳本、嚴格控制 Appender 引用拓撲、統一 UTF-8 編碼鏈路,能消除 90% 以上的日誌基礎設施故障。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved