錯誤日志和訪問日志一樣也是Apache的標准日志。本文分析錯誤日志的內容,介紹如何設置和錯誤日志相關的選項,文檔錯誤和CGI錯誤的分類,以及如何方便地查看日志內容,等等。 一、位置和內容 前文討論了Apache的訪問日志,包括它的內容、格式和如何設置訪問日志有關的選項。本文我們要討論的是另外一種Apache標准日志——錯誤日志。 錯誤日志無論在格式上還是在內容上都和訪問日志不同。然而,錯誤日志和訪問日志一樣也提供豐富的信息,我們可以利用這些信息分析服務器的運行情況、哪裡出現了問題。 錯誤日志的文件名字是error_log,但如果是Windows平台,則錯誤日志的文件名字是error.log。錯誤日志的位置可以通過ErrorLog指令設置: ErrorLog logs/error.log 除非文件位置用“/”開頭,否則這個文件位置是相對於ServerRoot目錄的相對路徑。如果Apache采用默認安裝方式安裝,那麼錯誤日志的位置應該在/usr/local/apache/logs下。但是,如果Apache用某種包管理器安裝,錯誤日志很可能在其他位置。 正如其名字所示,錯誤日志記錄了服務器運行期間遇到的各種錯誤,以及一些普通的診斷信息,比如服務器何時啟動、何時關閉等。 我們可以設置日志文件記錄信息級別的高低,控制日志文件記錄信息的數量和類型。這是通過LogLevel指令設置的,該指令默認設置的級別是error,即記錄稱得上錯誤的事件。有關該指令中允許設置的各種選項的完整清單,請參見http://www.apache.org/docs/mod/core.Html#loglevel的Apache文檔。 大多數情況下,我們在日志文件中見到的內容分屬兩類:文檔錯誤和CGI錯誤。但是,錯誤日志中偶爾也會出現配置錯誤,另外還有前面提到的服務器啟動和關閉信息。 二、文檔錯誤 文檔錯誤和服務器應答中的400系列代碼相對應,最常見的就是404錯誤——Document Not Found(文檔沒有找到)。除了404錯誤以外,用戶身份驗證錯誤也是一種常見的錯誤。 404錯誤在用戶請求的資源(即URL)不存在時出現,它可能是由於用戶輸入的URL錯誤,或者由於服務器上原來存在的文檔因故被刪除或移動。 順便說一下,按照Jakob Nielson的意見,在不提供重定向或者其他補救措施的情況下,我們永遠不應該移動或者刪除Web網站的任何資源。Nielson的更多文章,請參見http://www.zdnet.com/devhead/alertbox/。 當用戶不能打開服務器上的文檔時,錯誤日志中出現的記錄如下所示: [Fri Aug 18 22:36:26 2000] [error] [client 192.168.1.6] File does not exist: /usr/local/apache/bugletdocs/Img/south-korea.gif 可以看到,正如訪問日志Access_log文件一樣,錯誤日志記錄也分成多個項。 錯誤記錄的開頭是日期/時間標記,注意它們的格式和access_log中日期/時間的格式不同。access_log中的格式被稱為“標准英文格式”,這或許是歷史跟我們開的一個玩笑,但現在要改變它已經太遲了。 錯誤記錄的第二項是當前記錄的級別,它表明了問題的嚴重程度。這個級別信息可能是LogLevel指令的文檔中所列出的任一級別(參見前面LogLevel的鏈接),error級別處於warn級別和crit級別之間。404屬於error錯誤級別,這個級別表示確實遇到了問題,但服務器還可以運行。 錯誤記錄的第三項表示用戶發出請求時所用的IP地址。 記錄的最後一項才是真正的錯誤信息。對於404錯誤,它還給出了完整路徑指示服務器試圖訪問的文件。當我們料想某個文件應該在目標位置卻出現了404錯誤時,這個信息是非常有用的。此時產生這種錯誤的原因往往是由於服務器配置錯誤、文件實際所處的虛擬主機和我們料想的不同,或者其他一些意料不到的情況。 由於用戶身份驗證問題而出現的錯誤記錄如下所示: [Tue Apr 11 22:13:21 2000] [error] [client 192.168.1.3] user rbowen@rcbowen. com: authentication failure for "/cgi-bin/hirecareers/company.cgi": passWord mismatch 注意,由於文檔錯誤是用戶請求的直接結果,因此它們在訪問日志中也會有相應的記錄。 三、CGI錯誤 錯誤日志最主要的用途或許是診斷行為異常的CGI程序。為了進一步分析和處理方便,CGI程序輸出到STDERR(Standard Error,標准錯誤設備)的所有內容都將直接進入錯誤日志。這意味著,任何編寫良好的CGI程序,如果出現了問題,錯誤日志就會告訴我們有關問題的詳細信息。 然而,把CGI程序錯誤輸出到錯誤日志也有它的缺點,錯誤日志中將出現許多沒有標准格式的內容,這使得用錯誤日志自動分析程序從中分析出有用的信息變得相當困難。 下面是一個例子,它是調試Perl CGI代碼時,錯誤日志中出現的一個錯誤記錄: [Wed Jun 14 16:16:37 2000] [error] [client 192.168.1.3] Premature end of script headers: /usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi Global symbol "$rv" requires eXPlicit package name at /usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi line 81. Global symbol "%details" requires explicit package name at /usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi line 84. Global symbol "$Config" requires explicit package name at /usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi line 133. Execution of /usr/local/apache/cgi-bin/HyperCalPro/announcement.cgi aborted due to compilation errors. 可以看到,CGI錯誤和前面的404錯誤格式相同,包含日期/時間、錯誤級別以及客戶地址、錯誤信息。但這個CGI錯誤的錯誤信息有好幾行,這往往會干擾一些錯誤日志分析軟件的工作。 有了這個錯誤信息,即使是對Perl不太熟悉的人也能夠找出許多有關錯誤的信息,例如至少可以方便地得知是哪幾行代碼出現了問題。Perl在報告程序錯誤方面的機制是相當完善的。當然,不同的編程語言輸出到錯誤日志的信息會有所不同。 由於CGI程序運行環境的特殊性,如果沒有錯誤日志的幫助,大多數CGI程序的錯誤都將很難解決。 有不少人在郵件列表或者新聞組中抱怨說自己有一個CGI程序,當打開網頁時服務器卻返回錯誤,比如“Internal Server Error”。我們可以肯定,這些人還沒有看過服務器的錯誤日志,或者根本不知道錯誤日志的存在。決多大多數情況下,錯誤日志能夠精確地指出CGI錯誤的所在以及如何修正這個錯誤。 四、查看日志文件 我常常告訴別人說,在進行開發的同時我會不斷地檢查服務器的日志,以便能夠立即知道哪兒出了問題。但我得到的回答卻往往是沉默。起先我以為這種沉默意味著“你當然得這樣做”,後來我才發現這種沉默的真正含義是“我不知道別人的做法,但我自己是不干的。” 雖然如此,下面我們還是要看看如何方便地查看服務器日志文件。用telnet連接到服務器,然後輸入下面的命令: tail -f /usr/local/apache/logs/error_log 該命令將顯示出日志文件的最後幾行內容,如果有新的內容加入到日志文件,它還會立即顯示出新加入的內容。 Windows用戶也同樣可以使用這種方法,比如可以使用各種為Windows提供的Unix工具軟件包。我個人愛好一個稱為AINTX的工具,它可以在http://maxx.mc.net/~jlh/nttools/index.htm找到。 還有一種替代方法是使用下面的Perl代碼,它利用了一個稱為File::Tail的模塊: use File::Tail; $file=File::Tail->new("/some/log/file"); while (defined($line=$file->read)) { print "$line"; } 無論具體采用的是哪一種方法,同時打開多個終端窗口都是一種好習慣:比如在一個窗口中顯示錯誤日志,在另一個窗口中顯示訪問日志。這樣,我們就能夠隨時獲知網站上發生的事情並立即予以解決。 在這個《Apache日志》系列的下一篇文章中,我們將討論定制服務器日志,即如何在日志文件中記錄所有我們想要的信息,排除所有我們不想要的信息。 在此之後,我們還將討論日志文件的處理,即如何從日志文件生成統計報表。在最後幾篇文章中,我們還將討論如何把日志記錄重定向到指定的程序而不是保存到日志文件,以便由程序實時地處理新生成的日志數據,比如將日志數據保存到數據庫,或者當發生某些關鍵性錯誤時通過email把日志信息發送給系統管理員,等等。