2013-03-30 21 views
0

我需要创建一个关于历史唯一访问者(由IP地址标识)的一次性报告,并按日期和操作系统从默认格式的Apache访问日志中组织。例如: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,但它看起来很强大,如果我有更多的经验,可以使它变得简单。

+0

什么是Apache Access日志的“默认格式”?如果你在谈论通用日志格式,它不包含任何用户代理信息... – FrankieTheKneeMan

+0

我的错误,格式实际上是:('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)') – tsspires

回答

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" 

要获得基于OS每天的独立访客数,他们正在使用:

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日志中的日期时间字段中删除时间。

第四行输出必填字段。

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

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

输出:

28/Oct/2012 127.0.0.1 Linux 1 
+0

我想OP希望统计不同的访问者,因此,当你有'uniq -c | awk'{print $ 3,$ 2,$ 4,$ 1}''时,我认为'uniq | awk'{print $ 2,$ 3}'| uniq -c | awk'{print $ 2,$ 3,$ 1}''更符合OP的速度。知识产权故意遗漏。 – FrankieTheKneeMan

+0

我已经给出了一个简约的答案。提供给uniq的输出是: '127.0.0.1 03/Nov/2012 Linux' 我正在考虑将上述行作为uniq访问者。 –

+0

你的答案并不简单,它是错误的。您正在计算每台操作系统每天每个客户端IP的访问次数。 OP需要的是每个操作系统每天唯一的客户端IP数量。你很接近,但只有一步。我的想法并不是放弃你的答案,而是写自己的答案,我只是指出你的答案的相当小的修改,使其不同于OP的请求。 – FrankieTheKneeMan

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(我用一个简单的二元组用于演示目的在这里):

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!)和操作系统。