Zwei Bedingungen in der if-Anweisung

Zwei Bedingungen in der if-Anweisung

Ich habe Probleme mit der if-Anweisung

Ich möchte, dass die Meldung „Das System ist stark ausgelastet“ angezeigt wird, wenn die Speichernutzung oder CPU-Auslastung 70 % überschreitet. Jetzt habe ich die folgenden beiden Bedingungen in der if-Anweisung ausprobiert, aber es tritt ein Fehler auf.

# This script monitors CPU and memory usage
RED='\033[0;31m'
NC='\033[0m' # No Color


while :
do
  # Get the current usage of CPU and memory

  limit=70.0
  cpuUsage=$(top -bn1 | awk '/Cpu/ { print $2}')
  memTotal=$(free -m | awk '/Mem/{print $2}')
  memUsage=$(free -m | awk '/Mem/{print $3}')
  memUsage=$(( (memUsage * 100) / memTotal ))

  # Print the usage
  echo "CPU Usage: $cpuUsage%"
  echo "Memory Usage: $memUsage%"
  # Sleep for 1 second
  sleep 1

  if  (( $(echo "$cpuUsage > $limit ; $memUsage > $limit" |bc -l) ))
  then
         printf "${RED}The system is highly utilized${NC}\n"
  else
        echo The system is not highly utilized
  fi
done

soweit ich weiß, prüft der ;-Lauf die erste Bedingung und geht dann zur zweiten über, unabhängig vom Erfolg. Ich erhalte trotzdem diesen Fehler: 0 : Syntaxfehler im Ausdruck (Fehlertoken ist „0“)

Antwort1

bcversteht ||und &&.

if (( $(echo "$cpuUsage > $limit || $memUsage > $limit" | bc -l) ))

Antwort2

Obwohl Sie (wie Sie gesehen haben) Ausdrücke mit logical ||in GNU bc (und in busybox bc) kombinieren können, wird dies von POSIX1 nicht unterstützt .

topDa Sie bereits awk zum Parsen der und -Ausgaben verwenden free, wäre ein alternativer Ansatz, auch die arithmetischen und relationalen Tests in awk durchzuführen. Anschließend können Sie einen einfachen Ganzzahlvergleich in der Shell verwenden (wofür nicht einmal Bash erforderlich ist):

#!/bin/sh

# This script monitors CPU and memory usage

RED='\033[0;31m'
NC='\033[0m' # No Color

limit=${1:-70.0}

while :
do
  # Get the current usage of CPU and memory
  top -bn1 | awk -v limit="$limit" '
    /^%Cpu/ {printf "CPU Usage: %.1f%%\n", $2; exit ($2+0 > limit ? 1 : 0)} 
  '
  cpuHi=$?

  free -m | awk -v limit="$limit" '
    /^Mem/ {usage = 100*$3/$2; printf "Memory Usage: %.0f%%\n", usage; exit (usage > limit ? 1 : 0)}
  '
  memHi=$?

  sleep 1

  if [ "$cpuHi" -ne 0 ] || [ "$memHi" -ne 0 ]
  then
         printf "${RED}The system is highly utilized${NC}\n"
  else
        printf "The system is not highly utilized\n"
  fi

done

  1. Tatsächlich unterstützt POSIX bc nicht einmal relationale Operatoren außerhalb einer bedingten Konstruktion oder Schleife, zB:

     $ echo '2 > 1 || 1 > 2' | bc
     1
    

    aber mit aktivierten Warnungen:

     $ echo '2 > 1 || 1 > 2' | bc -w
     (standard_in) 1: (Warning) || operator
     (standard_in) 2: (Warning) comparison in expression
     1
    

    und ähnlich mit busybox

     $ echo '2 > 1 || 1 > 2' | busybox bc -w
     bc: POSIX does not allow boolean operators; this is bad: ||
     bc: POSIX does not allow comparison operators outside if or loops
     1
    

Antwort3

Um die Antwort von @choroba etwas zu erweitern:

echo "$cpuUsage > $limit ; $memUsage > $limit" |bc -l

wird ausgeben2 Zeilen.

Eine Demonstration

$ set -x
+ set -x
$ ans=$(echo "1==1; 2==1" | bc -l)
++ bc -l
++ echo '1==1; 2==1'
+ ans='1
0'
$ if (( $ans )); then echo yes; fi
+ ((  1
0  ))
bash: ((: 1
0 : syntax error in expression (error token is "0 ")

verwandte Informationen