Operador unário esperado

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 }' | cut -d. -f1)
[ $CPU_USAGE -gt 85 ] && mail -s "$SUBJECT" "$TO" < $MESSAGE'

./cpu.sh: line 11: [: -gt: unary operator expected Qual pode ser a razão

    
por darshan krishnaiah 14.10.2016 / 06:52

2 respostas

7

O problema

O problema é que CPU_USAGE termina como uma string vazia. Isso causa um problema aqui:

[ $CPU_USAGE -gt 85 ] 

Depois que a variável shell é avaliada, o acima se torna:

[ -gt 85 ] 

Isso falha porque o argumento antes do -gt está ausente agora.

A solução

Para obter um CPU_USAGE não vazio, precisamos substituir:

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

com:

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

em que % foi adicionado.

Citação

Como mencionado acima, quando CPU_USAGE está vazio e sem aspas, recebemos o erro "Operador unário":

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

É uma boa prática citar variáveis shell em situações como esta. Se citarmos, receberemos uma mensagem de erro diferente:

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

Enquanto ainda recebemos um erro, esta mensagem de erro é pelo menos mais informativa: diz que $CPU_USAGE não é um número.

Simplificação

O processo cut não é necessário. Nós podemos substituir:

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

com:

CPU_USAGE=$(top -b -n1 | awk -F'[ .]+' '/^%Cpu/ {print }')
    
por John1024 14.10.2016 / 07:00
4

Sua linha

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

está incorreto. Primeiro, você está pedindo ao AWK para encontrar a linha que começa com Cpu , quando, na verdade, começa com %Cpu .

Em segundo lugar, você não precisa de cut part. Você pode usar awk diretamente:

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

Para o futuro, você pode depurar scripts com set -x na parte superior do script depois de #!/bin/bash line. Além disso, use o link que verificará a sintaxe de um script de shell

    
por Sergiy Kolodyazhnyy 14.10.2016 / 07:00