patternbashMinor
Alerting for rapid disk growth
Viewed 0 times
rapiddiskforgrowthalerting
Problem
I have a server that is pretty stable (disk capacity) until a certain event occurs and then the drive grows over the course of two days until it is full. I wrote a very simple bash script but I'm not too happy with parts of it. First, I want to be able to see the capacity as a percent down to the tenths place. Also, doing an evaluation I had to strip my value of any decimal places to compare it against my defined threshold. Lastly I feel that I made too much use of
cut where I could've been more efficient. I'd love to get some tips for improvement. #! /bin/bash
monDrive=/opt
prevReading=/root/diskcheckreading.txt
percentThreshold=1
emailAlert=alerts@domain.com
#Check if log file exists
if [ ! -f $prevReading ]
then
touch $prevReading
prev=$(printf "%0.2f\n" $(bc -l $prevReading
fi
#Get current percentage used of monitored drive
current=$(printf "%0.2f\n" $(bc -l $prevReadingSolution
-
Proceed when
Your script proceeds to create the file first, and then almost immediately performs the same calculation. In this case, it might be better to just create the file first,
-
Performing the same calculation twice
You are repeating the same commands for setting
-
As illustrated above,
-
Validate file contents
It's good practice to sanity check that the file you are reading from has valid data. A simple way to do so is to check if
If the input value
-
As you have discovered, the basic test command
To sum it up
Note:
Proceed when
prevReading file does not exist?Your script proceeds to create the file first, and then almost immediately performs the same calculation. In this case, it might be better to just create the file first,
exit from the script and then wait for its next invocation to do the comparison.-
Performing the same calculation twice
You are repeating the same commands for setting
prev and current, so you should put it in a function:checkDiskUse() {
df "$monDrive" | awk '/\'"$monDrive"'/{printf "%0.2f",$3/$2*100; exit}'
}-
cut -d' ' -f23/24 can be substituted with awkAs illustrated above,
awk can 'solve' your weird usage of cut-ting on whitespaces, and then calling bc on them. Your use of cut assumes that the relevant line has your desired values (used / total) exactly 23 whitespaces before them, which may be wrong in the future. Let awk do the whitespace parsing for you instead, and simply extract the third and second values respectively ($3, $2).-
Validate file contents
It's good practice to sanity check that the file you are reading from has valid data. A simple way to do so is to check if
printf is able to parse it correctly or not:printf "%0.2f" "$prev" > /dev/null || exitIf the input value
$prev is valid, printf returns with a successful exit code. Otherwise, the statement proceeds to the 'or' || part and exit the script as a fail-safe measure.-
[ vs [[As you have discovered, the basic test command
[ does not deal with decimal values, but bash's built-in [[ conditional expression happens to handle that well. Compare:$ [ 0.601 -gt 0.6 ] && echo Y
bash: [: 0.601: integer expression expected
$ [[ 0.601 > 0.6 ]] && echo Y
YTo sum it up
monDrive=/opt
prevReading=/root/diskcheckreading.txt
percentThreshold=1
emailAlert=alerts@domain.com
checkDiskUse() {
df "$monDrive" | awk '/\'"$monDrive"'/{printf "%0.2f",$3/$2*100; exit}'
}
[ -f $prevReading ] && prev=$(cat $prevReading) || { checkDiskUse > $prevReading; exit; }
printf "%0.2f" "$prev" > /dev/null || exit
current=$(checkDiskUse)
results=$(bc $percentThreshold ]]
then printf "\"$monDrive\" has grown $results%% in the past hour.\n\n$(hostname):$(pwd)/$(basename $0)" | \
mail -s "Disk Alert - $(hostname):$monDrive" $emailAlert
fi
emailecho $current > $prevReading
Note:
$monDrive is assumed to only contain / at the start, since only the first is escaped in the awk statement. Refer to comments for a somewhat hack-y workaround in vim's syntax highlighting (YMMV). Alternatively, I think using END instead of the regex might work too:df "$monDrive" | awk 'END{printf "%0.2f",$3/$2*100; exit}'Code Snippets
checkDiskUse() {
df "$monDrive" | awk '/\'"$monDrive"'/{printf "%0.2f",$3/$2*100; exit}'
}printf "%0.2f" "$prev" > /dev/null || exit$ [ 0.601 -gt 0.6 ] && echo Y
bash: [: 0.601: integer expression expected
$ [[ 0.601 > 0.6 ]] && echo Y
Ydf "$monDrive" | awk 'END{printf "%0.2f",$3/$2*100; exit}'Context
StackExchange Code Review Q#84222, answer score: 2
Revisions (0)
No revisions yet.