Errore di script Bash: prevista espressione intera


13

Sto riscontrando un problema piuttosto strano, sto eseguendo uno script (Bash) su più server e ha smesso di funzionare su uno dei server (funziona perfettamente su tutti gli altri server).

Ecco la parte problematica dello script: (non l'ho scritto da solo, tutti i crediti vanno a "Rich") ( http://www.notrainers.org/monitoring-memory-usage-on-linux-with-nagios- e-nrpe / )

    if [ "$result" -lt "$warn_level" ]; then     #Line 56
    echo "Memory OK. $result% used."
    exit 0;
elif [ "$result" -ge "$warn_level" ] && [ "$result" -le "$critical_level" ]; then  #Line 59
    echo "Memory WARNING. $result% used."
    exit 1;
elif [ "$result" -gt "$critical_level" ]; then   #Line 62
    echo "Memory CRITICAL. $result% used."
    exit 2;
fi

Messaggio di errore completo:

./check_memory.sh: Line 56: [: 7.: integer expression expected

./check_memory.sh: Line 59: [: 7.: integer expression expected

./check_memory.sh: Line 62: [: 7.: integer expression expected

Se hai bisogno di maggiori informazioni, fammi sapere e cercherò di fornirle il più velocemente possibile.

Apprezzo tutti gli input :)

Risposte:


5

Dal link che hai fornito, vedo la riga sotto.

result=$(echo "$used / $total * 100" |bc -l|cut -c -2)

Come da commento di @ Graeme, cambia la riga sopra in basso.

result=$(echo "$used / $total * 100" |bc -l)

Ora, dopo aver aggiunto la riga sopra, dobbiamo modificare l'output resultdell'intero come di seguito.

result1=${result/.*}

Immagino in una delle macchine in cui si verifica l'errore, questo output non è un numero intero. Basta convertire l'output del risultato in numero intero in modo da poter gestire tali casi. Aggiungi la riga seguente dopo aver calcolato result.

result1=${result/.*}

E invece di resultmodificare i nomi delle variabili come result1all'interno dei ifloop e l'errore non si verificherà.

Ho il sospetto, gli cut -c -2attributi dell'errore soprattutto perché sta tagliando solo i primi 2 caratteri. Cosa succede se il risultato ha solo un carattere? Supponiamo che, se il risultato è 1.23456, il taglio sopra risulterà 1.come il valore per il resultquale ovviamente è la causa integer expecteddell'errore.

Il motivo per cui funziona correttamente nei server rimanenti è perché non si è verificato un caso in cui la resultvariabile ha una sola cifra. È molto probabile che fallisca anche nei server rimanenti se il risultato è una variabile a una cifra (qualcosa come ho menzionato nell'esempio sopra).


${result%%.*}sarebbe l'espansione corretta per rimuovere il punto decimale qui. Ma nota che cut -c -2causerà anche problemi con numeri di 100 o più, quindi è più sicuro lasciarlo cadere completamente.
Graeme,

@Graeme, l'ho perso. Avrei dovuto apportare le modifiche in quella riga :)
Ramesh

6

Dall'aspetto delle cose, la tua resultvariabile ha una .in essa dopo che il numero che fa bash non la riconosce come tale. Puoi riprodurre l'errore semplicemente facendo:

[ 7. -gt 1 ]

Se aggiungi più script alla tua domanda, posso suggerire da dove questo potrebbe provenire.

Aggiornare

Guardando la sceneggiatura completa, vorrei solo sostituire la riga:

result=$(echo "$used / $total * 100" |bc -l|cut -c -2)

Con:

result=$(( 100 * used / total ))

Poiché usede totalsono numeri interi e bashcompie l'aritmetica dei numeri interi, sebbene si noti che lo spostamento della moltiplicazione è 100 all'inizio. O se si desidera garantire l'arrotondamento corretto (la "divisione di numeri interi" nell'informatica arrotonda sempre efficacemente verso il basso):

result=$( printf '%.0f' $(echo "$used / $total * 100" | bc -l) )

Questo assicurerà che non ci siano punti finali in result. L'approccio utilizzato cutnon è una buona idea poiché è valido solo per il risultato nell'intervallo 10-99. Fallirà per a resultda 0-9 (come nel tuo caso) e anche numeri sopra 99.

Aggiornamento 2

Dal commento di @ Stephane qui sotto , è meglio arrotondare per eccesso rispetto alle soglie. Considerando questo, c'è un altro piccolo errore con lo snippet nella domanda - nota l'incoerenza tra i confronti usati per il warn_levele il critical_level. I confronti per warn_levelsono corretti, ma critical_levelutilizza -le(minore o uguale) anziché -lt(solo minore). Considera quando resultè leggermente più grande di critical_level- verrà arrotondato per difetto critical_levele non attivare l'avviso critico anche se dovrebbe (e farebbe se -ltfosse usato un confronto).

Forse non è un grosso problema, ma ecco il codice corretto:

if [ "$result" -lt "$warn_level" ]; then
  echo "Memory OK. $result% used."
  exit 0;
elif [ "$result" -lt "$critical_level" ]; then
  echo "Memory WARNING. $result% used."
  exit 1;
else
  echo "Memory CRITICAL. $result% used."
  exit 2;
fi

I -getest sono inoltre ridondanti poiché questi casi implicano il raggiungimento di elif/ else, quindi sono stati rimossi.


2
Tuttavia, per controllare le soglie, non si desidera arrotondare in su . 49.6 dovrebbe comunque essere OK se la soglia di avviso è 50. Quindi result=$(( 100 * $used / $total ))dovrebbe andare bene.
Stéphane Chazelas,

0

Quindi non so affatto usare awkmolto bene. Ma so che quello che sta succedendo nello script che hai collegato è un sacco di sciocchezze e che qualcosa di simile al seguente dovrebbe funzionare. Mi dispiace di non poterlo scrivere perfettamente, ma dato che stai già chiamando awk- due volte sembra - dovresti usare qualcosa del genere.

_chkmem() { return $( 
    free -m | grep "buffers/cache"
        awk '{ 
        percent = ( $3 / ( $3 + $4 ) ) * 100     
        warn = '"${warnlevel?No warning level specified!}"' < percent ? WARNING : OK
        crit = '"${critical?No critical level specified!}"' < percent ? CRITICAL : $warn
        print "Mem $crit : $percent% used"
        if ( $crit != OK ) exit 1
    }')
}

_chkmem || exit 1
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.