Der Fehler ist, dass Sie zuerst [
entfernen sollten da Sie den Exit-Status überprüfen möchten, verwenden Sie den Befehl direkt.
Die Wiki-Seiten des Tools Shellcheck haben dazu eine Erklärung (issue SC1014):
[ .. ]
ist nicht Teil der Shell-Syntax wie if
Aussagen. Es ist nicht gleichbedeutend mit Klammern in C-ähnlichen Sprachen, if (foo) { bar; }
, und sollte nicht um zu testende Befehle gewickelt werden.
[
ist nur ein normaler Befehl, wie whoami
oder grep
, aber mit komischem Namen (siehe ls -l /bin/[
). Es ist eine Abkürzung für test
.
Wenn Sie den Beendigungsstatus eines bestimmten Befehls überprüfen möchten, verwenden Sie diesen Befehl direkt.
Wenn Sie die Ausgabe eines Befehls überprüfen möchten, verwenden Sie "$(..)"
um seine Ausgabe zu erhalten, und verwenden Sie dann test
oder [
/[[
um einen Zeichenfolgenvergleich durchzuführen:
Verwenden Sie auch ps aux | grep -q "[r]elayevent.sh"
sodass Sie den Exit-Status im Hintergrund erhalten, anstatt irgendetwas auf stdout
zu drucken .
Oder Sie können pgrep
verwenden und leite seine Ausgabe an /dev/null
weiter .
Verwenden Sie zuerst die zweite Bedingung, da dies für den letzten Fall effizienter ist.
Das endgültige Skript sieht also folgendermaßen aus:
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh" ; do
sleep 3
let COUNTER+=1
done
Oder
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && pgrep "[r]elayevent.sh" >/dev/null ; do
sleep 3
let COUNTER+=1
done
Sie können keine Pipe innerhalb von [ ... ]
haben . Es ist auch besser, pgrep
zu verwenden als zu versuchen, die Ausgabe von ps
zu parsen :
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
BSD-Systeme könnten pgrep -q ...
verwenden statt pgrep ... >/dev/null
um die tatsächliche Ausgabe von pgrep
zu verwerfen , genau wie beim gewöhnlichen grep
(uns interessiert nur der Exit-Status).
Beachten Sie, dass wir pgrep
nicht einfügen Befehl innerhalb von [ ... ]
. Das liegt daran, dass wir nicht an seiner Ausgabe interessiert sind, sondern nur an seinem Exit-Status. Mit [ ... ]
Sie vergleichen normalerweise Zeichenfolgen oder Zahlen. Der [ ... ]
führt zu einem Exit-Status, der null (wahr) oder ungleich null (falsch) ist, genau wie pgrep
Ausführung.
Dies prüft jedoch nicht auf Sperrmechanismen, sondern nur darauf, ob ein bestimmter Prozess läuft oder nicht.
Wenn Sie versuchen, nur eine einzige Instanz eines Skripts zum Laufen zu bringen, dann ist es besser, so etwas zu tun (vorausgesetzt, der EXIT
trap wird immer dann ausgeführt, wenn das Skript ordnungsgemäß beendet wird):
lockdir=dir.lock
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
else
echo 'Only one instance of this script allowed' >&2
exit 1
fi
Mit einigen Versuchen und schlafen:
lockdir=dir.lock
count=0
while [ "$count" -lt 10 ]; then
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
break
else
echo 'Locked. Sleeping...' >&2
sleep 3
fi
count=$(( count + 1 ))
done
if [ "$count" -eq 10 ]; then
echo 'Giving up.' >&2
exit 1
fi
Verwandte:
- Wie stelle ich sicher, dass nur eine Instanz eines Bash-Skripts ausgeführt wird?