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?