Apache 日志文件

2021-10-13 18:21 更新
為了有效地管理Web服務(wù)器,有必要獲得有關(guān)服務(wù)器的活動和性能以及可能發(fā)生的任何問題的反饋。Apache HTTP Server提供了非常全面和靈活的日志記錄功能。本文將介紹如何配置其日志記錄功能,以及如何理解日志包含的內(nèi)容。

Apache HTTP Server提供了各種不同的機(jī)制,用于記錄服務(wù)器上發(fā)生的所有事情,從初始請求到URL映射過程,再到最終的連接解決方案,包括流程中可能發(fā)生的任何錯誤。除此之外,第三方模塊可以提供日志記錄功能,或者將條目注入到現(xiàn)有日志文件中,并且諸如CGI程序或PHP腳本或其他處理程序之類的應(yīng)用程序可以向服務(wù)器錯誤日志發(fā)送消息。

在本文中,我們將討論作為http服務(wù)器標(biāo)準(zhǔn)部分的日志記錄模塊。

安全警告

任何能夠?qū)懭階pache httpd正在編寫日志文件的目錄的用戶幾乎可以訪問服務(wù)器啟動的uid,通常是root用戶。不要在不知道后果的情況下對存儲日志的目錄進(jìn)行寫訪問;。

此外,日志文件可能包含客戶端直接提供的信息,而不會轉(zhuǎn)義。因此,惡意客戶端可能會在日志文件中插入控制字符,因此在處理原始日志時必須小心。

錯誤日志

服務(wù)器錯誤日志(其名稱和位置由ErrorLog指令設(shè)置)是最重要的日志文件。這是Apache httpd將發(fā)送診斷信息并記錄它在處理請求時遇到的任何錯誤的地方。當(dāng)啟動服務(wù)器或服務(wù)器操作出現(xiàn)問題時,它是第一個查看的地方,因?yàn)樗ǔ0e誤的詳細(xì)信息以及如何修復(fù)它。

錯誤日志通常寫入文件(通常是Unix系統(tǒng)上的error_log和Windows和OS/2上的error.log)。在Unix系統(tǒng)上,也可以讓服務(wù)器向syslog發(fā)送錯誤或?qū)⑺鼈儌鬟f給程序。

錯誤日志的格式由ErrorLogFormat指令定義,可以使用該指令自定義記錄的值。如果未指定默認(rèn)格式,則默認(rèn)為格式。典型的日志消息如下:

[Fri Sep 09 10:42:29.902022 2011] [core:error] [pid 35708:tid 4328636416] [client 72.15.99.187] File does not exist: /usr/local/apache2/htdocs/favicon.ico
Shell

日志條目中的第一項(xiàng)是消息的日期和時間。接下來是生成消息的模塊(在本例中為核心)以及該消息的嚴(yán)重性級別。接下來是經(jīng)歷該條件的進(jìn)程ID以及(如果適用的話)線程ID。接下來,我們有發(fā)出請求的客戶端地址。最后是詳細(xì)的錯誤消息,在這種情況下表示對不存在的文件的請求。

錯誤日志中可能會出現(xiàn)各種各樣的不同消息。大多數(shù)看起來類似于上面的例子。錯誤日志還將包含CGI腳本的調(diào)試輸出。通過CGI腳本寫入stderr的任何信息都將直接復(fù)制到錯誤日志中。

在錯誤日志和訪問日志中放置%L標(biāo)識符將生成一個日志條目ID,您可以使用該ID將錯誤日志中的條目與訪問日志中的條目相關(guān)聯(lián)。如果加載了mod_unique_id,則其唯一請求ID也將用作日志條目ID。

在測試期間,連續(xù)監(jiān)視錯誤日志以查找任何問題通常很有用。在Unix系統(tǒng)上,您可以使用以下方法完成此操作 -

$ tail -f error_log
Shell

按模塊記錄日志

LogLevel指令用于基于每個模塊指定日志嚴(yán)重性級別。通過這種方式,如果您只使用一個特定模塊來解決問題,則可以調(diào)高其日志記錄量,而無需獲取不感興趣的其他模塊的詳細(xì)信息。這對于mod_proxymod_rewrite等模塊特別有用。你想知道它想要做什么的細(xì)節(jié)。

通過在LogLevel指令中指定模塊的名稱來執(zhí)行此操作:

LogLevel info rewrite:trace5
Shell

這會將主LogLevel設(shè)置為info,但將其設(shè)置為trace5以獲取mod_rewrite

訪問日志

服務(wù)器訪問日志記錄服務(wù)器處理的所有請求。訪問日志的位置和內(nèi)容由CustomLog指令控制。LogFormat指令可用于簡化日志內(nèi)容的選擇。本節(jié)介紹如何配置服務(wù)器以在訪問日志中記錄信息。

當(dāng)然,將信息存儲在訪問日志中只是日志管理的開始。下一步是分析此信息以生成有用的統(tǒng)計信息。一般而言,日志分析超出了本文檔的范圍,并不是Web服務(wù)器本身的部分工作。

各種版本的Apache httpd使用其他模塊和指令來控制訪問日志記錄,包括mod_log_referermod_log_agentTransferLog指令。CustomLog指令現(xiàn)在包含所有舊指令的功能。

訪問日志的格式是高度可配置的。使用格式字符串指定格式,該字符串看起來很像C樣式的printf(1)格式字符串。

通用日志格式
訪問日志的典型配置可能如下所示-

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

這定義了昵稱common,并將其與特定的日志格式字符串相關(guān)聯(lián)。格式字符串由百分比指令組成,每個指令指示服務(wù)器記錄特定的信息。文字字符也可以放在格式字符串中,并直接復(fù)制到日志輸出中。引號字符(")必須通過在它前面放一個反斜杠來轉(zhuǎn)義,以防止它被解釋為格式字符串的結(jié)尾。格式字符串也可能包含特殊控制字符\n表示換行符和\t為標(biāo)簽。

CustomLog指令使用定義的昵稱設(shè)置新的日志文件。訪問日志的文件名相對于ServerRoot,除非它以斜杠開頭。

上述配置將以稱為通用日志格式(CLF)的格式寫入日志條目。這種標(biāo)準(zhǔn)格式可以由許多不同的Web服務(wù)器生成,并由許多日志分析程序讀取。CLF中生成的日志文件條目如下所示:

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

組合日志格式

另一種常用的格式字符串稱為組合日志格式,它可以如下使用。

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

此格式與通用日志格式完全相同,另外還添加了兩個字段。每個附加字段都使用percent-directive%{header}i,其中header可以是任何HTTP請求標(biāo)頭。此格式下的訪問日志如下所示:

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)"
Shell

多個訪問日志

只需在配置文件中指定多個CustomLog指令即可創(chuàng)建多個訪問日志。例如,以下指令將創(chuàng)建三個訪問日志。第一個包含基本的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"
Shell

條件日志
有時,根據(jù)客戶端請求的特征從訪問日志中排除某些條目是方便的。這可以通過環(huán)境變量輕松完成。首先,必須設(shè)置環(huán)境變量以指示請求滿足特定條件。通常通過SetEnvIf完成。然后,CustomLog指令的env =子句用于包含或排除設(shè)置環(huán)境變量的請求。一些例子:

# 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
Shell

作為另一個示例,考慮將來自英語用戶的請求記錄到一個日志文件,將非英語用戶記錄到不同的日志文件。

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

在緩存場景中,如果想知道緩存的效率。一個非常簡單的方法是:

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

mod_cache將在mod_env之前運(yùn)行,并且在成功時將在沒有它的情況下傳遞內(nèi)容。在這種情況下,緩存命中將記錄 - 而緩存未命中將記錄1。

除了env =語法之外,LogFormat還支持以HTTP響應(yīng)代碼為條件的日志記錄值:

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

在第一個示例中,如果HTTP狀態(tài)代碼為400或501,則將記錄用戶代理。在其他情況下,將記錄文字-。同樣,在第二個示例中,如果HTTP狀態(tài)代碼不是200,204或302,則將記錄Referer。

記錄輪換

即使是在中等繁忙的服務(wù)器上,日志文件中存儲的信息量也非常大。訪問日志文件通常每10,000個請求增長1MB或更多。因此,有必要通過移動或刪除現(xiàn)有日志來定期輪換日志文件。這在服務(wù)器運(yùn)行時無法完成,因?yàn)锳pache httpd將繼續(xù)寫入舊的日志文件,只要它保持文件打開即可。相反,必須在移動或刪除日志文件后重新啟動服務(wù)器,以便它將打開新的日志文件。

通過使用正常重新啟動,可以指示服務(wù)器打開新的日志文件,而不會丟失來自客戶端的任何現(xiàn)有或掛起的連接。但是,為了實(shí)現(xiàn)此目的,服務(wù)器必須在完成舊請求的服務(wù)時繼續(xù)寫入舊日志文件。因此,在對日志文件進(jìn)行任何處理之前,必須在重新啟動后等待一段時間。簡單地旋轉(zhuǎn)日志并壓縮舊日志以節(jié)省空間的典型方案是:

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

管道日志

Apache httpd能夠通過管道將錯誤和訪問日志文件寫入另一個進(jìn)程,而不是直接寫入文件。此功能可顯著提高日志記錄的靈活性,而無需向主服務(wù)器添加代碼。要將日志寫入管道,只需使用管道符“|”替換文件名,然后替換應(yīng)接受其標(biāo)準(zhǔn)輸入上的日志條目的可執(zhí)行文件的名稱。服務(wù)器啟動時服務(wù)器將啟動管道日志進(jìn)程,如果在服務(wù)器運(yùn)行時崩潰,它將重新啟動它。

管道日志進(jìn)程由父Apache httpd進(jìn)程生成,并繼承該進(jìn)程的用戶標(biāo)識。這意味著管道日志程序通常以root身份運(yùn)行。因此,保持程序簡單安全非常重要。

管道日志的一個重要用途是允許日志輪換而無需重新啟動服務(wù)器。為此,Apache HTTP Server包含一個名為rotatelogs的簡單程序。例如,要每24小時輪換一次日志,您可以使用:

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

請注意,引號用于包含將為管道調(diào)用的整個命令。雖然這些示例適用于訪問日志,但相同的技術(shù)可用于錯誤日志。

與條件日志記錄一樣,管道日志是一種非常強(qiáng)大的工具,但是如果可以使用更簡單的解決方案(如離線后處理),則不應(yīng)使用它們。

默認(rèn)情況下,在不調(diào)用shell的情況下生成管道日志進(jìn)程。使用|$代替|使用shell生成(通常使用/bin/sh -c):

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

這是Apache 2.2的默認(rèn)行為。根據(jù)shell的具體情況,這可能會導(dǎo)致日志記錄管道程序的生命周期內(nèi)的額外shell進(jìn)程以及重新啟動期間的信號處理問題。出于與Apache 2.2的兼容性原因,符號|| 也支持并等同于使用|。

虛擬主機(jī)日志

運(yùn)行具有許多虛擬主機(jī)的服務(wù)器時,有幾個選項(xiàng)可用于處理日志文件。首先,可以使用與單主機(jī)服務(wù)器完全相同的日志。只需將日志記錄指令放在主服務(wù)器上下文中的<VirtualHost>部分之外,就可以在同一訪問日志和錯誤日志中記錄所有請求。此技術(shù)不允許在單個虛擬主機(jī)上輕松收集統(tǒng)計信息。

如果將CustomLogErrorLog指令放在<VirtualHost>部分中,則該虛擬主機(jī)的所有請求或錯誤將僅記錄到指定的文件。任何沒有日志記錄指令的虛擬主機(jī)仍會將其請求發(fā)送到主服務(wù)器日志。此技術(shù)對于少量虛擬主機(jī)非常有用,但如果主機(jī)數(shù)量非常大,則管理起來可能很復(fù)雜。此外,它通常會產(chǎn)生文件描述符不足的問題。

對于訪問日志,有一個非常好的折衷方案。通過將虛擬主機(jī)上的信息添加到日志格式字符串,可以將所有主機(jī)記錄到同一日志中,然后將日志拆分為單個文件。例如,請考慮以下指令。

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

%v用于記錄為請求提供服務(wù)的虛擬主機(jī)的名稱。然后,可以使用像split-logfile這樣的程序?qū)υL問日志進(jìn)行后處理,以便將其分成每個虛擬主機(jī)的一個文件。





以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號