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 "
2
Answers
I see newline after
awk -F :
and I would write:This works on my test system. To test it properly, you have to change the dates in the input data 🙂 .
Code
Sample input
Output
Explanation
date +'%s'
format gives a numeric count of seconds* for each date.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. Thendate
is used to convert that date text to a count of seconds for comparison.$()
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, butwill cause an error.
* This may not work as-is across leap seconds.