【问题标题】:parse byte count in ftp log解析 ftp 日志中的字节数
【发布时间】:2013-09-15 20:55:24
【问题描述】:

我在 arm 架构上运行。 应该是一个 bash 脚本。 我想绘制进出我的 ftp 服务器的总字节数。

我用这个命令解析 ftp.log 文件来得到这个输出:

    `cat ftp.log | grep loaded`

有趣的行是这种格式:

Sep 14 18:46:00 sharecenter pure-ftpd: (doc@omega) [NOTICE] /mnt/HD/HD_a2//SAVE/backupffp.sh downloaded (423 bytes, 0.78KB/sec) Sep 15 22:06:47 sharecenter pure-ftpd: (doc@omega) [NOTICE] /mnt/HD/HD_a2//SAVE/ffp-2013-09-14.tar.bz2 downloaded (904753213 bytes, 1928.17KB/sec) Sep 15 22:32:26 sharecenter pure-ftpd: (doc@omega) [NOTICE] /mnt/HD/HD_a2//SAVE/test.avi uploaded (576711530 bytes, 1465.80KB/sec)

现在我需要获取 "(" 之后和单词 "bytes" 之前的值并添加它们。

  • 示例:

--> 下载423+904753213=904753636 => 返回值:904753636

--> 上传576711530 => 返回值:576711530

现在脚本将每 5 分钟运行一次,因此结果必须仅考虑最后 5 分钟之间的数字。 例子: 在 22:05 脚本运行并添加所有字节。当脚本在 22:10 再次运行时,仅应添加 22:05 到 22:10 之间传输的字节。

对于 rrd,您需要一个简单的输出,2 个变量“dowloaded”和“uploaded”。 所以我需要这 2 个变量中的这 2 个值。

我希望我足够清楚,如果不是,请不要犹豫,询问更多信息。

非常感谢您的帮助。

【问题讨论】:

    标签: bash ftp


    【解决方案1】:

    有很多方法可以做到这一点。这个很有趣:

    for i in $(grep -P -o '(?<=downloaded \()[0-9]+(?= bytes)' file.txt); do ((downloaded+=i)); done
    echo "Downloaded: $downloaded"
    


    现在脚本将每 5 分钟运行一次,因此结果必须仅考虑最后 5 分钟之间的数字。

    还有很多方法可以做到这一点。其中之一是使用tail -f,而不是每 5 分钟运行一次。另一种是记住文件行数(例如wc -l),然后你可以使用tail来获取附加部分。

    【讨论】:

    • “还有很多方法可以做到这一点。”请问有哪些方法?
    • @user2782004 我给了你线索。 wc -l 应该告诉您行数(例如 35)。现在,5 分钟后如果你再做一次,你会得到一个更大的数字(例如 40)。这样你就知道你应该只解析最后 5 行,所以你使用 tail -n 5tail -n +35 来获取最新的部分。
    【解决方案2】:

    这个版本对格式会很严格。即使某些部分会在文件 URL 中添加空格,它也可以工作。

    #!/usr/bin/awk -f
    
    BEGIN {
        u = d = 0
    }
    
    match($0, / downloaded  \([0-9]+/) {
        d += substr($0, RSTART + 14, RLENGTH - 14)
        next
    }
    
    match($0, / uploaded  \([0-9]+/) {
        u += substr($0, RSTART + 12, RLENGTH - 12)
    }
    
    END {
        printf("downloaded=%d\nuploaded=%d\n", d, u)  ## You can change this to have desired format of output.
    }
    

    输出:

    > awk -f script.awk file
    downloaded=904753636
    uploaded=576711530
    

    精简格式:

    awk 'BEGIN{u=d=0}match($0,/ downloaded  \([0-9]+/){d+=substr($0,RSTART+14,RLENGTH-14);next}match($0,/ uploaded  \([0-9]+/){u+=substr($0,RSTART+12,RLENGTH-12)}END{printf("downloaded=%d\nuploaded=%d\n",d,u)}' file
    

    要在 bash 脚本上运行它,请通过进程替换将 awk 作为输入运行,将格式更改为 "%d\n%d\n" 并读取包含两个变量的两行:

    #!/bin/bash
    { read downloaded; read uploaded; } < <(exec awk 'BEGIN{u=d=0}match($0,/ downloaded  \([0-9]+/){d+=substr($0,RSTART+14,RLENGTH-14);next}match($0,/ uploaded  \([0-9]+/){u+=substr($0,RSTART+12,RLENGTH-12)}END{printf("%d\n%d\n",d,u)}' file)
    echo "Downloaded: $downloaded"
    echo "Uploaded: $uploaded"
    

    【讨论】:

    • 哇,这令人印象深刻,我希望我知道如何操作所有这些强大的工具。
    • bash 脚本对我不起作用。我不知道如何发布我遇到的错误。我应该使用评论还是答案。
    • @user2782004 你可以在这里评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-28
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    相关资源
    最近更新 更多