Apache日志分析:按操作系统按日期分类的唯一访问者

时间:2013-03-30 07:54:56

标签: python regex apache awk grep

我需要创建历史唯一访问者(由IP地址标识)的一次性报告,并按默认格式从Apache访问日志按日期和操作系统进行组织。例如:

Date OS    Count
3/1 iPhone 23
3/1 Windows 402
3/2 iPhone 32
etc..

我今天已经尝试了许多工具(Octupussy,AWStats,goaccess,appachetop),并且没有找到能够以这种方式打破日志的任何东西。操作系统报告可以在所有这些中找到,但它不是白天,只是整个日志。有人知道任何有这种功能的东西吗?

此外: 我正在考虑编写一个python程序,它将循环遍历日志并使用正则表达式或系统grep / awk命令,但如果有一个快速工具,或者如果awk可以轻松地做到这一点,我将不胜感激。我从来没有在今天之前使用过awk,但它看起来非常强大,如果我有更多的经验可以让它变得简单。

2 个答案:

答案 0 :(得分:1)

您没有在示例输出中包含IP地址,我正在使用输出中包含的IP地址写回答。

我的apache access.log文件的示例日志行:

27.0.0.1 - - [28/Oct/2012:21:38:34 +0530] "GET /phpmyadmin HTTP/1.1" 301 559 "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4"

根据用户使用的操作系统计算每日唯一身份访问者的数量:

awk '$6 ~ /GET/ \
{ gsub("[[]", "", $4); \ 
gsub(":.*", "", $4); \
print $1,$4,$14}' access.log | \

sort -t ' ' -k 2 | \
uniq -c|awk '{print $3,$2}'|uniq -c|awk '{print $3, $2, $1}'

以下答案适用于基于日期,每个操作系统的每个IP的唯一身份用户。

从上面获得所需输出的一个班轮:

awk '$6 ~ /GET/ \
{ gsub("[[]", "", $4); \ 
gsub(":.*", "", $4); \
print $1,$4,$14}' access.log | \

sort -t ' ' -k 2 | \
uniq -c|awk '{print $3,$2,$4,$1}'

<强>解释

第一个awk行是使用GET请求过滤行。

第二个awk行是删除额外的右方括号[

第三行将从apache日志中的datetime字段中删除时间。

第四行打印必填字段。

第五行根据日期对输出进行排序。

最后,再次使用uniqawk以您希望的格式打印输出。

输出:

28/Oct/2012 127.0.0.1 Linux 1

答案 1 :(得分:0)

对于组合日志格式,您可以像这样扫描:

In [1]: import re

In [2]: text = '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)"'

In [3]: logitems = re.compile('^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) ([^ ]*) ([^ ]*) \[([^\]]*)\] "([^"]*)" \d+ \d+ "([^"]*)" "([^"]*)"')

In [4]: logitems.findall(text)
Out[4]: [('127.0.0.1', '-', 'frank', '10/Oct/2000:13:55:36 -0700', 'GET /apache_pb.gif HTTP/1.0', 'http://www.example.com/start.html', 'Mozilla/4.08 [en] (Win98; I ;Nav)')]

假设text包含日志文件文本,使用re.findall将生成包含所需信息的元组列表。

假设你有这个元组列表,使用列表推导和一组来获取唯一的IP(我在这里使用一个简单的2元组用于演示目的):

In [4]: lst = [('127.0.0.1', 'foo'), ('192.168.0.1', 'bar'), ('123.022.200.023', 'baz'), ('127.0.0.1', 'double')]

In [5]: [i[0] for i in lst]
Out[5]: ['127.0.0.1', '192.168.0.1', '123.022.200.023', '127.0.0.1']

In [6]: list(set([i[0] for i in lst]))
Out[6]: ['192.168.0.1', '123.022.200.023', '127.0.0.1']

对于所有IP地址,您可以获得所有访问权限:

In [8]: [i for i in lst if i[0] == '127.0.0.1']
Out[8]: [('127.0.0.1', 'foo'), ('127.0.0.1', 'double')]

然后您可以按日期进一步过滤(将其转换为datetime.datatime!)和操作系统。