6
#!/bin/bash

SUBJECT="WARNING CPU USAGE HIGH"
TO=gmail id
MESSAGE=/tmp/messages
echo "#######################" > $MESSAGE
echo "CPU statistics as follows.." >> $MESSAGE
mpstat >> $MESSAGE
echo "#######################" >> $MESSAGE
CPU_USAGE=$(top -b -n1 | awk '/^Cpu/ {print $2}' | cut -d. -f1)
[ $CPU_USAGE -gt 85 ] && mail -s "$SUBJECT" "$TO" < $MESSAGE`

./cpu.sh: line 11: [: -gt: unary operator expected What might be the reason

  • 1
    Try quoting $CPU_USAGE: [ "$CPU_USAGE" -gt 85 ]. Also, this is bash. Just do (( CPU_USAGE > 85 )) && ... – muru Oct 14 '16 at 4:59
  • You might want to rm $MESSAGE in the end – grooveplex Oct 14 '16 at 8:33
7

The problem

The problem is that CPU_USAGE ends up as an empty string. This causes a problem here:

[ $CPU_USAGE -gt 85 ] 

After the shell variable is evaluated, the above becomes:

[ -gt 85 ] 

This fails because the argument before the -gt is now missing.

The solution

To get a non-empty CPU_USAGE, we need to replace:

CPU_USAGE=$(top -b -n1 | awk '/^Cpu/ {print $2}' | cut -d. -f1)

with:

CPU_USAGE=$(top -b -n1 | awk '/^%Cpu/ {print $2}' | cut -d. -f1)

where a % was added.

Quoting

As mentioned above, when CPU_USAGE is empty and unquoted, we get the "Unary operator" error:

$ CPU_USAGE=""; [ $CPU_USAGE -gt 85 ] && echo yes
bash: [: -gt: unary operator expected

It is best practice to quote shell variables in situations like this. If we do quote it, then we get a different error message:

$ CPU_USAGE=""; [ "$CPU_USAGE" -gt 85 ] && echo yes
bash: [: : integer expression expected

While we still get an error, this error message is at least more informative: it says that $CPU_USAGE is not a number.

Simplification

The cut process is not needed. We can replace:

CPU_USAGE=$(top -b -n1 | awk '/^%Cpu/ {print $2}' | cut -d. -f1)

with:

CPU_USAGE=$(top -b -n1 | awk -F'[ .]+' '/^%Cpu/ {print $2}')
  • I have made the necessary changes and the script has executed error free. But the script is unable to send the mail to the respective mail id. Since i am using ubuntu i have installed apt-get install mailutils. The mail is sent to /var/mail/root instead of the given mail id. – darshan krishnaiah Oct 14 '16 at 5:15
  • @darshankrishnaiah I'm glad that helped. Your mail command works fine for me but I am using BSD-mailx. Unfortunately, I have no experience with GNU's mailutils. – John1024 Oct 14 '16 at 5:27
4

Your line

top -b -n1 | awk '/^Cpu/ {print $2}' | cut -d. -f1

is incorrect. First of all , you're asking AWK to find line starting with Cpu, when in fact it starts with %Cpu.

Second, you dont need cut part. You can use awk directly:

$ top -b -n1 | awk '/^%Cpu/ {gsub(/\./," ");print $2}'                                             
31

For future, you can debug scripts with set -x at the top of the script after #!/bin/bash line. Also , use https://www.shellcheck.net/ which will check the syntax of a shell script

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.