<-
Apache > HTTP Server > 文件 > 版本 2.4

日誌檔案

可用語言:  en  |  fr  |  ja  |  ko  |  tr 

要有效率地管理網站伺服器,有必要回報關於伺服器的活動和效能,還有問題的發生。Apache HTTP Server 提供非常全面和彈性的紀錄功能。這份文件描述如何設定它的記錄功能,以及如何了解日誌裡面的內容。

Support Apache!

另請參閱

top

概觀

Apache HTTP Server 為紀錄伺服器上發生的一切事情提供各種不同機制,從最初的要求、經過 URL 對應程序,到最後的連線解決,包括在處理程序中發生的錯誤。此外,協力廠商模組可能會提供記錄功能,或把項目插入到現有的日誌檔案,而應用程式如 CGI 程式、PHP 指令碼,或其他處理常式,可能會傳送訊息到伺服器的錯誤日誌。

在本文檔中,我們討論包含在 http 伺服器之中標準部分的記錄模組。

top

安全警告

任何能夠寫入 Apache httpd 寫入日誌檔案目錄的人,幾乎可以確定能存取伺服器啟動的 uid,通常是 root。不要在不知道後果的情況下,授予人們寫入日誌檔案儲存目錄的權限;請查看安全秘訣文件查看詳細資訊。

此外,記錄檔可能包含未經跳脫處理,由用戶端直接提供資訊。因此,惡意用戶端有可能插入控制字元到記錄檔中,所以處理原始記錄檔時需小心謹慎。

top

錯誤記錄檔

伺服器錯誤記錄檔(由指令碼 ErrorLog 設定名稱和位置)是最重要的記錄檔。Apache httpd 會將診斷資訊傳送至這個記錄檔,並將處理請求時所遭遇的任何錯誤記錄下來。當伺服器發生起動問題或運作問題時,最先會檢視的便是這個記錄檔,因為這個記錄檔通常會顯示錯誤詳細資訊以及修復方法。

錯誤記錄檔通常會寫入一個檔案中(在 Unix 系統中通常為 error_log,在 Windows 和 OS/2 中通常為 error.log)。在 Unix 系統中,伺服也可以將錯誤傳送到 syslog傳遞至某個程式

錯誤記錄檔的格式由指令碼 ErrorLogFormat 定義,你可以使用此指令碼自訂記錄的數值。如果你未設定值,預設會定義一個格式。典型的記錄訊息範例:

[2011 年 9 月 9 日星期五上午 10:42:29.902022] [核心:錯誤] [程序 ID 35708:執行緒 ID 4328636416] [用戶端 72.15.99.187] 檔案不存在:/usr/local/apache2/htdocs/favicon.ico

記錄條目中的第一個項目是訊息的日期和時間。下一項是由哪個模組產生該訊息(本例為核心)以及哪個訊息的嚴重性等級。接著是由哪個程序處理這項條件的程序 ID 和(如果需要)執行緒 ID。接著是提出請求的用戶端位址。最後一是詳細的錯誤訊息,本例指出請求的檔案不存在。

各種不同的訊息會顯示在錯誤記錄檔中。大多數的訊息如下例所示。錯誤記錄檔也包含 CGI 腳本的偵錯輸出。CGI 腳本寫入 stderr 的任何資訊都會直接複製到錯誤記錄檔。

在錯誤記錄檔和連線記錄檔中放入 %L 權杖會產生一個記錄條目 ID,你可以利用此 ID 將錯誤記錄檔中的條目與連線記錄檔中的條目關聯起來。如果載入 mod_unique_id,其唯一的請求 ID 也會用作記錄條目 ID。

測試時,持續監控錯誤記錄檔以找出任何問題通常非常有用。在 Unix 系統中,你可以使用下列指令達成此目的:

tail -f error_log

top

每模組記錄

LogLevel 指令讓您能對每一個模組指定日誌記錄等級。這樣一來,如果您在排除特定模組問題,您可以在不記錄其他您不感興趣的模組的情況下,將其記錄程式加大。這對於 mod_proxymod_rewrite 等模組特別有用,對於您想要知道其嘗試執行的細節時更是如此。

LogLevel 指令中指定模組名稱即可。

LogLevel info rewrite:trace5

這會將主要的 LogLevel 設為資訊,但會將 mod_rewriteLogLevel 設為 trace5

這取代了之前的伺服器版本中,例如 RewriteLog,等每個模組的記錄指令。
top

存取記錄

伺服器存取記錄會記錄伺服器處理的所有要求。存取記錄的位置和內容由 CustomLog 指令控制。LogFormat 指令可用於簡化記錄內容的選取。此章節說明如何設定伺服器,以便在存取記錄中記錄資訊。

將資訊儲存在存取記錄僅是記錄管理的第一步。下一步是分析此資訊以產生有用的統計資訊。整體來說,記錄分析超出了本文的範圍,也不算是網路伺服器本身的工作。

各種版本的 Apache httpd 使用了其他模組和指令控制存取記錄,包括 mod_log_referer、mod_log_agent,以及 TransferLog 指令。CustomLog 指令現在包含所有舊指令的功能。

存取記錄的格式可選擇性極高。格式是使用格式化字串指定的,其看來非常像 C 風格的 printf(1) 格式化字串。下一個章節會提供一些範例。有關格式化字串可能內容的完整清單,請參閱 mod_log_config 格式化字串

一般記錄格式

以下是存取記錄的典型設定。

LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common

這會定義暱稱common並把它關聯到特定日誌格式字串,格式字串由百分比指令組成,每個指令都告訴伺服器記錄特定資訊,字面字元也可以放入格式字串,並會直接複製到日誌輸出版中,引號字元(")必須在前面加上反斜線以免被解釋成格式字串的結尾,格式字串也可能包含以下特殊控制字元:「\n」代表換行,「\t」代表跳格。

CustomLog指令使用已定義的暱稱設定新的日誌檔案,瀏覽紀錄的檔案名稱相對於 ServerRoot,除非檔案名稱開頭為斜線。

以上的組態會以共通紀錄格式 (Common Log Format, CLF) 記錄日誌條目,這種標準格式可以用許多不同的網路伺服器產生,並使用許多日誌分析程式讀取,CLF產生的日誌檔案條目看起來會像這樣:

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326

這則日誌條目中的每一部分說明如下。

127.0.0.1 (%h)
這是對伺服器提出要求的用戶端(遠端主機)的 IP 位址)。如果HostnameLookups設為開啟,伺服器會試著判定主機名稱並記錄在 IP 位址中,不過,並不建議這種組態,因為這樣會顯著拖慢伺服器,您最好使用 logresolve 等日誌後處理器來判定主機名稱,這裡報告的IP 位址不一定使用者的電腦的位置,如果用戶端和伺服器之間有代理伺服器,這個位址會是代理伺服器的位址,而不是原始電腦的。
- (%l)
輸出中的「連字元」表示所要求的資訊不可用,在本例中,不可用的資訊是 RFC 1413 客戶端識別碼,該識別碼由用戶端電腦上的「識別精靈」(identd) 所判定,該資訊極不可靠,幾乎不曾使用,除非在管制嚴格的內部網路中。除非IdentityCheck設為開啟,否則 Apache httpd 甚至不會嘗試判定資訊。
frank (%u)
這是由 HTTP 驗證所決定的文件請求者使用者 ID。相同值通常在「CGI scripts」中以「REMOTE_USER」的環境變數提供。如果請求狀態碼(請見下方)是 401,則不應信任此值,因為使用者尚未驗證。如果文件未受密碼保護,這部分就像前述內容一樣會是「-」。
「[10/Oct/2000:13:55:36 -0700]」(%t)
接收請求的時間。格式如下:

[d/m/y:h:m:s 區段]
d = 2*位元組
m = 3*字母
y = 4*位元組
h = 2*位元組
m = 2*位元組
s = 2*位元組
區段 = (+ | -)4*位元組

可以藉由在記錄格式字串中指定「%{format}t」,以其他格式顯示時間,其中「format」為 C 標準函式庫中的「strftime(3)」,或是其中一個受支持的特殊權杖。詳細資訊請見「mod_log_config格式字串

「GET /apache_pb.gif HTTP/1.0」(%r)
客戶端的請求行以雙引號標示。請求行包括大量有用資訊。首先,客戶端使用的方法為「GET」。接著,客戶端請求資源為「/apache_pb.gif」,最後,客戶端使用協定為「HTTP/1.0」。也可以獨立記錄請求行的其中一部分或多部分。舉例來說,格式字串「%m %U%q %H」將記錄方法、路徑、查詢字串和協定,結果輸出與「%r」完全相同。
「200」(%s)
這是伺服器送回給客戶端的狀態碼。此資訊非常有價值,因為它揭露請求是否產生成功的回應(2開頭的代碼)、重新導向(3開頭的代碼)、因客戶端造成錯誤(4開頭的代碼)、或伺服器錯誤(5開頭的代碼)。可能的狀態碼完整清單可在「HTTP 規範」中找到(RFC2616 第 10 節)。
「2326」(%b)
最後一部分表示傳回給客戶端的物件大小,不包括回應標頭。如果未傳回任何內容給客戶端,這個值會是「-」。若要記錄「0」以表示無內容,請改用 %B。

複合記錄格式

另一種常用的格式字串稱為複合記錄格式。使用方法如下:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
CustomLog log/access_log combined

此格式與一般記錄格式完全相同,只多加了兩個欄位。各附加欄位都使用百分比指令「%{header}i」,其中「header」是可以是任何 HTTP 請求標頭。根據此格式的存取記錄會看起來像這樣

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"

其他欄位如下

"http://www.example.com/start.html" (\"%{Referer}i\")
指的是客戶端報告所轉介的網站的「Referer」HTTP 要求標頭。(應該是連結到 /apache_pb.gif 或包含該檔案的網頁。)
"Mozilla/4.08 [en] (Win98; I ;Nav)" (\"%{User-agent}i\")
User-Agent HTTP 要求標頭。這是客戶端瀏覽器報告的其自身識別資訊。

多個存取記錄

只要在設定檔中指定多個指令 CustomLog 即可建立多個存取記錄。例如,下列指令將建立三個存取記錄。第一個包含基本的 CLF 資訊,而第二和第三個包含轉介資訊和瀏覽器資訊。最後兩個指令 CustomLog 顯示如何模仿指令 ReferLogAgentLog 的效果。

LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common
CustomLog logs/referer_log "%{Referer}i -> %U"
CustomLog logs/agent_log "%{User-agent}i"

此範例也顯示使用指令 LogFormat 定義別名不必要。LogFormat 可以直接在指令 CustomLog 中指定。

條件記錄

有時候,根據客戶端要求的特性從存取記錄中排除特定條目很方便。可輕鬆使用 環境變數 達成。首先,必須設定環境變數以指出要求符合特定條件。通常會使用 SetEnvIf 完成。接下來使用指令 CustomLogenv= 子句包含或排除已設定環境變數的要求。一些範例

# Mark requests from the loop-back interface
SetEnvIf Remote_Addr "127\.0\.0\.1" dontlog
# Mark requests for the robots.txt file
SetEnvIf Request_URI "^/robots\.txt$" dontlog
# Log what remains
CustomLog logs/access_log common env=!dontlog

再舉一個例子,考量將英文人士的要求記錄到一個記錄檔,而將非英文人士的要求記錄到另一個記錄檔。

SetEnvIf Accept-Language "en" english
CustomLog logs/english_log common env=english
CustomLog logs/non_english_log common env=!english

在快取情況下,您會想知道快取的效率。以下是找出它的非常簡單方法

SetEnv CACHE_MISS 1
LogFormat "%h %l %u %t "%r " %>s %b %{CACHE_MISS}e" common-cache
CustomLog logs/access_log common-cache

mod_cache 會在 mod_env 之前執行,如果成功,將不提供內容。在這種情況下,快取命中會記錄 -,而快取未命中會記錄 1

除了 env= 語法外,LogFormat 還支援在 HTTP 回應代碼中記錄值條件

LogFormat "%400,501{User-agent}i" browserlog
LogFormat "%!200,304,302{Referer}i" refererlog

在第一個範例中,如果 HTTP 狀態碼是 400 或 501,將會記錄 使用者代理程式。其他情況,將會記錄連字符號 "-" 取代。以此類推,在第二個範例中,如果 HTTP 狀態碼不是 200、304,或 302,將會記錄 HTTP 來源。(請注意狀態碼之前的驚嘆號。)

儘管我們剛剛已說明條件式記錄非常強大且彈性,但它並非控制日誌內容的唯一方式。日誌檔案包含伺服器活動的完整記錄時會更有用。通常最簡單的方式是將日誌檔案後處理,移除您不想考慮的要求。

top

日誌輪換

即便是在負荷不大的伺服器上,儲存在日誌檔中的資訊量也非常龐大。存取日誌檔案的容量通常會每 10,000 個要求增加 1 MB 以上。因此必須定期輪換日誌檔案,方法是移動或刪除現有日誌。當伺服器正在執行時無法執行此動作,因為只要 Apache httpd 維持檔案開啟,就會持續寫入舊日誌檔案。取而代之的是,伺服器必須在移動或刪除日誌檔案之後重新啟動,其才會開啟新的日誌檔案。

透過使用優雅的重新啟動,可發布指令讓伺服器開啟新的日誌檔而不會失去任何來自客戶端的現有或待處理連線。不過,若要達成此目的,伺服器必須在服務舊要求的同時持續寫入舊日誌檔。因此,在重新啟動之後必須等一段時間,才能對日誌檔執行任何處理。一個只會輪換日誌並壓縮舊日誌以節省空間的典型範例為

mv access_log access_log.old
mv error_log error_log.old
apachectl graceful
sleep 600
gzip access_log.old error_log.old

執行日誌輪換的另一種方式是使用管道日誌,如下一節所述。

top

管道日誌

Apache httpd 有能力透過管道將錯誤和存取日誌寫入另一個程序,而不是直接輸出到檔案。這種能力大幅提升了記錄的彈性,而且無需加入任何程式碼到主伺服器。若要將日誌寫入管道,只要將檔案名稱取代為管道字元 "|",然後再接上可接受其標準輸入中日誌輸入項目的可執行檔名稱。伺服器在啟動時將啟動管道日誌程序,而且若程式在伺服器執行時崩潰,伺服器也會重新啟動該程式。(由於後項功能,我們可以將此技術稱為「可靠的管道記錄」)

管線日誌處理程序是由母項 Apache httpd 處理程序衍生的,並繼承該處理程序的 user id。這表示管線日誌程式通常以根執行。因此,保持程式簡單且安全非常重要。

管線日誌的一個重要用途是允許日誌輪替,無需重新啟動伺服器。為此,Apache HTTP Server 包含一個稱為 rotatelogs 的簡單程式。例如,若要每 24 小時輪替日誌,您可以使用

CustomLog "|/usr/local/apache/bin/rotatelogs /var/log/access_log 86400" common

請注意,引號用於封裝會呼叫管線的完整命令。儘管這些範例是針對存取日誌,但相同技術也可以用於錯誤日誌。

與條件式記錄一樣,管線日誌是一個非常強大的工具,但如果可以使用較簡單的解決方案(如離線後處理),則不應使用它們。

預設情況下,管線日誌處理程序衍生時不會呼叫 shell。使用「|$」代替「|」以使用 shell 衍生(通常使用 /bin/sh -c

# Invoke "rotatelogs" using a shell
CustomLog "|$/usr/local/apache/bin/rotatelogs   /var/log/access_log 86400" common

這是 Apache 2.2 的預設行為。根據 shell 規格,這可能會導致記錄管線程式運行過程中產生額外的 shell 處理程序,並在重新啟動時產生訊號處理問題。為了與 Apache 2.2 相容,也支援並等同於使用「|」的記號「||」。

Windows 注意事項

請注意,在 Windows 上,當執行許多管線記錄器處理程序(尤其是在 HTTPD 以服務身份執行的狀況)時,您可能會遇到問題。這是因為用罄了桌面堆積空間所導致。提供的桌面堆積空間給每個服務是由 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SessionManager\SubSystems\Windows 註冊值中 SharedSection 參數的第三個參數來指定的。請謹慎變更此值;變更 Windows 註冊表的正常注意事項適用,但如果數字調整得太高,您也可能耗盡桌面堆積空間池。

top

虛擬主機

當執行具有許多 虛擬主機 的伺服器時,有幾個選項可以處理日誌檔案。首先,可以在單主機伺服器中完全相同的方式使用日誌。只要將記錄指令置於主伺服器內容中 <VirtualHost> 部分外部,即可在同一個存取日誌和錯誤日誌中記錄所有要求。此技術不允許輕鬆收集個別虛擬主機的統計資料。

如果 CustomLogErrorLog 指令放在 <VirtualHost> 區段內,那這個虛擬主機的所有要求或錯誤將只記錄到指定的檔案。任何沒有記錄指令的虛擬主機,其要求仍會傳送到主伺服器記錄。這個技術對少數虛擬主機來說很有用,但如果主機數量非常多,管理上可能會很複雜。此外,通常會造成 檔案描述符不足 的問題。

對存取記錄來說,有個很好的折衷方法。藉由將虛擬主機的資訊加入記錄格式字串,可以將所有主機記錄到同一個記錄中,稍後再將記錄分割成個別檔案。例如,考慮下列指令。

LogFormat "%v %l %u %t \"%r\" %>s %b" comonvhost
CustomLog logs/access_log comonvhost

%v 用於記錄提供請求服務的虛擬主機名稱。然後像 split-logfile 這樣的程式可以用於後處理存取記錄,以便將其分割成每個虛擬主機一個檔案。

top

其他記錄檔

記錄實際發送和接收的位元組

mod_logio 新增了兩個附加的 LogFormat 欄位(%I 和 %O),用於記錄實際在網路中接收和傳送的位元組數目。

鑑識記錄

mod_log_forensic 提供鑑識客戶端請求的記錄。記錄在處理請求之前和之後完成,因此鑑識記錄包含每個請求的兩個記錄列。鑑識記錄器非常嚴格,沒有任何自訂。它可以成為非常有用的偵錯和安全性工具。

PID 檔案

啟動時,Apache httpd 會將父 httpd 處理程序的處理程序識別碼儲存在檔案 logs/httpd.pid 中。這個檔案名稱可以使用 PidFile 指令變更。處理程序識別碼由管理員用於重新啟動和終止守護程式,方法是將訊號傳送給父處理程序;在 Windows 上,改用 -k 命令列選項。如需更多資訊,請參閱 停止和重新啟動 頁面。

腳本記錄

ScriptLog 指令讓您可以記錄 CGI 腳本的輸入和輸出來協助偵錯。只能在測試時使用這個功能,不要用於實體伺服器。更多資訊可在 mod_cgi 文件中找到。

可用語言:  en  |  fr  |  ja  |  ko  |  tr 

top

評論

注意事項
此處並非問答區段。放置於此處的留言應該針對改善文件或伺服器提出建議,若已實作或被視為無效/偏離主題,可能會遭我們的管理員移除。關於如何管理 Apache HTTP Server 的問題,請導向我們位在 Libera.chat 上的 IRC 頻道 #httpd,或寄送至我們的郵寄清單