Shell 技巧 - 日志文件分析回顾

作者:Dave Taylor

上个月,我们花了很多时间研究 Apache 日志文件,看看如何使用基本的 Linux 命令来确定您网站的一些基本统计信息。

您会记得,即使是像 head、tail 和 wc 这样的简单命令也可以帮助您计算出每小时的点击次数,并且结合一些明智的 grep 用法,可以显示您发送了多少图形,哪些 HTML 文件最受欢迎等等。

更重要的是,以最基本的方式使用 awk 可以轻松地提取特定列的信息,并查看标准 Apache 日志文件条目的不同字段具有不同的值。本月,我将进一步深入研究日志文件,并探索如何利用更复杂的脚本来确定给定时间单位的总字节传输量。

您传输了多少数据?

许多 ISP 对您的每月带宽都有最大分配量,因此能够计算出您发送了多少数据非常重要。让我们检查一个日志文件条目,看看字节发送字段在哪里

72.82.44.66 - - [11/Jul/2006:22:15:14 -0600] "GET
↪/individual-entry-javascript.js HTTP/1.1" 200 2374
↪"http://www.askdavetaylor.com/
↪sync_motorola_razr_v3c_with_windows_xp_via_bluetooth.html"
↪"Mozilla/4.0 (compatible; MSIE 6.0;
↪Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR
↪2.0.50727)"

这里有很多不同的数据字段,但我们想要的是字段 #10,在本例中是 2374。在文件系统上仔细检查,您会发现这是已发送文件的大小(以字节为单位),无论是图形、HTML 文件,还是在本例中,JavaScript 包含文件。

因此,如果您可以提取日志文件中所有字段 #10 的值并对其进行汇总,您就可以计算出总字节传输量。提取字段很容易;但是,将它们全部加起来就比较棘手了

$ awk '{ print $10 }' access_log

这使我们获得了所有传输大小,并且我们可以使用 awk 的功能使汇总也成为单行命令

$ awk '{ sum += $10 } END { print sum }' access_log

正如我之前所说,awk 对于那些愿意花一点时间学习其来龙去脉的人来说,功能非常强大。请注意这里的一个懒人快捷方式:我没有初始化变量 sum,只是利用了变量在 awk 中首次分配时设置为零的事实。并非所有脚本语言都提供此快捷方式!

无论如何,在访问日志上运行这个小小的单行命令,您就可以看到传输的总字节数:354406825。我可以将其除以 1024 来计算出千字节、兆字节等等,但这并不是有用的信息,除非我们能够弄清楚另一件事:这涵盖了多长时间?

我们可以通过查看日志文件的第一行和最后一行并计算差值来计算经过的时间,或者我们也可以简单地使用 grep 从日志文件中提取一天的的数据,然后将结果乘以 30 以获得运行的平均每月传输速率。

回顾日志文件条目;日期格式如下- [11/Jul/2006:22:15:14 -0600]。忽略除日期格式为 DD/MMM/YYYY 之外的所有内容。

我将使用 08/Aug/2006 对其进行测试,以仅提取当天的日志条目,然后将其馈送到 awk 脚本中

$ grep "08/Aug/2006" access_log | awk '{ sum += $10 }
↪END { print sum }'
78233022

只是一个非常粗略的估计:78MB。将其乘以 30,我们将获得该网站每月 2.3GB 的数据传输速率。

将其转换为 Shell 脚本

现在,让我们将其转换为实际的 shell 脚本。我想做的是从日志文件中提取前一天的数据并自动将其乘以 30,这样,无论何时运行该命令,我们都可以大致了解每月的数据传输速率。

第一步是进行一些日期计算。我将大胆假设您的系统上安装了 GNU date,它允许日期计算。如果没有,那么这超出了本文的范围,尽管我在我的书 Wicked Cool Shell Scripts (www.intuitive.com/wicked) 中谈到了这一点。

GNU date 允许您使用 -v 选项和修饰符来备份任意时间单位。要备份一天,请使用-v-1d。例如

$ date
Wed Aug  9 01:00:00 GMT 2006
$ date -v-1d
Tue Aug  8 01:00:47 GMT 2006

date 命令可以做的另一个巧妙技巧是使用 strftime(3) 手册页中详述的许多选项,以您需要的任何格式打印其输出。要获得 DD/MMM/YYYY,我们添加一个格式字符串

$ date -v-1d +%d/%b/%Y
08/Aug/2006

现在,让我们开始将脚本组合在一起。脚本中的第一步是创建此日期字符串,以便我们可以将其用于 grep 调用,然后继续提取和汇总当天传输的字节数。接下来,我们可以使用这些值通过 expr 命令计算其他值,并将所有内容保存在变量中,以便我们可以在最后获得一些可读的输出。

这是我的脚本,只有一点点花哨的步法

#!/bin/sh

LOGFILE="/home/limbo1/logs/intuitive/access_log"

yesterday="$(date -v-1d +%d/%b/%Y)"

# total number of "hits" and "bytes" yesterday:

hits="$(grep "$yesterday" $LOGFILE | wc -l)"

bytes="$(grep "$yesterday" $LOGFILE | awk '{ sum += $10 }
END { print sum }')"

# now let's play with the data just a bit

avgbytes="$(expr $bytes / $hits )"
monthbytes="$(expr $bytes \* 30 )"

# calculated, let's now display the results:

echo "Calculating transfer data for $yesterday"
echo "Sent $bytes bytes of data across $hits hits"
echo "For an average of $avgbytes bytes/hit"
echo "Estimated monthly transfer rate: $monthbytes"

exit 0

运行脚本,这是您将获得的数据类型(一旦您将 LOGFILE 变量指向您自己的日志)

$ ./transferred.sh
Calculating transfer data for 08/Aug/2006
Sent 78233022 bytes of data across 15093 hits
For an average of 5183 bytes/hit
Estimated monthly transfer rate: 2346990660

本月我们的空间已用完,但下个月,我们将回到此脚本并添加一些代码,以使传输速率以兆字节显示,或者,如果仍然太大,则以千兆字节显示。毕竟,估计每月 2346990660 的传输速率是一个只有真正的极客才会喜欢的值!

Dave Taylor 是一位拥有 26 年 UNIX 经验的资深人士,The Elm Mail System 的创建者,也是畅销书 Wicked Cool Shell ScriptsTeach Yourself Unix in 24 Hours 的作者,以及他的 16 本技术书籍。他的主要网站是 www.intuitive.com

加载 Disqus 评论