Unary operator expected

5,795

Solution 1

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}')

Solution 2

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

Share:
5,795

Related videos on Youtube

darshan krishnaiah
Author by

darshan krishnaiah

Updated on September 18, 2022

Comments

  • darshan krishnaiah
    darshan krishnaiah over 1 year
    #!/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

  • darshan krishnaiah
    darshan krishnaiah over 7 years
    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.
  • John1024
    John1024 over 7 years
    @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.