2

I wrote a script that check last httpd error logs for the last 10 min but i got an error it stay looping: the problem is that the output of the script is a loop of errors until the log file ends I tyed to get the date - 10 min by running the cmd date --date='-10min' then I parsed the log file line by line then checked if the hours and minutes the every line in the log file is greater or equal to the hours and mins of date -10 mins here is a part of the output:

./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

when i tryed to debug it here is a part of the problem and its repeat in every line of the log file :

+ 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

Here is the code :

#!/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 "
taruk
  • 31
  • 5
  • Welcome to the site! **(1)** I see you have `if [ [ ` and `] ]; then`, with spaces between the brackets. If you remove the spaces, does the problem go away? **(2)** Would you please [edit your question](https://stackoverflow.com/posts/56002178/edit) to give us the details of the problem? Does the script terminate with an error, or does it produce unexpected results? **(3)** Would you please also edit the question to add a small input sample and the expected and actual output? That will help us test. Thanks! – cxw May 06 '19 at 10:49
  • i removed the spaces and nothing special, for the script is used to get the errors number in the last 10 min the output of the script is : ./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 and it loop until the log file ends – taruk May 06 '19 at 11:01

2 Answers2

1

This works on my test system. To test it properly, you have to change the dates in the input data :) .

Code

#!/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:

Sample input

[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"

Output

[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

Explanation

  • Comparing dates is much easier if they are numbers. The date +'%s' format gives a numeric count of seconds* for each date.
  • You can extract the timestamp from a line with awk -F '[][]'. The [][] is a regular expression that matches a [ or a ]. Therefore, awk -F '[][]' '{print $2}' gets the text of the error log's timestamp. Then date is used to convert that date text to a count of seconds for comparison.
  • General comments: I prefer to wrap all my $() as "$()" if I want all the output together. I think that is clearer.
  • As @lojza also mentioned, in general, any bash command must be entirely on one line. So DATE_10_MIN_HOURS=$(some random code) is fine, but

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

    will cause an error.

* This may not work as-is across leap seconds.

cxw
  • 16,685
  • 2
  • 45
  • 81
  • thnaks for the help its worked and thans for the advice too :) – taruk May 06 '19 at 14:55
  • @taruk Thanks! May I have an upvote as well? You accepted the answer, which is good --- it means this answer solved your problem. The upvote indicates that the answer was helpful, which may not always be the same thing ;) . See the [tour](https://stackoverflow.com/tour) for more of how the site works. Thanks for considering this request! – cxw May 06 '19 at 16:19
  • cxw, I think that they need "reputation" of 15 (I think) for that privilege. (I like the answer though, +1.) @taruk -- I absolutely support cxw's comment: it is precisely the voting that sets this resource (stackoverflow) apart from many other "forums." Once you have those (15?) points I encourage you to vote around the site as you see posts that you like (and absolutely on this one, since it even answered your question). – zdim May 06 '19 at 18:52
  • @zdim Thanks for the reminder - I forgot about the 15 level. Time for a meta post requesting OPs be allowed to upvote answers on their own questions :) . – cxw May 06 '19 at 19:21
  • @cxw Ha -- a great idea! That should indeed be allowed. (And perhaps ... encouraged ... with +1? Until they've got their 15.) – zdim May 06 '19 at 19:56
0

I see newline after awk -F : and I would write:

DATE_10_MIN=`date --date='-10min' '+%H:%M:%S'` 
DATE_10_MIN_HOURS=`date --date='-10min' '+%H'`
DATE_10_MIN_MIN=`date --date='-10min' '+%M'`
lojza
  • 1,823
  • 2
  • 13
  • 23