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
bc
versteht ||
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 .
top
Da 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
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 ")