# Ubuntu – Conditions and ranges within case statements in bash

bashsyntax

I was writing a plugin for Nagios to check the number of security packages and doing a case statement as the one here.

but the whole thing ended up turning into a freak show. All I basically wanted to do was saying if there are between 1-20 packages show this warning, if 21-infinity show critical and so on, but I could not just do [ -gt 1 ] or even [20-10000]

When applying these ranges the script would run kind of irregularly and warn when it was meant to be critical, etc. I think I gathered that ranges are not really possible here, I am just wondering why it worked for the example given above but not for me. Also, Is it in any way possible to include conditions within case?

In the end I managed to do a fully working script but I had to create if conditions and pass them to case. Just wondering if there was an easier way to do this without having to do that.

Below is more or less what I was trying to do. The last part was just me being desperate trying loads of different ranges to see if it worked.

case $SECURITY_PACKAGES in 0) echo "OK - not bad: There are a total of$TOTAL_PACKAGES packages to upgrade in this server, but none of them are security updates!"

exit 0

;;

[1-20]*)

echo "WARNING - $TOTAL_PACKAGES packages required to upgrade in this server, of which$SECURITY_PACKAGES are security updates"

exit 1
;;

[21-99]|[100-999]|[1000-9999]*)

echo "CRITICAL -  $SECURITY_PACKAGES out of$TOTAL_PACKAGES are security     updates! Consider upgrading soon!"

exit 2
;;

*) echo "UNKNOWN - I am not sure what's happening now, check later or check server: $TOTAL_PACKAGES to upgrade,$SECURITY_PACKAGES are security updates"

exit 3
;;

esac


You cannot express number ranges easily in the case expressions - the pattern [1000-9999], for example, does not mean the numbers 1000 to 9999, but the characters 1, 0, 0, the range 0-9, the characters 9, 9, 9 - essentially all the digits. [1-85] does not mean the numbers 1 to 85, but the digits from 1 to 8, and 5, ... which are just the digits from 1 to 8. So [1-20]* means anything that begins with 1, 2, or 0 - so even 20000000 will match that. Use if/then/elif/else/fi instead:

if (( $SECURITY_PACKAGES == 0 )) then echo "OK - not bad: There are a total of$TOTAL_PACKAGES packages to upgrade in this server, but none of them are security updates!"
exit 0
elif (( $SECURITY_PACKAGES <= 20 )) then echo "WARNING -$TOTAL_PACKAGES packages required to upgrade in this server, of which $SECURITY_PACKAGES are security updates" exit 1 elif (($SECURITY_PACKAGES <= 9999 ))
then
echo "CRITICAL -  $SECURITY_PACKAGES out of$TOTAL_PACKAGES are security     updates! Consider upgrading soon!"
exit 2
else
echo "UNKNOWN - I am not sure what's happening now, check later or check server: $TOTAL_PACKAGES to upgrade,$SECURITY_PACKAGES are security updates"
exit 3
fi