bash - comparators - ¿Cómo hacer "si no es verdadera condición"?
operators bash linux (5)
¿Qué estoy haciendo mal?
$(...)
mantiene el valor , no el estado de salida, por eso este enfoque es incorrecto. Sin embargo, en este caso específico, sí funciona porque se imprimirá sysa
, lo que hace que la declaración de prueba se haga realidad. Sin embargo, if ! [ $(true) ]; then echo false; fi
if ! [ $(true) ]; then echo false; fi
if ! [ $(true) ]; then echo false; fi
siempre se imprimiría false
porque el comando true
no escribe nada en la salida estándar (aunque el código de salida es 0). Es por eso que necesita ser reformulado a if ! grep ...; then
if ! grep ...; then
if ! grep ...; then
Una alternativa sería cat /etc/passwd | grep "sysa" || echo error
cat /etc/passwd | grep "sysa" || echo error
cat /etc/passwd | grep "sysa" || echo error
. Edición: Como señaló Alex, el gato es inútil aquí : grep "sysa" /etc/passwd || echo error
grep "sysa" /etc/passwd || echo error
.
Encontró las otras respuestas bastante confusas, espero que esto ayude a alguien.
Me gustaría tener el comando echo
ejecutado cuando cat /etc/passwd | grep "sysa"
cat /etc/passwd | grep "sysa"
no es cierto.
¿Qué estoy haciendo mal?
if ! [ $(cat /etc/passwd | grep "sysa") ]; then
echo "ERROR - The user sysa could not be looked up"
exit 2
fi
Creo que se puede simplificar en:
grep sysa /etc/passwd || {
echo "ERROR - The user sysa could not be looked up"
exit 2
}
o en una sola línea de comando
$ grep sysa /etc/passwd || { echo "ERROR - The user sysa could not be looked up"; exit 2; }
En los sistemas Unix que lo soportan (no macOS parece):
if getent passwd "$username" >/dev/null; then
printf ''User %s exists/n'' "$username"
else
printf ''User %s does not exist/n'' "$username"
fi
Esto tiene la ventaja de que consultará cualquier servicio de directorio que esté en uso (YP / NIS o LDAP, etc.) y el archivo de la base de datos de contraseñas local.
El problema con grep -q "$username" /etc/passwd
es que dará un falso positivo cuando no exista dicho usuario, pero otra cosa coincide con el patrón. Esto podría suceder si hay una coincidencia parcial o exacta en algún otro lugar del archivo.
Por ejemplo, en mi archivo de passwd
, hay una línea que dice
build:*:21:21:base and xenocara build:/var/empty:/bin/ksh
Esto provocaría una coincidencia válida en cosas como cara
y enoc
, etc., aunque no haya tales usuarios en mi sistema.
Para que una solución grep
sea correcta, deberá analizar correctamente el /etc/passwd
:
if cut -d '':'' -f 1 /etc/passwd | grep -qxF "$username"; then
# found
else
# not found
fi
... o cualquier otra prueba similar contra el primero de los campos :
delimitados.
tratar
if ! grep -q sysa /etc/passwd ; then
grep
devuelve true
si encuentra el objetivo de búsqueda, y false
si no lo encuentra.
Entonces NO es false
== true
.
if
evaluación en shells está diseñada para ser muy flexible, y muchas veces no requiere cadenas de comandos (como ha escrito).
Además, mirando su código tal como está, su uso de la forma $( ... )
de la sustitución cmd debe ser elogiado, pero piense en lo que está saliendo del proceso. Prueba echo $(cat /etc/passwd | grep "sysa")
para ver a qué me refiero. Puedes llevar esto más lejos usando la opción -c
(contar) para grep y luego haz if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then
if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then
if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then
que funciona pero es más bien de la vieja escuela.
PERO, podría usar las funciones de shell más recientes (evaluación aritmética) como
if ! (( $(grep -c "sysa" /etc/passwd) == 0 )) ; then ...`
que también le brinda la ventaja de utilizar los operadores de comparación basados en c-lang, ==,<,>,>=,<=,%
y quizás algunos otros.
En este caso, según un comentario de Orwellophile, la evaluación aritmética puede reducirse aún más, como
if ! (( $(grep -c "sysa" /etc/passwd) )) ; then ....
O
if (( ! $(grep -c "sysa" /etc/passwd) )) ; then ....
Finalmente, hay un premio llamado Useless Use of Cat (UUOC)
. :-) Algunas personas saltan de arriba a abajo y lloran gothca! Solo diré que grep
puede tomar un nombre de archivo en su línea cmd, entonces ¿por qué invocar procesos adicionales y construcciones de tuberías cuando no es necesario? ;-)
Espero que esto ayude.
Aquí hay una respuesta a modo de ejemplo:
Para asegurarse de que los registradores de datos estén en línea, se ejecuta un script cron
cada 15 minutos que tiene este aspecto:
#!/bin/bash
#
if ! ping -c 1 SOLAR &>/dev/null
then
echo "SUBJECT: SOLAR is not responding to ping" | ssmtp [email protected]
echo "SOLAR is not responding to ping" | ssmtp [email protected]
else
echo "SOLAR is up"
fi
#
if ! ping -c 1 OUTSIDE &>/dev/null
then
echo "SUBJECT: OUTSIDE is not responding to ping" | ssmtp [email protected]
echo "OUTSIDE is not responding to ping" | ssmtp [email protected]
else
echo "OUTSIDE is up"
fi
#
... y así sucesivamente para cada registrador de datos que puede ver en el montaje en http://www.SDsolarBlog.com/montage
Para su información, utilizando &>/dev/null
redirige toda la salida del comando, incluidos los errores, a /dev/null
(El condicional solo requiere el exit status
de exit status
del comando ping
)
También para su información, tenga en cuenta que, dado que los trabajos cron
ejecutan como root
no es necesario utilizar sudo ping
en un script cron
.