我需要创建历史唯一访问者(由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,但它看起来非常强大,如果我有更多的经验可以让它变得简单。
答案 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字段中删除时间。
第四行打印必填字段。
第五行根据日期对输出进行排序。
最后,再次使用uniq
和awk
以您希望的格式打印输出。
输出:
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
!)和操作系统。