编写一个 Bash shell 脚本来读取 mongodb 日志文件并将其内容写入另一个文本文件

问题描述

我正在尝试读取位于 /var/log/mongodb 的 MongoDB 日志文件,其内容如下:


2019-11-04T05:04:00.390-0800 I COMMAND [conn38649] command loldb.$cmd command: update { update: "SUBSCRIPTION",ordered: true,writeConcern: { w: 1 },$db: " loldb" } numYields:0 reslen:295 锁:{全局:{acquireCount:{r:460,w:460}},数据库:{acquireCount:{w:460}},集合:{acquireCount:{w:459} },oplog:{acquireCount:{w:1}}}协议:op_query 568ms

2019-11-04T05:04:00.396-0800 I COMMAND [conn38657] command loldb.SUBSCRIPTION command: find { find: "SUBSCRIPTION",filter: { customerID: 75824180,policeDepartmentID: 1 },projection: {},$readPreference: { mode: "secondaryPreferred" },$db: "loldb" } planSummary: COLLSCAN keysexamined:0 docsexamined:69998 cursorExhausted:1 numYields:550 nreturned:1 reslen:430 locks:{ Global: {acquireCount: { r: 1102}},数据库:{acquireCount:{r:551}},集合:{acquireCount:{r:551}}}协议:op_query 424ms

2019-11-04T05:04:00.402-0800 I COMMAND [conn38735] command loldb.SUBSCRIPTION command: find { find: "SUBSCRIPTION",filter: { customerID: 75824164 },$db: "loldb" } planSummary: COLLSCAN keysexamined:0 docsexamined:58142 cursorExhausted:1 numYields:456 nreturned:1 reslen:417 locks:{ Global: {acquireCount: { r: 914 } },数据库:{acquireCount:{r:457}},集合:{acquireCount:{r:457}}} 协议:op_query 374ms


每个块引用是一个单行条目

文件内容每秒更新一次,我需要读取文件,如果查询时间 protocol:op_query 385ms 超过 300 毫秒,我需要将整个日志/行保存到另一个文本文件 slow_queries.text 中。

我正在读取的文件.log 文件,但内容看起来像 JSON 格式(如果我错了,请纠正我)前面是时间戳和命令类型,有没有什么有效的方法来读取这个数据格式?我只是逐字逐句地阅读。

另外,我该怎么做才能自动读取对 .log 文件所做的更改,而无需每次都运行脚本?

解决方法

我刚刚在我的本地机器上尝试过这个,可能需要为您的用例做一些工作。但我添加了一些评论,所以也许这会对您有所帮助:

编辑:我添加了时间戳检查,您必须根据需要对其进行配置

#!/bin/bash

# continously read from the file and pipe it into the while loop
tail -F "test.log" | \
while read LINE
do
    # get timestamp from LINE and get time in seconds
    timeinseconds="$(grep -P "^\S*" | date -d - +%s)"
    # get current timestamp before 5 minutes
    timebeforefivemin="$(date -d '-5 minutes' +%s)"
    # only log if timestamp of line is smaller to time before 5 min
    if [[ $(expr $timeinseconds - $timebeforefivemin) -lt 0 ]];
        then
        # get the time of the query from the line
        querytime="$(echo "$LINE" | grep -oP '\d+ms' | grep -oP '\d+')"
        #if the grep was successful and the query time is greater than 300
        if [ $? = 0 ] && [ "$querytime" -gt 300 ]
        then
            # echo the line into the slow_queries file -> change it to the path you want
            echo "$LINE" >> slow_queries.txt
        fi
    fi
done