首页 > 解决方案 > 获取最后日志 10 分钟的 shell 脚本问题

问题描述

我写了一个脚本来检查最后 10 分钟的最后一个 httpd 错误日志,但是我得到一个错误,它一直在循环:问题是脚本的输出是一个错误循环,直到日志文件结束我才得到日期 -通过运行 cmd date --date='-10min' 10 分钟,然后我逐行解析日志文件,然后检查日志文件中每一行的小时和分钟是否大于或等于日期的小时和分钟 -这里的 10 分钟是输出的一部分:

./test2.sh: line 26: [: -ge: unary operator expected
./test2.sh: line 26: [Mon: command not found
./test2.sh: line 26: [: -ge: unary operator expected
./test2.sh: line 26: [Mon: command not found
./test2.sh: line 26: [: -ge: unary operator expected
./test2.sh: line 26: [Mon: command not found
./test2.sh: line 26: [: -ge: unary operator expected
./test2.sh: line 26: [Mon: command not found

当我尝试在这里调试它时,这是问题的一部分,并且它在日志文件的每一行中重复:

+ IFS=
+ read -r line
+ errorBool=0
+ [[ [Sun Apr 28 03:52:39.791442 2019] [autoindex:error] [pid 15012] 
[client 127.0.0.1:49054] AH01276: Cannot serve directory /var/www/html/: 
No matching DirectoryIndex (index.html,index.php) found, and server- 
generated directory index forbidden by Options directive == *:error* ]]
++ awk -F : '{printf $1}'
++ '[Sun' Apr 28 03:52:39.791442 '2019]' '[autoindex:error]' '[pid' 
'15012]' '[client' '127.0.0.1:49054]' AH01276: Cannot serve directory 
/var/www/html/: No matching DirectoryIndex '(index.html,index.php)' found, 
and server-generated directory index forbidden by Options directive
test2.sh: line 26: [Sun: command not found
++ awk '{printf $4}'
+ '[' -ge 12 ']'
test2.sh: line 26: [: -ge: unary operator expected

这是代码:

#!/bin/bash


#SCRIPT TO CHECK THE ERROR LOGS IN THE LAST 10 MINS

#VARIABLES

#NUMBER OF ERROR LOGS
errorCount=0
DATE_10_MIN=$(date --date='-10min' | awk '{print $4}' )
DATE_10_MIN_HOURS=$(date --date='-10min' | awk '{print $4}' | awk -F : 
'{print $1} ')
DATE_10_MIN_MIN=$(date --date='-10min' | awk '{print $4}' | awk -F : 
'{print $2} ')

#_______________________#

while IFS= read -r  line ; do


#BOOLEAN TO CHECK IF THE LINE HAVE THE EXPRESSION
errorBool=0


#if [[ $($line | awk '{print $4 }' | cut -c-8) -gt $DATE_10_MIN   ]] ; 
then

    if [[ $line  == *:error*  ]] ; then
            if [ [ $($line  | awk  '{print $4}' | awk -F : '{print $1}' )  
-ge $DATE_10_MIN_HOURS ] && [ $($line | awk  '{print $4}' | awk -F : 
'{print $2}')  -ge $DATE_10_MIN_MIN ] ]; then
            errorBool=1
            (( errorCount++ ))
            echo $line
            fi
    fi
 done < /var/log/httpd/error_log

 echo "There were $errorCount error logs in the last 10 mins "

标签: bashapacheshellloggingawk

解决方案


这适用于我的测试系统。要正确测试它,您必须更改输入数据中的日期:)。

代码

#!/bin/bash
#Script to check the error logs in the last 10 mins

#Variables.  Note: user variables should not be all uppercase.
errorCount=0
    # Number of error logs found
date_10_min_ago="$(date --date='-10min' +'%s')"
    # Time in seconds so it can be compared.
    # See https://unix.stackexchange.com/a/170982/63804 .

#_______________________#

while IFS= read -r line ; do
    if [[ $line  == *:error*  ]] ; then
        line_timestamp="$(awk -F '[][]' '{print $2}' <<<"$line")"
            # Get the date string, which is between brackets
        record_time="$(date --date="$line_timestamp" +'%s')"
            # Convert the date string to seconds.
            # Thanks to https://stackoverflow.com/a/1842754/2877364

        if (( record_time > date_10_min_ago)) ; then
            (( ++errorCount ))
            echo $line
        fi
    fi
done < 178.txt

echo "There were $errorCount error logs in the last 10 mins "

# vi: set ts=4 sts=4 sw=4 et ai:

样本输入

[Mon May 6 07:35:39.791442 2019] [autoindex:error] [pid 15012] [client 127.0.0.1:49054] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html,index.php) found, and server-generated directory index forbidden by Options directive - this error is older than 10 min
[Mon May 6 08:35:39.791442 2019] [autoindex:error] [pid 15012] [client 127.0.0.1:49054] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html,index.php) found, and server-generated directory index forbidden by Options directive
[Mon May 6 08:35:40.123456 2019] [autoindex:success] [pid 15012] [client 127.0.0.1:1337] Example input that doesn't contain the word "e r r o r"

输出

[Mon May 6 08:35:39.791442 2019] [autoindex:error] [pid 15012] [client 127.0.0.1:49054] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html,index.php) found, and server-generated directory index forbidden by Options directive
There were 1 error logs in the last 10 mins

解释

  • 如果日期是数字,比较日期会容易得多。该date +'%s'格式给出了每个日期的秒数*
  • 您可以从带有awk -F '[][]'. The[][]是匹配 a[或 a的正则表达式]。因此,awk -F '[][]' '{print $2}'获取错误日志的时间戳文本。然后date用于将该日期文本转换为秒数以进行比较。
  • 一般评论:我更喜欢把我的所有东西都包装起来$(),就"$()"好像我想要所有的输出一样。我认为这更清楚。
  • 正如@lojza 也提到的,一般来说,任何 bash 命令都必须完全在一行上。所以DATE_10_MIN_HOURS=$(some random code)很好,但是

    DATE_10_MIN_HOURS=$(some random code
    and more code on a different line)
    

    会导致错误。

* 这可能无法在闰秒内按原样工作。


推荐阅读