访问过 /page1 和 /page2 的访客

访问过 /page1 和 /page2 的访客

在我的 Apache 日志文件中,other_vhosts_access.log如下所示:

www.example.com:80 12.34.56.78 - - [01/Aug/2017:00:42:18 +0200] "GET /page1.html HTTP/1.1" 200 1542 " "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
www.example.com:80 99.99.99.99 - - [02/Aug/2017:06:19:44 +0200] "GET /test.jpg HTTP/1.1" 200 90749 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
www.anotherwebsite.com:80 11.11.11.11 - - [04/Aug/2017:09:39:01 +0200] "GET /test.jpg HTTP/1.1" 200 90749 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"

...
www.example.com:80 12.34.56.78 - - [23/Aug/2017:01:12:11 +0200] "GET /somethingelse2.html HTTP/1.1" 200 21161 "http://www.example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"

我想找到访问过的访客/page1.html /somethingelse2.html,在此示例中:12.34.56.78。

如果我使用:

grep page1.html other_vhosts_access.log

我无法再过滤输出,因为其余行不包含somethingelse2.html.

如何查找访问过一个特定页面+另一页面的访客?

答案1

使用bash,grepawk:

这是获取与该page1.html文件相关的所有 IP 号码的方法:

awk '/page1\.html/ { print $2 }' log

对于示例数据,这将输出12.34.56.78.

这可用于获取包含该 IP 地址的所有日志条目:

grep -wF -f <( awk '/page1\.html/ { print $2 }' log ) log

这使用命令的结果awk作为模式,并再次扫描日志文件以输出包含该 IP 的所有行。这将返回示例中的第一行和最后一行。

和标志 to-w用于告诉-Fgrepgrep将模式(IP 地址)解释为固定串(-F ) 并仅返回包含该字符串作为整个词( -w)。这意味着12.34.56.789不会与固定字符串模式匹配12.34.56.78

从这个结果我们可以消除page1.html关于的线条

grep -wF -f <( awk '/page1\.html/ { print $2 }' log ) log | grep -vF 'page1.html'

现在您拥有了页面访问者生成的所有日志条目page1.html(但不包括page1.html页面本身)。

如果您想获取某个项目的条目特别的其他页面,然后将最后一个更改grep -vF 'page1.html'grep -F 'otherpage.html'


我很确定那里有更强大的日志解析和分析工具,但如果有的话,我不知道它们(我不经常进行日志解析)。

答案2

通常,这是在 awk 中使用关联数组来记住输入中已经看到的内容来完成的。使用默认的 awk 空白字段分隔符,我们注意到字段 2 是 ip 地址,字段 8 是 url,因此,例如,

awk '$8=="/page1.html"          { ipaddr[$2] = 1; next }
     $8=="/somethingelse2.html" { if(ipaddr[$2]==1)print $2 }'

这将比较 url 字段,当它与第一个 url 匹配时,它会在数组中ipaddr为 ip 地址创建一个条目,以保存值 1。当它与第二个 url 匹配时,它会检查我们是否为同一 ip 地址设置了该条目,并且如果是这样打印它。为了避免重新打印相同的 IP 地址,我们可以将其记录在另一个数组中:

awk '$8=="/page1.html"          { ipaddr[$2] = 1; next }
     $8=="/somethingelse2.html" { if(ipaddr[$2]==1 && !done[$2]){print $2; done[$2]=1 } }'

如果 url 可能有查询部分(例如"/page1.html?id=77"),您可以使用匹配而不是比较,即$8~/^\/page1.html/

如果可能以相反的顺序访问 url,您可以使用位掩码值来记住您已经见过的一个,例如 1 表示 page1,2 表示 someelse2,然后等到您获得值 3。位掩码仅在 awk 中可用通过or和等函数and。所以我们可能有

awk '
BEGIN { v["/page1.html"] = 1
        v["/somethingelse2.html"] = 2
}
$8=="/page1.html" || $8=="/somethingelse2.html"  {
  ipaddr[$2] = or(ipaddr[$2], v[$8])
  if(ipaddr[$2]==3){ print $2; ipaddr[$2] = 4 }
}'

这会在开始时完成的 BEGIN 块中设置关联数组中的映射,v以将 url 转换为我们的位掩码值(只是一个整数)。当任一 url 匹配时,记住的值具有适当的位掩码值或 -ed。如果现在是 3,我们打印该地址,并将其设置为不会再次打印。

答案3

在此任务中,您可能会发现 other_vhosts_access.log 的格式比您关心的要丰富。我建议你挑选一些你最喜欢的列,例如awk '{print $2, $8}' other_vhosts_access.log > small.log,然后操作small.log,这样你可以更方便地观察。

问题的解释是https://httpd.apache.org/docs/2.4/logs.html

...常用的格式字符串称为组合日志格式。它可以按如下方式使用。 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{推荐人}i\" \"%{用户代理}i\"" 组合

这似乎就是你正在使用的。您example.com在(经过清理的)日志中引用了该内容,表明像 example.com 这样的网站具有指向您网站的 HREF,并且浏览器在其 GET 请求中包含“Referer:www.example.com”标头。

看起来 /page1 很可能有 /page2 的 HREF。某些浏览器会在 page2 请求上发送 page1 引用标头。您可以选择依赖于此,并 grep 查找“page2.*page1”。或者您可以选择依赖源 IP,如已接受的答案中所示。在这种情况下,您可能希望删除其他会导致错误匹配的分散注意力的列,并使用简化的small.log 进行分析。

相关内容