El error es que debes eliminar primero [
porque desea verificar el estado de salida, luego use el comando directamente.
Las páginas Wiki de la herramienta Shellcheck tienen una explicación para esto (problema SC1014):
[ .. ]
no es parte de la sintaxis de shell como if
declaraciones. No es equivalente a paréntesis en lenguajes tipo C, if (foo) { bar; }
, y no debe incluirse en los comandos para probar.
[
es solo un comando regular, como whoami
o grep
, pero con un nombre gracioso (ver ls -l /bin/[
). Es una abreviatura de test
.
Si desea verificar el estado de salida de un determinado comando, use ese comando directamente.
Si desea verificar la salida de un comando, use "$(..)"
para obtener su salida, y luego use test
o [
/[[
para hacer una comparación de cadenas:
También use ps aux | grep -q "[r]elayevent.sh"
para que obtenga el estado de salida en silencio en lugar de imprimir cualquier cosa en stdout
.
O puede usar pgrep
y dirige su salida a /dev/null
.
Use la segunda condición primero porque será más eficiente para el último caso.
Así que el guión final será como:
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh" ; do
sleep 3
let COUNTER+=1
done
O
#!/bin/bash
COUNTER=0
while [ "$COUNTER" -lt 10 ] && pgrep "[r]elayevent.sh" >/dev/null ; do
sleep 3
let COUNTER+=1
done
No puedes tener una tubería dentro de [ ... ]
. También es mejor usar pgrep
que intentar analizar la salida de ps
:
count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
sleep 3
count=$(( count + 1 ))
done
Los sistemas BSD podrían usar pgrep -q ...
en lugar de pgrep ... >/dev/null
para descartar la salida real de pgrep
, al igual que con el grep
ordinario (solo nos interesa el estado de salida).
Tenga en cuenta que no ponemos el pgrep
comando dentro de [ ... ]
. Eso es porque no estamos interesados en su salida, solo en su estado de salida. Con [ ... ]
comúnmente compara cadenas o números. El [ ... ]
dará como resultado un estado de salida que es cero (verdadero) o distinto de cero (falso), al igual que el pgrep
ejecución.
Sin embargo, esto no verifica ningún mecanismo de bloqueo, solo si un proceso en particular se está ejecutando o no.
Si está tratando de ejecutar solo una instancia de un script, entonces es mejor hacer algo como esto (suponiendo que EXIT
trap se ejecuta cada vez que el script finaliza ordenadamente):
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 varios intentos y dormir:
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
Relacionado:
- ¿Cómo asegurarse de que solo se ejecute una instancia de un script bash?