【问题标题】:Perl + Bash one-liner to sum bytes sent from Apache log files: Can this be right?Perl + Bash one-liner to sum bytes sent from Apache log files: 这是对的吗?
【发布时间】:2014-07-13 03:44:26
【问题描述】:

客户已请求使用其传出带宽。

我们的 Apache 日志有如下几行,其中 36618 表示以字节为单位的传出请求大小:

111.111.111.11 - - - foo.org [23/May/2014:01:00:15 -0400] 036618"GET /baz/bar.html HTTP/1.1" 200 3734 "http://foo.org/baz/bar.html" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"

我构建了这个(主要是)Perl 单行代码,通过正则表达式获取所有这些数字,并将其附加到一个空数组,然后通过 Bash 计算器转储由 '+' 分隔的数组。 (下面的行最终通过|paste -sd+|bc 管道传递到标准输入的下面的行中。

@BYTES = (); while(<>) { push(@BYTES, $1) if ( $_ =~ qr/] (?:\d+|-) (\d+)/) }; foreach(@BYTES) { print "$_\n" }

但是,我看到的使用量比我预期的要高得多,在短短几天内就达到了数 GB。那是不对的。这里有什么问题?

更新请参阅下面的评论,我输入了错误的字段,我选择的字段是以微秒为单位提供请求的时间,一定会高于请求的大小(以字节为单位)。

【问题讨论】:

  • 我填错了,对不起!我有时间在微秒内处理请求!对不起!在这种情况下,它应该是 3734。

标签: apache perl bash sum


【解决方案1】:

但是,我看到的使用量比我预期的要高得多,在短短几天内就达到了数 GB。那是不对的。这里有什么问题?

可能是您查看了错误的字段,请在网络服务器配置中检查您的 LogFormat

111.111.111.11 - - - foo.org [23/May/2014:01:00:15 -0400] 0 36618 "GET /baz/bar.html HTTP/1.1" 200 3734 "http://foo.org/baz/bar.html" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36"

【讨论】:

  • 这是正确的答案,我在这篇文章之前就已经猜到了,但是我将它奖励给你,因为你实际上是完全正确的。
  • @GreggLeventhal 不需要使用sum => perl -nE '$s += $_ for /] (?:\d+|-) (\d+)/ END{ say $s }' logfile
【解决方案2】:

这似乎有效:

cat file.log | sed 's/"http.*//' | awk '{print $NF}' | paste -sd+ | bc

【讨论】:

  • 不错,但我不能保证每一行都有以http开头的引荐来源网址。您也可以将其缩短为sed 's/"http.*//' file.log | awk '{print $NF}' | paste -sd+ | bc
  • 对,不保证referer。使用grep -o "HTTP/1.*" file.log | awk '{print $3}' | paste -sd+ | bc
【解决方案3】:

也许:

sum=$( perl -anE '$sum += $F[8]} END {say $sum' file.log )

假设大小总是在一行的第 9 个字段中。

【讨论】:

    【解决方案4】:

    使用 perl 单行从正确的字段中提取:

    perl -ne '$s += $1 if /"\s+\d+\s+(\d+)\s+"/ }{ print "$s\n"' access_log
    

    【讨论】:

    • 你如何摆脱}{ ?我在想它是-n,但不是在代码周围放了一段时间(){},这是为什么呢?所以这评估为while (<>) {$s += $1 if /"\s+\d+\s+(\d+)\s+"/ } { print $s\n } ?
    • -e 'EXPR1; }{ EXPR2'-e 'EXPR1; END { EXPR2 }' 的 perl oneliner 快捷方式。不幸的是,我不知道它在 perldoc 中的记录位置,所以我无法指向参考。
    猜你喜欢
    • 1970-01-01
    • 2016-04-22
    • 2014-07-31
    • 2016-11-22
    • 2014-05-08
    • 2014-03-19
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    相关资源
    最近更新 更多