1

好吧,伙计们,我真的在这里陷入了死胡同,不知道还能尝试什么...

我正在为一些电子邮件统计编写一个脚本,它需要做的一件事是计算邮件日志中所有消息的完整大小,这是我到目前为止所写的:

egrep ' HOSTNAME sendmail\[.*.from=.*., size=' maillog | awk '{print $8}' |  
tr "," "+" | tr -cd '[:digit:][=+=]' | sed 's/^/(/;s/+$/)\/1048576/' |  
bc -ql | awk -F "." '{print $1}'

这是我的邮件日志中的示例行:

Nov 15 09:08:48 HOSTNAME sendmail[3226]: oAF88gWb003226:  
from=<name.lastname@domain.com>, size=40992, class=0, nrcpts=24,  
msgid=<E08A679A54DA4913B25ADC48CC31DD7F@domain.com>, proto=ESMTP,  
daemon=MTA1, relay=[1.1.1.1]

因此,我将尝试逐步解释它:

首先,我通过文件查找包含实际“大小”的所有行,然后打印第 8 个字段,在本例中为“大小 = 40992”。

接下来,我用加号替换所有逗号字符。

然后我删除除数字和加号之外的所有内容。

然后我将行首替换为“(”,并将最后一个额外的加号替换为“)”,然后是“/1048576”。所以我得到一个像这样的巨大表达:

“(1+2+3+4+5...+n)/1048576”

因为我想将所有单独的消息大小相加并将其划分,所以我得到以 MB 为单位的结果。

最后一个 awk 命令是当我得到一个十进制数时,我真的不关心精度,所以我只打印小数点之前的部分。

问题是,这不起作用......我可以发誓它在某个时候起作用,会不会是我的表情太长而无法处理?

感谢您花时间阅读:)

4

2 回答 2

4

我认为单行awk脚本也可以。它匹配您的 egrep 模式匹配的任何行,然后对于这些行,它用 = 符号拆分第八条记录,并将第二部分(数字)添加到 SUM 变量中。当它看到文件的 END 时,它会打印出 SUM/1048576 的值(或以 Mibibytes 为单位的字节数)。

awk '/ HOSTNAME sendmail\[.*.from=.*., size=/{ split($8,a,"=") ; SUM += a[2] } END { print SUM/1048576 }' maillog
于 2010-11-16T01:43:58.147 回答
1
  • 如果输入中没有换行符,则 bc 会窒息,就像您的表达式一样。您必须将 sed 部分更改为:

sed 's/^/(/;s/+$/)\/1048576\n/'

  • 如果总大小小于 1MB 并且 bc 输出类似于 0.03333334234 的内容,最终的 awk 会很高兴地吃掉你的所有输出。如果您对小数部分不感兴趣,请从 bc 中删除最后一个 awk 命令和 -l 参数。

  • 我会用这个单线做到这一点:

grep ' 主机名 sendmail[[0-9][0-9]*]:..*:.*from=..*, size=' 邮件日志 | sed 's|.*, size=\([0-9][0-9]*\), .*|\1+|' | tr -d '\n' | sed 's|^|(|; s|$|0)/1048576\n|' | 公元前

于 2010-11-16T01:23:56.597 回答