为了有效地管理Web服务器,有必要获取有关服务器活动和性能以及可能发生的任何问题的反馈。Apache HTTP Server提供了非常全面和灵活的日志记录功能。本文档介绍了如何配置其日志记录功能以及如何理解日志包含的内容。
相关模块 | 相关指令 |
---|---|
Apache HTTP Server提供了多种不同的机制来记录服务器上发生的所有事情,从最初的请求到URL映射过程,再到连接的最终解决,包括过程中可能发生的任何错误。除此之外,第三方模块还可以提供日志记录功能,或将条目注入现有的日志文件中,并且诸如CGI程序,PHP脚本或其他处理程序之类的应用程序可以向服务器错误日志发送消息。
在本文档中,我们讨论作为http服务器标准部分的日志记录模块。
可以写入Apache httpd写入日志文件的目录的任何人几乎都可以访问服务器启动时所使用的uid(通常是root)。千万 不要给人的日志存储在没有意识到后果的目录的写权限; 有关详细信息,请参见 安全提示文档。
此外,日志文件可能包含客户端直接提供的信息,而不会转义。因此,恶意客户端有可能在日志文件中插入控制字符,因此在处理原始日志时必须格外小心。
相关模块 | 相关指令 |
---|---|
服务器错误日志(由ErrorLog
伪指令设置名称和位置)是
最重要的日志文件。这是Apache httpd发送诊断信息并记录在处理请求时遇到的任何错误的地方。当启动服务器或服务器操作出现问题时,它是第一个查看的地方,因为它通常包含发生问题的原因以及如何解决的详细信息。
通常将错误日志写入文件(通常
error_log
在Unix系统以及
error.log
Windows和OS / 2上)。在Unix系统上,还可以让服务器将错误发送到程序syslog
或将错误通过程序发送
给程序。
错误日志的格式由ErrorLogFormat
指令定义,您可以使用该指令自定义要记录的值。如果未指定格式,则默认为格式定义。典型的日志消息如下:
[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
日志条目中的第一项是消息的日期和时间。接下来是产生消息的模块(在这种情况下为核心)和该消息的严重性级别。紧随其后的是遇到该条件的进程的进程ID和线程ID(如果适用)。接下来,我们有发出请求的客户地址。最后是详细的错误消息,在这种情况下,该错误消息表示请求的文件不存在。
错误日志中会出现各种各样的不同消息。大多数看起来类似于上面的示例。错误日志还将包含CGI脚本的调试输出。stderr
CGI脚本写入的任何信息都将直接复制到错误日志中。
%L
在错误日志和访问日志中都放置一个令牌将产生一个日志条目ID,您可以使用该ID将错误日志中的条目与访问日志中的条目相关联。如果
mod_unique_id
已加载,则其唯一的请求ID也将用作日志条目ID。
在测试过程中,连续监视错误日志中是否存在任何问题通常很有用。在Unix系统上,可以使用以下方法完成此操作:
tail -f error_log
该LogLevel
指令允许您指定每个模块的日志严重性级别。这样,如果你只用一个特定模块排除故障,您可以打开了它的记录容量,而不也越来越其他模块,你不感兴趣的细节。这是模块,如特别有用,
mod_proxy
或者mod_rewrite
在那里你想要了解有关其尝试操作的详细信息。
通过在LogLevel
指令中指定模块名称来执行此操作
:
LogLevel info rewrite:trace5
这LogLevel
会将main设置为info,但将其设置为trace5
for
mod_rewrite
。
RewriteLog
服务器早期版本中存在的按模块记录的指令,例如
。相关模块 | 相关指令 |
---|---|
服务器访问日志记录服务器处理的所有请求。访问日志的位置和内容由CustomLog
指令控制。该LogFormat
指令可用于简化日志内容的选择。本节介绍如何配置服务器以在访问日志中记录信息。
当然,将信息存储在访问日志中只是日志管理的开始。下一步是分析此信息以生成有用的统计信息。日志分析通常不在本文档的讨论范围之内,并不是Web服务器本身工作的一部分。有关此主题的更多信息以及执行日志分析的应用程序,请检查 Open Directory。
各种版本的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
除非以斜杠开头,否则访问日志的文件名是相对于的。
上面的配置将以称为通用日志格式(CLF)的格式写入日志条目。这种标准格式可以由许多不同的Web服务器生成,并可以由许多日志分析程序读取。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
)HostnameLookups
设置为On
,则服务器将尝试确定主机名并将其记录在IP地址的位置。但是,不建议使用此配置,因为它会大大降低服务器的速度。相反,最好使用日志后处理器logresolve
来确定主机名。此处报告的IP地址不一定是用户所坐机器的地址。如果用户和服务器之间存在代理服务器,则该地址将是代理服务器的地址,而不是原始计算机的地址。-
(%l
)identd
在客户端计算机上确定的客户端的RFC 1413身份。该信息高度不可靠,几乎不应使用,除非在受到严格控制的内部网络上使用。除非IdentityCheck
设置为,否则Apache httpd甚至不会尝试确定此信息On
。frank
(%u
)REMOTE_USER
环境变量中为CGI脚本提供相同的值
。如果请求的状态代码(请参阅下文)为401,则此值不应被信任,因为用户尚未通过身份验证。如果文档没有密码保护,则该部分将与上一部分一样为“ -
”。[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
是无论是作为在
strftime(3)
从C标准库,或所支持的特殊标记中的一个。有关详细信息,请参见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
)2326
(%b
)-
”。要登录0
无内容的“ ”,请
%B
改用。另一种常用的格式字符串称为合并日志格式。可以如下使用。
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined CustomLog log/access_log combined
此格式与“通用日志格式”完全相同,但增加了两个字段。每个其他字段都使用percent-directive
,其中header可以是任何HTTP请求标头。这种格式的访问日志如下所示:%{header}i
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\"
)/apache_pb.gif
)。"Mozilla/4.08 [en] (Win98; I ;Nav)"
(\"%{User-agent}i\"
)只需CustomLog
在配置文件中指定多个指令即可创建多个访问日志。例如,以下指令将创建三个访问日志。第一个包含基本CLF信息,第二个和第三个包含引用程序和浏览器信息。最后两CustomLog
行显示了如何模仿ReferLog
and 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"
此示例还表明,无需使用LogFormat
指令定义昵称。相反,可以在CustomLog
指令中直接指定日志格式。
有时根据客户端请求的特征方便地从访问日志中排除某些条目。在环境变量的帮助下,这很容易实现。首先,必须设置环境变量以指示请求满足某些条件。这通常可以通过完成
SetEnvIf
。然后,伪指令的
env=
子句CustomLog
用于包含或排除设置了环境变量的请求。一些例子:
# 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
在第一个示例中,User-agent
如果HTTP状态代码为400或501,将记录。在其他情况下,将记录文字“-”。同样,在第二个示例中,Referer
如果HTTP状态代码不是 200、204或302 ,则将记录。(请注意,状态代码之前为“!”。
尽管我们刚刚显示了条件日志记录非常强大和灵活,但这并不是控制日志内容的唯一方法。日志文件包含服务器活动的完整记录时,它们将更为有用。通常,简单地对日志文件进行后处理以删除您不想考虑的请求通常会更容易。
即使在繁忙的服务器上,日志文件中存储的信息量也很大。访问日志文件通常每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
执行日志轮换的另一种方法是使用管道日志,如下一节所述。
Apache httpd能够写入错误,并通过管道将日志文件访问另一个进程,而不是直接访问文件。此功能极大地增加了日志记录的灵活性,而无需在主服务器中添加代码。为了将日志写入管道,只需将文件名替换为管道字符“ |
”,后跟可执行文件的名称,该可执行文件应在其标准输入上接受日志条目。服务器启动时,服务器将启动管道日志进程,如果在服务器运行时崩溃,则将重新启动管道日志进程。(这最后一个功能是为什么我们可以将此技术称为“可靠的管道记录”。)
父Apache httpd进程产生了管道日志进程,并继承了该进程的用户ID。这意味着管道日志程序通常以root身份运行。因此,使程序保持简单和安全非常重要。
管道日志的一项重要用途是无需重新启动服务器即可允许日志轮换。Apache HTTP Server包含一个rotatelogs
为此目的而调用的简单程序。例如,要每24小时轮换一次日志,可以使用:
CustomLog "|/usr/local/apache/bin/rotatelogs /var/log/access_log 86400" common
注意,引号用于包围将为管道调用的整个命令。尽管这些示例用于访问日志,但是可以将相同的技术用于错误日志。
与条件日志记录一样,管道日志记录是一个非常强大的工具,但是在可以使用脱机后处理等更简单的解决方案的地方,不应使用它们。
默认情况下,在不调用shell的情况下产生了管道日志进程。使用“ |$
”代替“ |
”来使用外壳程序(通常使用/bin/sh -c
)生成:
# Invoke "rotatelogs" using a shell CustomLog "|$/usr/local/apache/bin/rotatelogs /var/log/access_log 86400" common
这是Apache 2.2的默认行为。根据外壳的具体情况,这可能会导致在日志记录管道程序的整个生命期内进行额外的外壳过程,并在重新启动期间出现信号处理问题。出于与Apache 2.2兼容性的考虑,||
还支持符号“ ”,等效于使用“ |
”。
请注意,在Windows上,运行许多管道记录器进程时可能会遇到问题,尤其是当HTTPD作为服务运行时。这是由于桌面堆空间不足而引起的。分配给每个服务的桌面堆空间由SharedSection
HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ SessionManager \ SubSystems \ Windows注册表值中参数的第三个参数指定
。小心改变这个值 ; 通常会使用更改Windows注册表的警告,但是如果将数字调整得太高,您也可能会耗尽桌面堆池。
当运行具有许多虚拟主机的服务器时,有几种处理日志文件的选项。首先,可以完全像在单主机服务器中那样使用日志。只需将日志记录伪指令放置<VirtualHost>
在主服务器上下文中各部分的外面,就可以将所有请求记录在同一访问日志和错误日志中。此技术无法轻松收集各个虚拟主机上的统计信息。
如果CustomLog
或ErrorLog
指令放在
<VirtualHost>
节中,则该虚拟主机的所有请求或错误将仅记录到指定文件中。任何没有日志记录指令的虚拟主机仍会将其请求发送到主服务器日志。该技术对于少量虚拟主机非常有用,但是如果主机数量很大,则管理起来可能会很复杂。另外,它经常会产生文件描述符不足的问题。
对于访问日志,有一个很好的折衷方案。通过将虚拟主机上的信息添加到日志格式字符串中,可以将所有主机记录到同一日志中,然后将日志拆分为单个文件。例如,考虑以下指令。
LogFormat "%v %l %u %t \"%r\" %>s %b" comonvhost CustomLog logs/access_log comonvhost
该%v
用于记录所服务请求的虚拟主机的名称。然后,可以使用诸如split-logfile之类的程序对访问日志进行后处理,以便将其分为每个虚拟主机一个文件。
相关模块 | 相关指令 |
---|---|
mod_logio
添加了两个附加
LogFormat
字段(%I和%O),它们记录了网络上实际接收和发送的字节数。
mod_log_forensic
提供客户请求的取证日志。记录是在处理请求之前和之后完成的,因此,取证日志包含每个请求的两条日志行。取证记录器非常严格,没有自定义设置。它可能是非常宝贵的调试和安全工具。
启动时,Apache httpd将父httpd进程的进程ID保存到file中logs/httpd.pid
。可以使用PidFile
指令更改该文件名。进程ID供管理员用于通过向父进程发送信号来重新启动和终止守护程序。在Windows上,请改用-k命令行选项。有关更多信息,请参见停止和重新启动页面。
为了帮助调试,该
ScriptLog
指令允许您记录CGI脚本的输入和输出。仅应将其用于测试中,而不应用于实时服务器。有关更多信息,请参见mod_cgi文档。