# 日志文件
要有效地管理Web服務器,就有必要反饋服務器的活動、性能以及出現的問題。Apache HTTP服務器提供了非常全面而靈活的日志記錄功能。本文將闡述如何配置文件以及如何理解日志內容。
## 安全警告
任何人只要對Apache存放日志文件的目錄具有寫權限,也就當然地可以獲得啟動Apache的用戶(通常是root)的權限,_絕對不要_隨意給予任何人存放日志文件目錄的寫權限。細節請參見[安全方面的提示](#calibre_link-263)。
另外,日志文件可能會包含未加轉換的來自用戶的信息,用戶就有機會惡意插入控制符,所以處理原始日志時應該當心這個問題。
## 錯誤日志(Error Log)
相關模塊
* `ErrorLog`
* `LogLevel`
相關指令
錯誤日志是最重要的日志文件,其文件名和位置取決于`ErrorLog`指令。Apache httpd將在這個文件中存放診斷信息和處理請求中出現的錯誤,由于這里經常包含了出錯細節以及如何解決,如果服務器啟動或運行中有問題,首先就應該查看這個錯誤日志。
錯誤日志通常被寫入一個文件(unix系統上一般是`error_log` ,Windows和OS/2上一般是`error.log`)。在unix系統中,錯誤日志還可能被重定向到`syslog`或[通過管道操作傳遞給一個程序](#calibre_link-491)。
錯誤日志的格式相對靈活,并可以附加文字描述。某些信息會出現在絕大多數記錄中,一個典型的例子是:
```
[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1]
client denied by server configuration:
/export/home/live/ap/htdocs/test
```
其中,第一項是錯誤發生的日期和時間;第二項是錯誤的嚴重性,`LogLevel`指令使只有高于指定嚴重性級別的錯誤才會被記錄;第三項是導致錯誤的IP地址;此后是信息本身,在此例中,服務器拒絕了這個客戶的訪問。服務器在記錄被訪問文件時,用的是文件系統路徑,而不是Web路徑。
錯誤日志中會包含類似上述例子的多種類型的信息。此外,CGI腳本中任何輸出到`stderr`的信息會作為調試信息原封不動地記錄到錯誤日志中。
用戶可以增加或刪除錯誤日志的項。但是對某些特殊請求,在[訪問日志(access log)](#calibre_link-492)中也會有相應的記錄,比如上述例子在訪問日志中也會有相應的記錄,其狀態碼是403,因為訪問日志也可以定制,所以可以從訪問日志中得到錯誤事件的更多信息。
在測試中,對任何問題持續監視錯誤日志是非常有用的。在unix系統中,可以這樣做:
```
tail -f error_log
```
## 訪問日志(Access Log)
相關模塊
* `mod_log_config`
* `mod_setenvif`
相關指令
* `CustomLog`
* `LogFormat`
* `SetEnvIf`
訪問日志中會記錄服務器所處理的所有請求,其文件名和位置取決于`CustomLog`指令,`LogFormat`指令可以簡化日志的內容。這里闡述如何配置服務器的訪問日志。
實施日志管理,首先當然必須產生訪問日志,然后才能分析日志從而得到有用的統計信息。日志分析不是Web服務器的職責,已超出本文的范疇,更多資料和有關分析工具的信息,可以查看[Open Directory](http://dmoz.org/Computers/Software/Internet/Site_Management/Log_analysis/)或[Yahoo](http://dir.yahoo.com/Computers_and_Internet/Software/Internet/World_Wide_Web/Servers/Log_Analysis_Tools/) 。
不同版本的Apache httpd使用了不同的模塊和指令來控制對訪問的記錄,包括mod_log_referer, mod_log_agent和`TransferLog`指令。現在,`CustomLog`指令包含了舊版本中相關指令的所有功能。
訪問日志的格式是高度靈活的,使用很象C風格的printf()函數的格式字符串。下面有幾個例子,完整的說明可以查看用于`mod_log_config`模塊的[格式字符串](#calibre_link-72)。
### 通用日志格式(Common Log Format)
這是一個典型的記錄格式:
```
LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common
```
它定義了一種特定的記錄格式字符串,并給它起了個_別名_叫`common` ,其中的"%"指示服務器用某種信息替換,其他字符則不作替換。引號(`"`)必須加反斜杠轉義,以避免被解釋為字符串的結束。格式字符串還可以包含特殊的控制符,如換行符"`\n`" 、制表符"`\t`"。
`CustomLog`指令建立一個使用指定_別名_的新日志文件,除非其文件名是以斜杠開頭的絕對路徑,否則其路徑就是相對于`ServerRoot`的相對路徑。
上述配置是一種被稱為通用日志格式(CLF)的記錄格式,它被許多不同的Web服務器所采用,并被許多日志分析程序所識別,它產生的記錄形如:
```
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`設為 `On` ,則服務器會嘗試解析這個IP地址的主機名并替換此處的IP地址,但并不推薦這樣做,因為它會顯著拖慢服務器,最好是用一個日志后續處理器來判斷主機名,比如`logresolve` 。如果客戶和服務器之間存在代理,那么記錄中的這個IP地址就是那個代理的IP地址,而不是客戶機的真實IP地址。
`-` (`%l`)
這是由客戶端`identd`進程判斷的RFC1413身份(identity),輸出中的符號"-"表示此處的信息無效。除非在嚴格控制的內部網絡中,此信息通常很不可靠,不應該被使用。只有在將`IdentityCheck`指令設為 `On` 時,Apache才會試圖得到這項信息。
`frank` (`%u`)
這是HTTP認證系統得到的訪問該網頁的客戶標識(userid),環境變量`REMOTE_USER`會被設為該值并提供給CGI腳本。如果狀態碼是401,表示客戶未通過認證,則此值沒有意義。如果網頁沒有設置密碼保護,則此項將是"`-`"。
`[10/Oct/2000:13:55:36 -0700]` (`%t`)
這是服務器完成請求處理時的時間,其格式是:
`[日/月/年:時:分:秒 時區]
日 = 2數字
月 = 3字母
年 = 4數字
時 = 2數字
分 = 2數字
秒 = 2數字
時區 = (+|-)4數字`
可以在格式字符串中使用 `%{format}t` 來改變時間的輸出形式,其中的`format`與C標準庫中的`strftime()`用法相同。
`"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規范](http://www.w3.org/Protocols/rfc2616/rfc2616.txt)(RFC2616第10章)。
`2326` (`%b`)
最后這項是返回給客戶端的不包括響應頭的字節數。如果沒有信息返回,則此項應該是"`-`",如果希望記錄為"`0`"的形式,就應該用`%B` 。
### 組合日志格式(Combined Log Format)
另一種常用的記錄格式是組合日志格式,形式如下:
```
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\"
\"%{User-agent}i\"" combined
CustomLog log/access_log combined
```
這種格式與通用日志格式類似,但是多了兩個 `%{_header_}i` 項,其中的_header_可以是任何請求頭。這種格式的記錄形如:
```
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"請求頭。此項指明了該請求是被從哪個網頁提交過來的,這個網頁應該包含有`/apache_pb.gif`或者其連接。
`"Mozilla/4.08 [en] (Win98; I ;Nav)"` (`\"%{User-agent}i\"`)
"User-Agent"請求頭。此項是客戶端提供的瀏覽器識別信息。
### 多文件訪問日志
可以簡單地在配置文件中用多個`CustomLog`指令來建立多文件訪問日志。如下例,既記錄基本的CLF信息,又記錄提交網頁和瀏覽器的信息,最后兩行`CustomLog`示范了如何模擬`ReferLog`和`AgentLog`指令的效果。
```
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"
```
此例也說明了,記錄格式可以直接由`CustomLog`指定,而并不一定要用`LogFormat`起一個別名。
### 條件日志
許多時候,根據與請求特征相關的[環境變量](#calibre_link-232)來有選擇地記錄某些客戶端請求會帶來便利。首先,需要使用`SetEnvIf`指令來設置特定的[環境變量](#calibre_link-232)以標識符合某種特定條件的請求,然后用`CustomLog`指令的 `env=` 子句,根據這些[環境變量](#calibre_link-232)來決定記錄或排除特定的請求。例如:
```
# 不記錄本機發出的請求
SetEnvIf Remote_Addr "127\.0\.0\.1" dontlog
# 不記錄對robots.txt文件的請求
SetEnvIf Request_URI "^/robots\.txt$" dontlog
# 記錄其他請求
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
```
雖然上述已經展示了條件日志記錄的強大和靈活,但這不是控制日志內容的唯一手段,還可以用日志后繼處理程序來剔除你不關心的內容,從而使日志更加有用。
## 日志滾動
即使一個并不繁忙的服務器,其日志文件的信息量也會很大,一般每10000個請求,訪問日志就會增加1MB或更多。這就有必要定期滾動日志文件。由于Apache會保持日志文件的打開,并持續寫入信息,因此服務器運行期間不能執行滾動操作。移動或者刪除日志文件以后,必須[重新啟動](#calibre_link-31)服務器才能讓它打開新的日志文件。
用_優雅的(graceful)_方法重新啟動,可以使服務器啟用新的日志文件,而不丟失原來尚未寫入的信息。為此,有必要等待一段時間,讓服務器完成正在處理的請求,并將記錄寫入到原來的日志文件。以下是一個典型的日志滾動和為節省存儲空間而壓縮舊日志的例子:
```
mv access_log access_log.old
mv error_log error_log.old
apachectl graceful
sleep 600
gzip access_log.old error_log.old
```
另一種執行滾動的方法是使用下一節闡述的[管道日志](#calibre_link-491)。
## 管道日志
Apache httpd可以通過管道將訪問記錄和出錯信息傳遞給另一個進程,而不是寫入一個文件,由于無須對主服務器進行編程,這個功能顯著地增強了日志的靈活性。只要用管道操作符"`|`"后面跟一個可執行文件名,就可以使這個程序從標準輸入設備獲得事件記錄。Apache在啟動時,會同時啟動這個管道日志進程,并且在運行過程中,如果這個進程崩潰了,會重新啟動這個進程(所以我們稱這個技術為"可靠管道日志")。
管道日志進程由其父進程Apache httpd產生,并繼承其權限,這意味著管道進程通常是作為root運行的,所以保持這個程序簡單而安全極為重要。
管道日志的一種重要用途是,允許日志滾動而無須重新啟動服務器。為此,服務器提供了一個簡單的程序`rotatelogs` 。每24小時滾動一次日志的例子如下:
```
CustomLog "|/usr/local/apache/bin/rotatelogs /var/log/access_log 86400" common
```
注意:引號用于界定整個管道命令行。雖然這是針對訪問日志的,但是其用法對于其他日志也一樣。
在其他站點,有一個類似但更靈活的日志滾動程序叫[cronolog](http://www.cronolog.org/) 。
如果有較簡單的離線處理日志的方案,就不應該使用條件日志和管道日志,即使它們非常強大。
## 虛擬主機
如果服務器配有若干[虛擬主機](#calibre_link-36),那么還有幾個控制日志文件的功能。首先,可以把日志指令放在`<VirtualHost>`段之外,讓它們與主服務器使用同一個訪問日志和錯誤日志來記錄所有的請求和錯誤,但是這樣就不能方便的獲得每個虛擬主機的信息了。
如果把`CustomLog`或`ErrorLog`指令放在`<VirtualHost>`段內,所有對這個虛擬主機的請求和錯誤信息會被記錄在其私有的日志文件中,那些沒有在`<VirtualHost>`段內使用日志指令的虛擬主機將仍然和主服務器使用同一個日志。這種方法對虛擬主機較少的服務器很有用,但虛擬主機非常多時,就會帶來管理上的困難,還經常會產生[文件描述符短缺](#calibre_link-68)的問題。
對于訪問日志,有一個很好的折衷方案,在同一個訪問日志文件中記錄對所有主機的訪問,而每條記錄都注明虛擬主機的信息,日后再把記錄拆開存入不同的文件。例如:
```
LogFormat "%v %l %u %t \"%r\" %>s %b" comonvhost
CustomLog logs/access_log comonvhost
```
`%v` 用來附加虛擬主機的信息。有個[split-logfile](#calibre_link-73)程序可以根據不同的虛擬主機信息對日志進行拆分,并將結果存入不同的文件。
## 其他日志文件
相關模塊
* `mod_logio`
* `mod_log_forensic`
* `mod_cgi`
* `mod_rewrite`
相關指令
* `LogFormat`
* `ForensicLog`
* `PidFile`
* `RewriteLog`
* `RewriteLogLevel`
* `ScriptLog`
* `ScriptLogBuffer`
* `ScriptLogLength`
### 記錄接收和發送的實際字節數
`mod_logio`增加了兩個額外的`LogFormat`字段(%I 和 %O)用于記錄接收和發送的實際字節數。
### 對比記錄(Forensic Logging)
`mod_log_forensic`提供了對客戶端請求的_對比_記錄,也就是在請求被處理之前和處理完成之后進行兩次記錄,所以對比日志(forensic log)對于每個請求都包含兩條記錄。對比記錄器(forensic logger)十分嚴格,不可以進行定制。它可以成為無價的調試和安全工具。
### PID文件
在啟動時,Apache httpd將會在`logs/httpd.pid`文件中保存其父進程httpd的進程ID(process id[PID])。該文件名可以用`PidFile`指令改變。該PID可以被管理員利用來重新啟動或者終止服務器后臺守護進程。在Windows中,可以使用命令行參數 -k 。更多信息請參見[停止和重新啟動](#calibre_link-31)。
### 腳本日志
為了方便調試,可以用`ScriptLog`指令來記錄CGI腳本的輸入和輸出。此功能應該僅用于測試,而不應該用于正常工作的服務器。更多資料請參見[mod_cgi](#calibre_link-218)文檔。
### 重寫日志
在使用強大且靈活的[mod_rewrite](#calibre_link-34)時,幾乎都有必要用`RewriteLog`來幫助調試。這個日志提供了重寫引擎如何轉換請求的詳細分解信息,其詳細程度取決于`RewriteLogLevel`指令。
- Apache HTTP Server Version 2.2 文檔 [最后更新:2006年3月21日]
- 版本說明
- 從1.3升級到2.0
- 從2.0升級到2.2
- Apache 2.2 新特性概述
- Apache 2.0 新特性概述
- The Apache License, Version 2.0
- 參考手冊
- 編譯與安裝
- 啟動Apache
- 停止和重啟
- 配置文件
- 配置段(容器)
- 緩沖指南
- 服務器全局配置
- 日志文件
- 從URL到文件系統的映射
- 安全方面的提示
- 動態共享對象(DSO)支持
- 內容協商
- 自定義錯誤響應
- 地址和端口的綁定(Binding)
- 多路處理模塊
- Apache的環境變量
- Apache處理器的使用
- 過濾器(Filter)
- suEXEC支持
- 性能方面的提示
- URL重寫指南
- Apache虛擬主機文檔
- 基于主機名的虛擬主機
- 基于IP地址的虛擬主機
- 大批量虛擬主機的動態配置
- 虛擬主機示例
- 深入研究虛擬主機的匹配
- 文件描述符限制
- 關于DNS和Apache
- 常見問題
- 經常問到的問題
- Apache的SSL/TLS加密
- SSL/TLS高強度加密:緒論
- SSL/TLS高強度加密:兼容性
- SSL/TLS高強度加密:如何...?
- SSL/TLS Strong Encryption: FAQ
- 如何.../指南
- 認證、授權、訪問控制
- CGI動態頁面
- 服務器端包含入門
- .htaccess文件
- 用戶網站目錄
- 針對特定平臺的說明
- 在Microsoft Windows中使用Apache
- 在Microsoft Windows上編譯Apache
- Using Apache With Novell NetWare
- Running a High-Performance Web Server on HPUX
- The Apache EBCDIC Port
- 服務器和支持程序
- httpd - Apache超文本傳輸協議服務器
- ab - Apache HTTP服務器性能測試工具
- apachectl - Apache HTTP服務器控制接口
- apxs - Apache 擴展工具
- configure - 配置源代碼樹
- dbmmanage - 管理DBM格式的用戶認證文件
- htcacheclean - 清理磁盤緩沖區
- htdbm - 操作DBM密碼數據庫
- htdigest - 管理用于摘要認證的用戶文件
- httxt2dbm - 生成RewriteMap指令使用的dbm文件
- htpasswd - 管理用于基本認證的用戶文件
- logresolve - 解析Apache日志中的IP地址為主機名
- rotatelogs - 滾動Apache日志的管道日志程序
- suexec - 在執行外部程序之前切換用戶
- 其他程序
- 雜項文檔
- 與Apache相關的標準
- Apache模塊
- 描述模塊的術語
- 描述指令的術語
- Apache核心(Core)特性
- Apache MPM 公共指令
- Apache MPM beos
- Apache MPM event
- Apache MPM netware
- Apache MPM os2
- Apache MPM prefork
- Apache MPM winnt
- Apache MPM worker
- Apache模塊 mod_actions
- Apache模塊 mod_alias
- Apache模塊 mod_asis
- Apache模塊 mod_auth_basic
- Apache模塊 mod_auth_digest
- Apache模塊 mod_authn_alias
- Apache模塊 mod_authn_anon
- Apache模塊 mod_authn_dbd
- Apache模塊 mod_authn_dbm
- Apache模塊 mod_authn_default
- Apache模塊 mod_authn_file
- Apache模塊 mod_authnz_ldap
- Apache模塊 mod_authz_dbm
- Apache模塊 mod_authz_default
- Apache模塊 mod_authz_groupfile
- Apache模塊 mod_authz_host
- Apache模塊 mod_authz_owner
- Apache模塊 mod_authz_user
- Apache模塊 mod_autoindex
- Apache模塊 mod_cache
- Apache模塊 mod_cern_meta
- Apache模塊 mod_cgi
- Apache模塊 mod_cgid
- Apache模塊 mod_charset_lite
- Apache模塊 mod_dav
- Apache模塊 mod_dav_fs
- Apache模塊 mod_dav_lock
- Apache模塊 mod_dbd
- Apache模塊 mod_deflate
- Apache模塊 mod_dir
- Apache模塊 mod_disk_cache
- Apache模塊 mod_dumpio
- Apache模塊 mod_echo
- Apache模塊 mod_env
- Apache模塊 mod_example
- Apache模塊 mod_expires
- Apache模塊 mod_ext_filter
- Apache模塊 mod_file_cache
- Apache模塊 mod_filter
- Apache模塊 mod_headers
- Apache模塊 mod_ident
- Apache模塊 mod_imagemap
- Apache模塊 mod_include
- Apache模塊 mod_info
- Apache模塊 mod_isapi
- Apache模塊 mod_ldap
- Apache模塊 mod_log_config
- Apache模塊 mod_log_forensic
- Apache模塊 mod_logio
- Apache模塊 mod_mem_cache
- Apache模塊 mod_mime
- Apache模塊 mod_mime_magic
- Apache模塊 mod_negotiation
- Apache模塊 mod_nw_ssl
- Apache模塊 mod_proxy
- Apache模塊 mod_proxy_ajp
- Apache模塊 mod_proxy_balancer
- Apache模塊 mod_proxy_connect
- Apache模塊 mod_proxy_ftp
- Apache模塊 mod_proxy_http
- Apache模塊 mod_rewrite
- Apache模塊 mod_setenvif
- Apache模塊 mod_so
- Apache模塊 mod_speling
- Apache模塊 mod_ssl
- Apache模塊 mod_status
- Apache模塊 mod_suexec
- Apache模塊 mod_unique_id
- Apache模塊 mod_userdir
- Apache模塊 mod_usertrack
- Apache模塊 mod_version
- Apache模塊 mod_vhost_alias
- Developer Documentation for Apache 2.0
- Apache 1.3 API notes
- Debugging Memory Allocation in APR
- Documenting Apache 2.0
- Apache 2.0 Hook Functions
- Converting Modules from Apache 1.3 to Apache 2.0
- Request Processing in Apache 2.0
- How filters work in Apache 2.0
- Apache 2.0 Thread Safety Issues
- 詞匯和索引
- 詞匯表
- 指令索引
- 指令速查
- 模塊索引
- 站點導航