0

In my custom bash script for server monitoring , which actually made to force my CentOS server take some actions and alert me if resources are overloaded more time than expected, I get the following error

line 17: [: 5.74: integer expression expected *

Now by definition all iostat results are float numbers and I already have used awk in my iostat command (WAIT) so how I can make my bash script to expect one instead of integer ?

** Value 5.74 represents current iostat result

#!/bin/bash

if [[ "`pidof -x $(basename $0) -o %PPID`" ]]; then
#       echo "Script is already running with PID `pidof -x $(basename $0) -o %PPID`"
        exit
fi

UPTIME=`cat /proc/uptime | awk '{print $1}' | cut -d'.' -f1`
WAIT=`iostat -c | head -4 |tail -1 | awk '{print $4}' |cut -d',' -f1`
LOAD=`cat /proc/loadavg |awk '{print $2}' | cut -d'.' -f1`

if [ "$UPTIME" -gt 600 ]
then
        if [ "$WAIT" -gt 50 ]
        then
                if [ "$LOAD" -gt 4 ]
                then
                        #action to take (reboot, restart service, save state sleep retry)
                        MAIL_TXT="System Status: iowait:"$WAIT" loadavg5:"$LOAD" uptime:"$UPTIME"!"
                        echo $MAIL_TXT | mail -s "Server Alert Status" "mymail@foe.foe"
                        /etc/init.d/httpd stop
#                       /etc/init.d/mysql stop
                        sleep 10
#                       /etc/init.d/mysql start
                        /etc/init.d/httpd start
                fi
        fi
fi

CentOS release 6.8 (Final) 2.6.32-642.13.1.el6.x86_64

  • Bash has only integer math; you need to use a tool other than bash (such as awk) to do floating-point. – Charles Duffy Feb 10 '17 at 16:59
  • However, this is easier (much easier!) because you're comparing to integer constants. – Charles Duffy Feb 10 '17 at 16:59
  • BTW, doing floating-point math in bash in general is [BashFAQ #22](http://mywiki.wooledge.org/BashFAQ/022). – Charles Duffy Feb 10 '17 at 17:01
  • ...as another aside, there's no need to `cat | awk | cut` -- `awk` can do the work of all three tools. `awk '{ print int($1) }' < /proc/uptime`. Using `cat foo | bar` is generally less efficient than `bar – Charles Duffy Feb 10 '17 at 17:03
  • For getting iowait percentage as an integer, I might use `iostat -c | awk 'NR == 4 { print int($4 * 100) }'`. – Charles Duffy Feb 10 '17 at 17:17
  • BTW, all-caps variable names are [specified by POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html) to be used for shell-builtin variables and environment variables with meaning to the OS or system; lowercase names are reserved for application use. Since even setting a regular shell variable will overwrite any environment variable having the same name, you should use lowercase variable names in your own code to prevent potential for conflicts. – Charles Duffy Feb 10 '17 at 17:19
  • As another aside -- don't end your quotes before expanding variables. `echo "String: ${variable}"` quotes both the constant string *and* the expansion -- and that's important, because unquoted expansions have a bunch of very surprising behaviors. (Contents are split on characters in `IFS` -- by default, spaces, tabs and newlines; and each result of that split is then expanded as a glob; thus, a string containing a whitespace-surrounded `*` will have a list of filenames in your current directory in the generated argument list). http://shellcheck.net/ will automatically catch this kind of bug. – Charles Duffy Feb 10 '17 at 17:35
  • (Similarly, `echo "$MAIL_TXT"`, not `echo $MAIL_TXT`; this is, incidentally, [BashPitfalls #14](http://mywiki.wooledge.org/BashPitfalls#echo_.24foo)). – Charles Duffy Feb 10 '17 at 17:41

1 Answers1

0

Normally, you'd need to use something other than native shell math, as described in BashFAQ #22. However, since you're comparing to integers, this is easy: You can just truncate at the decimal point.

[ "${UPTIME%%.*}" -gt 600 ] # truncates your UPTIME at the decimal point
[ "${WAIT%%.*}" -gt 50 ]    # likewise
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441