• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 日志文件

    为了有效地管理Web服务器,有必要获取有关服务器的活动和性能以及可能发生的任何问题的反馈。Apache HTTP Server提供了非常全面和灵活的日志记录功能。本文档介绍了如何配置其日志记录功能以及如何理解日志包含的内容。

    总览

    相关模块相关指令
    • mod_log_config
    • mod_log_forensic
    • mod_logio
    • mod_cgi

    Apache HTTP Server提供了各种不同的机制来记录服务器上发生的所有事情,从最初的请求到URL映射过程,再到连接的最终解决,包括过程中可能发生的任何错误。除此之外,第三方模块还可以提供日志记录功能,或将条目注入现有的日志文件中,并且诸如CGI程序,PHP脚本或其他处理程序之类的应用程序可以将消息发送到服务器错误日志。

    在本文档中,我们讨论作为http服务器标准部分的日志记录模块。

    安全警告

    任何可以写入Apache httpd写入日志文件的目录的人几乎都可以访问服务器启动时所使用的uid(通常是root)。千万不要给人的日志存储在没有意识到后果的目录的写权限;有关详细信息,请参见安全提示文档。

    此外,日志文件可能包含客户端直接提供的信息,而不会转义。因此,恶意客户端有可能在日志文件中插入控制字符,因此在处理原始日志时必须格外小心。

    错误记录

    相关模块相关指令
    • core
    • ErrorLog
    • ErrorLogFormat
    • LogLevel

    服务器错误日志(由ErrorLog伪指令设置名称和位置)是最重要的日志文件。Apache httpd将在此处发送诊断信息并记录其在处理请求时遇到的任何错误。当启动服务器或服务器操作出现问题时,它是第一个查看的地方,因为它通常包含发生问题的原因以及如何解决的详细信息。

    通常将错误日志写入文件(通常error_log在Unix系统以及error.logWindows和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脚本的调试输出。stderrCGI脚本写入的任何信息都将直接复制到错误日志中。

    %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,但将其设置为trace5for mod_rewrite

    这将替换RewriteLog服务器早期版本中存在的按模块记录的指令,例如。

    访问日志

    相关模块相关指令
    • mod_log_config
    • mod_setenvif
    • CustomLog
    • LogFormat
    • SetEnvIf

    服务器访问日志记录了服务器处理的所有请求。访问日志的位置和内容由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
    这是向服务器发出请求的客户端(远程主机)的IP地址。如果HostnameLookups设置为On,则服务器将尝试确定主机名并将其记录在IP地址的位置。但是,不建议使用此配置,因为它会大大降低服务器的速度。相反,最好使用日志后处理器logresolve来确定主机名。此处报告的IP地址不一定是用户所坐机器的地址。如果用户和服务器之间存在代理服务器,则该地址将是代理服务器的地址,而不是原始计算机的地址。
    -%l
    输出中的“连字符”表示请求的信息不可用。在这种情况下,不可用的信息是identd在客户端计算机上确定的客户端的RFC 1413身份。该信息高度不可靠,几乎不应使用,除非在受到严格控制的内部网络上使用。除非IdentityCheck设置为,否则Apache httpd甚至不会尝试确定此信息On
    frank%u
    这是由HTTP身份验证确定的请求文档的人的用户ID。通常在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在日志格式字符串中指定C语言标准库中的位置或受支持的特殊标记之一,format可以用另一种格式显示时间strftime(3)。有关详细信息,请参见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
    这是服务器发送回客户端的状态代码。该信息非常有价值,因为它揭示了请求是否导致成功的响应(代码以2开头),重定向(代码以3开头),客户端导致的错误(代码以4结尾)或错误。服务器(以5开头的代码)。可能的状态代码的完整列表可以在HTTP规范(RFC2616第10节)中找到。
    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" "Mozilla/4.08 [en] (Win98; I ;Nav)"
    

    其他字段是:

    "http://www.example.com/start"\"%{Referer}i\"
    “引用”(原文如此)HTTP请求标头。这提供了客户端报告已被引用的站点。(这应该是链接到或包含的页面/apache_pb.gif)。
    "Mozilla/4.08[en](Win98; I ;Nav)"\"%{User-agent}i\"
    用户代理HTTP请求标头。这是客户端浏览器报告的有关其自身的标识信息。

    多路访问日志

    只需CustomLog在配置文件中指定多个指令即可创建多个访问日志。例如,以下指令将创建三个访问日志。第一个包含基本CLF信息,第二个和第三个包含引用程序和浏览器信息。最后两CustomLog行显示了如何模仿ReferLogand 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笔记

    请注意,在Windows上,运行许多管道记录器进程时可能会遇到问题,尤其是当HTTPD作为服务运行时。这是由于桌面堆空间不足而引起的。分配给每个服务的桌面堆空间由SharedSectionHKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ SessionManager \ SubSystems \ Windows注册表值中参数的第三个参数指定。小心更改该值;通常会使用更改Windows注册表的警告,但是如果将数字调整得太高,您也可能会耗尽桌面堆池。

    虚拟主机

    当运行具有许多虚拟主机的服务器时,有几种处理日志文件的选项。首先,可以像在单主机服务器中一样使用日志。只需通过将日志记录伪指令放置<VirtualHost>在主服务器上下文中各部分之外,就可以将所有请求记录在同一访问日志和错误日志中。此技术无法轻松收集各个虚拟主机上的统计信息。

    如果CustomLogErrorLog指令放在<VirtualHost>节中,则该虚拟主机的所有请求或错误将仅记录到指定文件中。任何没有日志记录指令的虚拟主机仍会将其请求发送到主服务器日志。该技术对于少量的虚拟主机非常有用,但是如果主机数量很大,则管理起来可能会很复杂。另外,它经常会产生文件描述符不足的问题。

    对于访问日志,有一个很好的折衷方案。通过将虚拟主机上的信息添加到日志格式字符串中,可以将所有主机记录到同一日志中,然后将日志拆分为单个文件。例如,考虑以下指令。

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

    %v用于记录所服务请求的虚拟主机的名称。然后,可以使用诸如split-logfile之类的程序对访问日志进行后处理,以便将其分为每个虚拟主机一个文件。

    其他日志文件

    相关模块相关指令
    • mod_logio
    • mod_log_config
    • mod_log_forensic
    • mod_cgi
    • LogFormat
    • BufferedLogs
    • ForensicLog
    • PidFile
    • ScriptLog
    • ScriptLogBuffer
    • ScriptLogLength

    记录发送和接收的实际字节

    mod_logio添加了两个附加LogFormat字段(%I和%O),这些字段记录了在网络上接收和发送的实际字节数。

    法医记录

    mod_log_forensic提供客户请求的取证日志。记录是在处理请求之前和之后完成的,因此取证日志包含每个请求的两条日志行。取证记录器非常严格,没有任何自定义设置。它可以是宝贵的调试和安全工具。

    PID文件

    启动时,Apache httpd将父httpd进程的进程ID保存到file中logs/httpd.pid。可以使用PidFile指令更改此文件名。进程ID供管理员用于通过向父进程发送信号来重新启动和终止守护程序。在Windows上,请改用-k命令行选项。有关更多信息,请参见停止和重新启动页面。

    脚本日志

    为了帮助调试,该ScriptLog指令允许您记录CGI脚本的输入和输出。仅应将其用于测试中,而不应用于实时服务器。有关更多信息,请参见mod_cgi文档。