L'errore è che dovresti rimuovere prima [
perché vuoi controllare lo stato di uscita, quindi usa direttamente il comando.
Le pagine Wiki dello strumento Shellcheck hanno una spiegazione per questo (problema SC1014):
[ .. ]
non fa parte della sintassi della shell comeif
dichiarazioni. Non è equivalente alle parentesi nei linguaggi simili al C,if (foo) { bar; }
, e non dovrebbe essere avvolto intorno ai comandi da testare.
[
è solo un normale comando, comewhoami
ogrep
, ma con un nome buffo (vedils -l /bin/[
). È una scorciatoia pertest
.Se vuoi controllare lo stato di uscita di un certo comando, usa quel comando direttamente.
Se vuoi controllare l'output di un comando, usa
"$(..)"
per ottenere il suo output, quindi usatest
o[
/[[
per fare un confronto tra stringhe:
Usa anche ps aux | grep -q "[r]elayevent.sh"
in modo da ottenere lo stato di uscita in silenzio invece di stampare qualsiasi cosa su stdout
.
Oppure puoi usare pgrep
e indirizza il suo output a /dev/null
.
Usa prima la seconda condizione perché sarà più efficiente per l'ultimo caso.
Quindi lo script finale sarà come:
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh" ; do
sleep 3
let COUNTER+=1
done
Oppure
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && pgrep "[r]elayevent.sh" >/dev/null ; do
sleep 3
let COUNTER+=1
done
Non puoi avere una pipa all'interno di [ ... ]
. È anche meglio usare pgrep
piuttosto che cercare di analizzare l'output di ps
:
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
I sistemi BSD potrebbero usare pgrep -q ...
invece di pgrep ... >/dev/null
per scartare l'output effettivo di pgrep
, proprio come con il normale grep
(siamo interessati solo allo stato di uscita).
Nota come non inseriamo il pgrep
comando all'interno di [ ... ]
. Questo perché non siamo interessati al suo output, solo al suo stato di uscita. Con [ ... ]
di solito confronti stringhe o numeri. Il [ ... ]
risulterà in uno stato di uscita che è zero (vero) o diverso da zero (falso), proprio come il pgrep
esecuzione.
Tuttavia, questo non controlla alcun meccanismo di blocco, ma solo se un particolare processo è in esecuzione o meno.
Se stai cercando di eseguire solo una singola istanza di uno script, allora è meglio fare qualcosa del genere (supponendo che EXIT
trap viene eseguito ogni volta che lo script termina in modo ordinato):
lockdir=dir.lock
if mkdir "$lockdir"; then
trap 'rmdir "$lockdir"' EXIT
else
echo 'Only one instance of this script allowed' >&2
exit 1
fi
Con una serie di tentativi e dormi:
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
Correlati:
- Come assicurarsi che venga eseguita solo un'istanza di uno script bash?