Apache内建了记录服务器活动的功能,这就是它的日志功能。下面介绍的就是Apache的错误日志、访问日志以及如何管理日志等。
错误日志是Apache中最重要的日志文件,其文件名和位置取决于ErrorLog指令的设置。Apache将在这个文件中存放诊断信息和处理请求中出现的错误,由于日志中包含了出错细节以及如何解决等信息,一旦服务器启动或运行中出现问题,首先就应该查看错误日志。
在Fedora 6中错误日志的文件名字一般为error_log。
大多数情况下,在日志文件中见到的内容分属两类:文档错误和CGI错误。但是,错误日志中偶尔也会出现配置错误,另外还有服务器启动和关闭信息。
文档错误和服务器应答中的400系列代码相对应,最常见的就是404错误——DocumentNot Found(文档没有找到)。除了404错误以外,用户身份验证错误也是一种常见的错误。
404错误在用户请求的资源(即URL)不存在时出现,它可能是由于用户输入的URL错误,或者由于服务器上原来存在的文档因故被删除或移动。
当用户不能打开服务器上的文档时,错误日志中出现的记录如下所示:
[Fri Aug 18 22:36:26 2004] [error]
[client 192.168.1.6] File does not exist:
/usr/local/apache/bugletdocs/Img/south-korea.gif
错误记录的开头是日期/时间标记,错误记录的第二项是当前记录的级别,它表明了问题的严重程度。这个级别信息可能是LogLevel指令的文档中所列出的任一级别(参见前面LogLevel的链接),error级别处于warn级别和crit级别之间。404属于error错误级别,这个级别表示确实遇到了问题,但服务器还可以运行。错误记录的第三项表示用户发出请求时所用的IP地址。记录的最后一项才是真正的错误信息。对于404错误,它还给出了完整路径指示服务器试图访问的文件。当某个文件应该在目标位置却出现了404错误时,这个信息是非常有用的。此时产生这种错误的原因往往是由于服务器配置错误,或者其他一些意料不到的情况。
错误日志最主要的用途或许就是诊断行为异常的CGI程序。为了进一步分析和处理方便,CGI程序输出到STDERR(Standard Error,标准错误设备)的所有内容都将直接进入错误日志。这就是说,任何编写良好的CGI程序,如果出现了问题,错误日志就会告诉管理员有关问题的详细信息。
然而,把CGI程序错误输出到错误日志也有它的缺点,因为输入的信息并没有一定的格式,所以错误日志中将出现许多没有标准格式的内容,这使得用错误日志自动分析程序从中分析出有用的信息变得相当困难。
下面是一个例子,它是调试Perl CGI代码时,错误日志中出现的一个错误记录:
[Wed Jun 14 16:16:37 2004] [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程序的错误都将很难解决。
访问日志中会记录服务器所处理的所有请求,其文件名和位置取决于CustomLog 指令。访问日志的格式是高度灵活的,它使用了很像C的printf( )函数的格式字符串,如表5-6所示。
表5-6 日志文件记录格式说明符
格 式 |
描 述 |
%% |
百分号(Apache 2.0.44 或更高的版本) |
%...a |
远端IP地址 |
%...A |
本地IP地址 |
续上表 | |
格 式 |
描 述 |
%...B |
除HTTP报头外传送的字节数 |
%...b |
以CLF格式显示的除HTTP报头外的传送字节数,例如:当没有字节传送时显示“-”而不是0 |
%...{Foobar}C |
在请求中传送给服务端的cookie Foobar的内容 |
%...D |
服务器完成本请求的时间,以毫秒为单位 |
%...{FOOBAR}e |
环境变量FOOBAR的值 |
%...f |
文件名 |
%...h |
远端主机 |
%...H |
请求协议 |
%...{Foobar}I |
发送到服务器的请求报头Foobar的内容 |
%...l |
远端登录名(由identd而来,如果支持的话) |
%...m |
请求的方法 |
%...{Foobar}n |
从另一个模块来的注解Foobar: |
%...{Foobar}o |
返回时报头的内容Foobar: |
%...p |
服务器提供本请求对应服务的标准端口 |
%...P |
为本请求提供服务的子进程的进程ID |
%...q |
查询字串(如果存在由一个?引导,否则返回空串) |
%...r |
请求的第一行 |
%...s |
状态。对于内部重定向的请求,这个状态指的是原始请求的状态,--- %...>s则指的是最后请求的状态 |
%...t |
时间,用普通日志时间格式(标准英语格式) |
%...{format}t |
时间,用strftime(3)指定的格式表示的时间(默认情况下按本地化格式) |
%...T |
完成请求服务的时间,以秒为单位 |
%...u |
远程用户名(根据验证信息而来;如果返回status (%s)为401,可能是假的) |
%...U |
请求的URL路径,不包含查询串 |
%...v |
进行服务的服务器的标准名字ServerName |
%...V |
根据UseCanonicalName指令设定的服务器名称 |
%...X |
请求完成时的连接状态:X =连接在应答完成前中断 |
+ = |
应答传送完后继续保持连接 |
-= |
应答传送完后关闭连接 |
%...I |
接收的字节数,包括请求头的数据,并且不能为零。要使用这个指令你必须启用mod_logio模块 |
%...O |
发送的字节数,包括请求头的数据,并且不能为零。要使用这个指令你必须启用mod_logio模块 |
下面举个例子,来说明访问日志的格式。
LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common
这是一个典型的记录格式,它定义了一种特定的记录格式字符串,并给它起了个别名叫common,其中的“%”指示服务器用某种信息替换,其他字符信息则不作替换。引号(")必须加转义符反斜杠,以避免被解释为字符串的结束。格式字符串还可以包含特殊控制符,如换行“\n”、制表符“\t”。
这是一种普通记录格式,被称为Common Log Format(CLF),被许多不同的Web服务器所采用,并可以为许多日志分析程序所辩识,它产生的事件记录有如:
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
记录的各部分说明如下。
(1)127.0.0.1 (%h):这是发送请求到服务器的客户的IP地址。如果HostnameLookups设为On,则服务器会尝试解析这个IP地址的主机名,但是,这里并不推荐这样配置,因为这样会增加服务器负担。
(2)- (%l):这是由客户端identd 判断的RFC 1413身份,输出中的符号“-”表示此处信息无效。除非在严格控制的内部网络中,此信息通常并不可靠,不应该被使用。只有在IdentityCheck设为On时,Apache才会试图得到这项信息。
(3)frank(%u):这是由HTTP认证系统得到的访问该网页的客户名称,环境变量REMOTE_USER会被设为该值并提供给CGI脚本。如果状态码是401,表示客户没有通过认证,则此值没有意义。如果网页没有设置密码保护,则此项应该是“-”。
(4)[10/Oct/2000:13:55:36 -0700] (%t):这是服务器完成对请求的处理时的时间,其格式是:
[day/month/year:hour:minute:second zone]
day = 2*digit
month = 3*letter
year = 4*digit
hour = 2*digit
minute = 2*digit
second = 2*digit
zone = ('+' | '-') 4*digit
可以在格式字符串中使用%{format}t改变时间的输出形式,format与C标准库中的strftime(3)用法相同。
(5)"GET /apache_pb.gif HTTP/1.0" (\"%r\") :引号中是客户端发出的包含了许多有用信息的请求内容。可以看出,该客户的动作是GET,请求的资源是/apache_pb.gif,使用的协议是HTTP/1.0。另外,还可以记录其他信息,如:格式字符串“%m %U%q %H”会记录动作、路径、请求串、协议,结果其输出会和“%r”一样。
(6)200 (%>s):这个是服务器返回给客户端的状态码。这个信息非常有价值,因为它指示了请求的结果,或者是被成功响应了(以2开头),或者被转向了(以3开头),或者出错了(以4开头),或者产生了服务器端错误(以5开头)。
(7)2326 (%b):最后这项是返回给客户端的不包括响应头的字节数。如果没有信息返回,则此项应该是“-”,如果希望记录为“0”的形式,就应该用%B。