简介
近几年,我有许多次被问到“Log Parser有何用处?”这一问题。每次,我都感到很难找到适当的语言来描述这个工具。每当我找到了一句话来进行描述的时侯,随后都会发现这句话遗漏了一些重要的内容,无法真正表达出该工具的灵活性。当然,这可能是由于开发人员的偏执造成的,不过我对自己的回答,从来没有感到满意过。
我不会告诉您,Log Parser“能做”什么。您 能用它来做什么,才是关键。我有很多次都对 Log Parser 的一些特殊应用感到很吃惊,我原以为它们是不可能实现的。我将告诉您它是 如何 运作的,希望这能让您懂得能用它来做什么,而且我会向您介绍该工具的三种最常见的应用方案。我敢肯定,您也会对 Log Parser 的新用途感到吃惊的。
历史点滴
在我们介绍 Log Parser 的内部原理之前,您可能想了解一下该工具的历史背景。2.0 版是 Microsoft对外发布的第一个版本。Log Parser 1.0 是 Microsoft 的内部测试工具,几年前由本人开发而成,用于实现 IIS日志记录功能的自动化测试。由于这个工具吸引了许多内部用户,因此本人于 2001 年 11 月推出了 2.0 版,并在 Internet上提供了免费下载。
不久后,2.1 版随 IIS 6.0 资源工具包一同发布。该工具包包含有对 SQL 引擎功能的重要更新。
最后,2.2 版(目前的版本)于 2005 年 1 月推出。该版本包含了大量输入和输出格式,以及针对 SQL 引擎核心的其它一些重要更新。
Log Parser 如何运作?
Log Parser 使用户可以根据需要混合和匹配 输入格式 和 输出格式,来创建数据处理管道。该工具使用以一种 SQL 语言编写的查询,在上述两个组件间创建管道。
输入格式
输入格式组件能够从各种源,读取并返回信息。输入格式提供的信息类似于数据库表,其中的记录由许多字段组成,而每个字段带有的值属于下列五种可能的数据类型之一:INTEGER、STRING、TIMESTAMP、REAL 和 NULL。
Log Parser 2.2 提供的输入格式包括:
• | 分析 IIS 生成的日志文件并返回日志中的条目的输入格式 |
• | 分析通用文本日志文件(按 CSV、TSV、NCSA、W3C 和 XML 标准进行格式化)并返回日志所含字段的输入格式 |
• | 一个返回来自 Windows 事件日志的事件的输入格式 |
• | 返回 Active Directory 对象、文件和目录以及注册表项上的信息的输入格式 |
• | 一个分析 NetMon 捕获文件并返回 TCP/IP 数据包和连接上的信息的输入格式 |
假如没有一个可用的输入格式满足我们的需求,Log Parser 2.2 还允许您编写自定义的 输入格式插件。这些都是简单的 COM 对象,可以用任何编程语言(包括 C# 和脚本语言)来编写。您所要做的就是确定要让插件返回何种信息,只要实现了该插件,就可以像“标准”输入格式那样使用。
输出格式
输出格式的作用与输入格式正好相反:使用 记录,并用记录中的字段执行一些有用的功能。Log Parser 2.2 提供的输出格式能够:
• | 将记录保存到文本文件(按 CSV、TSV、W3C 和 XML 标准格式化) |
• | 将记录保存到文本文件(根据特定于用户的通用模板格式化) |
• | 将记录显示到控制台或 GUI 窗口中 |
• | 将记录上载到 SQL 数据库的表中 |
• | 按 Syslog 标准格式化记录,并将记录分配给 Syslog 服务器、文本文件或用户 |
• | 创建 Excel 样式的图表,以图形格式呈现记录的数值数据 |
同样,如果没有一个可用的输出格式满足您的需求,您还可以通过编程方式,利用 Log Parser COM 对象,来使用记录。
核心 SQL 引擎
在输入和输出格式间有一个数据处理引擎,能够通过一种 SQL 语言执行查询。Log Parser 查询实际上是一种用于粘连输入格式和输出格式的一种“胶水”,指定如何在输入格式提供的数据到达输出格式之前,对其进行转换。
这种“胶水”最简单的实例就是“SELECT *”查询。该查询用于指示应该将来自输入格式的记录,按原样传输给输出格式。通常,在 转换 文件格式时,使用这个简单的查询:比如,选择一个能够分析源文件中的数据的输入格式和一个按目标格式将记录写入文件的输出格式,并使用“SELECT *”传输未经处理的记录。
不过,SQL 语言设计用于执行较简单的“SELECT *”更重大的任务。您可以使用 Log Parser,对来自输入格式的数据进行筛选、排序和聚合,将您的计算结果发送到可显示和/或存储您所提取的信息的输出格式。
命令行与可编脚本的 COM 对象
您可以通过两种不同的方法使用 LogParser:从命令行使用“LogParser.exe”可执行文件;从应用程序使用“LogParser.dll”库导出的 Log ParserCOM 对象。具体要选择何种方法,取决于您要通过 Log Parser 来执行的任务。
在下面所介绍的几种应用方案中,我将使用命令行可执行程序,但是请记住,也可以使用 Log Parser COM 对象,通过脚本来实现这些方案。很灵活,不是吗?
搜索数据
Log Parser 最常见的应用之一是:在一组特定的数据中,搜索特定的信息。想象一下您正在管理一个 IIS 网站,并且被告知,有些用户发现一些未指定的页需要很长的执行时间。
您可能想查明的第一件事就是:究竟是哪些页需要如此长的执行时间。需要通过记事本打开 IIS日志文件,查看数百万行日志条目吗?我可不这么认为。 假如您将 IIS 日志存储在 SQL 数据库中,您可能想运行一个查询,来找出运行时间超过10 秒钟的页——如果您真的这么做了,那么可能就不需要 Log Parser——至少对于这个问题是这样。要是您没有把日志保存在 SQL数据库中,又该怎么办呢?在这种情况下,您可以使用 Log Parser 分析 IIS 日志文件,查明哪些页所需的执行时间超过了 10秒钟,并将结果显示在控制台窗口中。
具体方法如下。假定 IIS Web 服务器以 W3C 扩展的日志格式记录日志,而您使用 IISW3C 输入格式,分析 IIS 日志文件。
在运行任何查询之前,您需要这个输入格式导出了哪些字段。若要确定这一点,请转到命令行,确认 LogParser.exe 在路径中,并执行该命令:
C:>logparser –h –i:IISW3C
这个命令提供了有关 IISW3C 输入格式的简明的帮助,其中包含一个列有 IISW3C 输入格式导出的所有字段的列表:
LogFilename (S) LogRow (I) date (T) time (T) c-ip (S) cs-username (S) s-sitename (S) s-computername (S) s-ip (S) s-port (I) cs-method (S) cs-uri-stem (S) cs-uri-query (S) sc-status (I) sc-substatus (I) sc-win32-status (I) sc-bytes (I) cs-bytes (I) time-taken (I) cs-version (S) cs-host (S) cs(User-Agent) (S) cs(Cookie) (S) cs(Referer) (S) s-event (S) s-process-type (S) s-user-time (R) s-kernel-time (R) s-page-faults (I) s-total-procs (I) s-active-procs (I) s-stopped-procs (I)
根据上述输出,并借助IIS 日志记录文档,您就可以知道所要的是所有“time-taken”字段大于 10,000(“time-taken”字段用于测量执行页所需的 毫秒 数)的日志条目的“cs-uri-stem”字段。 that the page takes to execute).圆括号中的字母代表字段的 类型。“cs-uri-stem”字段属于 STRING 类型,而“time-taken”字段则属于 INTEGER 类型。
然后,定位到保存 IIS 日志文件的文件夹,并执行此命令:
C:Logs>logparser "SELECT cs-uri-stem FROM ex*.log WHERE time-taken > 10000" –i:IISW3C
根据日志文件的大小,您可能需要等待几秒钟的时间,该命令才会开始输出结果。输出示例如下:
cs-uri-stem ------------------- /home/login.asp /home/login.asp /home/login.asp /home/login.asp /images/button.gif /home/login.asp /home/login.asp /home/login.asp /home/login.asp /home/login.asp Press a key...
首先,请注意,我们使用了“-i:IISW3C”来指定输入格式。这个参数告诉 Log Parser,我们要让 IISW3C 输入格式,为我们生成数据。
其次,请注意,我们并未指定任何输出格式;在这种情况下,Log Parser 会自动选择“NAT”输出格式,后者将在控制台窗口中,显示查询记录。实际上,这个输出格式在显示完十个记录后,就会暂停。它在等您按一下键盘上的任意键,随后将再次显示十个记录。
最后,请注意,我们的 SQL 查询的 FROM 子句指定了我们要让输入格式分析的数据的实际的 源。对于 IISW3C 输入格式,我们可以指定任意数量的本地或远程文件(甚至包含通配符)。您可以在 FROM 子句中,指定更多的参数,但我不会在这里谈论这些选项——您可以在 Log Parser 说明文档的“输入格式”下,找到这些参数。
现在,回到我们所给的例子上,您可以从结果中看到,多数情况下,“login.asp”页的执行时间较长。不过,您也可能看到,其它一些页的加载时间,有时也会超过十秒钟,所以您还可能想找出每个不同的页出现过多少次执行时间超过十秒钟的情况。在输出中,出现次数较少的页,可能只是日志中的假“噪声”。
那么,继续运行以下命令:
C:Logs>logparser "SELECT TOP 10 cs-uri-stem, COUNT(*) FROM ex*.log WHERE time-taken > 10000 GROUP BY cs-uri-stem ORDER BY COUNT(*) DESC" –i:IISW3C
具体输出可能如下所示:
cs-uri-stem COUNT(ALL *) ------------------------ ------------ /home/login.asp 371 /images/lglogo.gif 2 /images/button.gif 1 /news/today.htm 1
这将命令 Log Parser 执行以下操作:
1. | 查找所有页执行时间超过十秒钟的日志条目 |
2. | 对于结果中每个不同的 页 URL,计算页 URL 在结果中出现的次数——换句话说,某个页出现过多少次执行时间超过十秒钟的情况 |
3. | 按照从大到小的顺序,对所算出的出现次数的结果进行排序,并且仅显示前十个结果 |
根据上方的输出,您可以做出这样的结论:“login.asp”页频繁出现执行时间超过十秒钟的情况;结果中的其它页只是一些假条目,不能表明存在任何具体的问题。
将日志导出到 SQL 数据库
对于许多用户,Log Parser所实现的查询功能并不能满足他们的需求。譬如,管理流量繁重的网站的公司通常需要将网站日志保存在中央数据库中,从而可以在其中运行任意数量的查询,并在多台 Web 服务器间关联数据。Windows 事件日志及其它日志文件也可能存在这样的情况。
Log Parser 也可通过提供一个可用于将查询结果上载到数据库表的“SQL”输出格式,来应对上述情况。
一般而言,从日志文件到 SQL 表的简单“SELECT *”查询就可能解决问题,但是大多数时候,日志包含的一些条目,并不值得永久保存在数据包中。譬如,您可能想排除对图像文件的请求;也可能存在对不存在的页的请求。
以下命令可以做到这一点:
C:Logs>logparser "SELECT * INTO LogsTable FROM ex*.log WHERE TO_LOWERCASE (EXTRACT_EXTENSION(cs-uri-stem)) NOT IN ('gif';'jpg';'png') AND sc-status <> 404" –i:IISW3C –o:SQL –database:LogsDatabase
这个命令要求 Log Parser 筛选出以“.gif”、“.jpg”和“.png”结尾的页的条目(URL 不分大小写)。该命令还将排除 HTTP 错误代码“404”(即“page not found”)产生的请求。
所有其它请求都将传递给 SQL 输出格式,后者将把记录保存到 INTO 子句所指定的表中。另外,这个输出格式还接受“database”参数(可用于指定目标数据库的名称)以及其它许多参数(可用于指定到 SQL 数据库连接的其它属性)。
若要实现上述操作,您可以将上面的命令放在一个批处理文件中,并使用 SCHTASKS.EXE 工具,设定该批处理文件每小时运行一次——好了!——您就得到了一个自动的机制,可定期将日志文件中的条目,上载到 SQL 数据库。
请注意,每次执行上述命令时,Log Parser 都会反复检查 所有 日志条目,并将所有这些条目多次上载到数据库。我们真正需要的是一个“仅分析尚未分析过的日志条目”的机制。
Log Parser 2.2 的一个新功能正好可以满足这一要求:“增量分析”功能,也称为“检查点 (checkpointing)”。
大多数 Log Parser输入格式支持一个名为“iCheckpoint”的参数。该参数可告诉输入格式将所分析的所有文件的当前状态,都保存在一个专门的数据文件(“检查点(checkpoint)”文件)中。当您使用上一次分析期间生成的检查点文件执行查询时,输入格式将只分析输入文件中那些尚未分析过的部分——即 新的 条目。
所以,只需指定通过“iCheckpoint”参数,指定一个检查点文件的名称,具体如下:
C:Logs>logparser "SELECT * INTO LogsTable FROM ex*.log WHERE TO_LOWERCASE (EXTRACT_EXTENSION(cs-uri-stem)) NOT IN ('gif';'jpg';'png') AND sc-status <> 404" –i:IISW3C –o:SQL –database:LogsDatabase –iCheckpoint:MyCheckpoint.lpc
在您第一次执行该命令时,并不存在“MyCheckpoint.lpc”文件,而且 IISW3C输入格式分析了所有日志文件中的所有条目,并对结果数据进行筛选,最后再上载到数据库。在分析了所有日志后,IISW3C输入格式会将每个日志文件的当前大小保存到“MyCheckpoint.lpc”文件。
当您稍后运行相同的命令时,IISW3C 输入格式将从上次分析结束的地方,开始加载检查点文件,并分析日志,从而仅处理、筛选和上载新的日志条目。完成后,将针对日志文件的新大小更新检查点文件,随后这个过程将再次循环。
假如认真理解了本文开头处的设计说明,那么您可能已经知道:只需更改输入格式,您就重复使用该命令,将 Log Parser 输入格式支持的 任何 日志上载到数据库。想要上载事件日志条目吗?只需使用 EVT 输入格式,具体如下:
C:Logs>logparser "SELECT * INTO EventLogsTable FROM System" –i:EVT –o:SQL – database:LogsDatabase –iCheckpoint:MyCheckpoint.lpc
创建报表
至此,您应该已经知道:通过选择正确的输入格式并编写正确的查询,就可以从日志文件、系统或 Log Parser 支持的任何对象,获得所需的任何信息。
不过,我们只看到有关命令将信息返回到控制台窗口,或者将记录上载到 SQL 数据库。假如您正在使用 Log Parser,为您的管理团队生成报表,那么您可能需要某种比 SQL 表更人性化的东西,不是吗?
生成 HTML 页
在这个例子中,假设我们要生成一个报表,使之包含一台特定的远程计算机(将在该计算机的安全事件日志中检索)上的所有登录信息:
C:>logparser "SELECT ComputerName, TimeGenerated AS LogonTime, STRCAT(STRCAT(EXTRACT_TOKEN (Strings, 1, '|'), ''), EXTRACT_TOKEN(Strings, 0, '|')) AS Username FROM SERVER01 Security WHERE EventID IN (552; 528) AND EventCategoryName = 'Logon/Logoff'" -i:EVT
不要被该查询吓倒——其表面上的复杂性大多是因为我们为了从事件数据中提取完整的 <doman><username> 字符串,而执行的一些字符串操作造成的。
若使用 NAT 输出格式,具体的输出结果如下所示:
ComputerName LogonTime Username ------------ ------------------- ---------------------------- SERVER01 2004-06-24 09:47:12 NT AUTHORITYNETWORK SERVICE SERVER01 2004-06-24 09:48:05 SERVERDCAdministrator SERVER01 2004-06-24 09:48:05 NT AUTHORITYNETWORK SERVICE SERVER01 2004-06-24 10:00:59 NT AUTHORITYNETWORK SERVICE SERVER01 2004-06-24 10:01:00 NT AUTHORITYLOCAL SERVICE SERVER01 2004-06-24 10:01:06 SERVER01Gabriele SERVER01 2004-06-24 10:01:15 NT AUTHORITYLOCAL SERVICE SERVER01 2004-06-24 10:01:18 SERVERDCMonica SERVER01 2004-06-24 10:01:18 NT AUTHORITYLOCAL SERVICE SERVER01 2004-06-24 10:01:24 NT AUTHORITYLOCAL SERVICE
为了将该输出格式化为 HTML 格式,我们将使用 TPL 输出格式。该输出格式把一个参数作为说明如何格式化输出的文本文件(“模板”文件)。这里,我们将编写该模板文件,将输出转化为 HTML 表,具体如下:
<LPHEADER> <HTML> <HEAD><TITLE>Logon/Logoff Report</TITLE></HEAD> <BODY> <H1>Logon/Logoff Report</H1> <TABLE BGCOLOR="#D0D0E0" BORDER="1" CELLPADDING="10"> <TR> <TH>%FIELDNAME_1%</TH> <TH>%FIELDNAME_2%</TH> <TH>%FIELDNAME_3%</TH> </TR> </LPHEADER> <LPBODY> <TR> <TD><TT>%FIELD_1%</TT></TD> <TD><TT>%FIELD_2%</TT></TD> <TD><TT>%FIELD_3%</TT></TD> </TR> </LPBODY> <LPFOOTER> </BODY> </HTML> </LPFOOTER>
我不在这里深入探讨该模板文件的细节——其格式在 Log Parser 的联机文档中有非常详细的说明。请注意,这个模板文件分为三节(标题、正文和页脚),每一节都使用了特殊的“%变量%”(在运行时,由来自查询结果的值进行替换)。
现在,我们就可以通过上述命令,使用 TPL 输出格式,生成报表了:
C:>logparser "SELECT ComputerName, TimeGenerated AS LogonTime, STRCAT(STRCAT(EXTRACT_TOKEN (Strings, 1, '|'), ''), EXTRACT_TOKEN(Strings, 0, '|')) AS Username INTO Report.html FROM SERVER01Security WHERE EventID IN (552; 528) AND EventCategoryName = 'Logon/Logoff'" - i:EVT –o:TPL –tpl:MyTemplate.txt
该命令将生成一个“Report.html”文件,并在浏览器中打开,具体如“图 1”所示。
图 1:使用 TPL 输出格式生成的报表
生成图表
在最后一个例子中,我将向您展示如何在不使用 Excel 的情况下,直接从查询结果生成图表。
以下命令可计算出 IIS 日志文件每小时的命中总数,具体方法是:使用 CHART 输出格式,创建一个包含图表的 JPG 图像:
C:>logparser "SELECT TO_STRING(time, 'HH') AS Hour, COUNT(*) AS Hits INTO MyChart.jpg FROM ex*.log GROUP BY Hour ORDER BY Hour ASC" -i:IISW3C -o:CHART -chartType:ColumnClustered - chartTitle:"Hourly Hits" -groupSize:420x280
具体输出如“图 2”所示。
图 2:显示每小时命中数的图表输出
总结
我们已经看到 Log Parser 体系结构可实现大量应用方案,而这都是通过 Log Parser灵活的“数据处理管道”实现的。我向您介绍了可以使用 Log Parser 搜索数据,将日志上载到 SQL数据库,并生成报表,而这只是该工具常规应用方案的三个例子。
我在前面说过,很难用一句话来概括 Log Parser 的用户,我可不是在骗你——不是吗?