Un operador "y" para una declaración "if" en Bash
Estoy intentando crear un script Bash simple para verificar si el sitio web no funciona y por alguna razón el operador "y" no funciona:
#!/usr/bin/env bash
WEBSITE=domain.example
SUBJECT="$WEBSITE DOWN!"
EMAILID="[email protected]"
STATUS=$(curl -sI $WEBSITE | awk '/HTTP\/1.1/ { print $2 }')
STRING=$(curl -s $WEBSITE | grep -o "string_to_search")
VALUE="string_to_search"
if [ $STATUS -ne 200 ] && [[ "$STRING" != "$VALUE" ]]; then
echo "Website: $WEBSITE is down, status code: '$STATUS' - $(date)" | mail -s "$SUBJECT" $EMAILID
fi
El operador "-a" tampoco funciona:
if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]
¿Podría también indicarnos cuándo utilizarlo?
- corchetes simples y dobles
- paréntesis
?
Si $STATUS
se expande a la cadena vacía, entonces
if [ $STATUS -ne 200 ]
no es válido porque es equivalente a
if [ -ne 200 ]
, lo que debería generar un error similar a "-ne: se espera un operador unario".
El comando
if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]];
no es válido independientemente de la expansión de $STATUS
porque está pasando [[
y ]]
como argumentos del [
comando, pero [
requiere que su último argumento sea la cadena literal ]
. Probablemente sería mejor hacer:
if ! [ "${STATUS}" -eq 200 ] 2> /dev/null && [ "${STRING}" != "${VALUE}" ]; then ...
o
if [ "${STATUS}" != 200 ] && [ "${STRING}" != "${VALUE}" ]; then ...
En cada uno de estos, ]
está el argumento final para la invocación de [
, según sea necesario. El shell analiza &&
y ;
como tokens que finalizan el [
comando, pero cadenas como -a
, [[
y ]]
son solo cadenas que el shell pasa al comando. (En el primer caso, el shell lo trata 2> /dev/null
como un operador de redirección, por lo que esas cadenas no se pasan [
como argumentos). Tenga en cuenta que utilizar -a
como argumento to como AND[
booleano se considera una mala práctica y debe evitarse.
[
y [[
son muy diferentes, pero la única diferencia entre [
y test
es que [
requiere que su argumento final sea ]
y test
no lo es. (Algunos argumentarán que otra diferencia es que [
es una función incorporada pero test
no lo es, y aunque puede haber habido un momento en el pasado distante en el que algunos shells tenían [
como función incorporada while test
siempre era una invocación de /bin/test
, probablemente ese no haya sido el caso en cualquier caparazón común durante décadas). Otra solución razonable es:
if test "${STATUS}" != 200 && test "${STRING}" != "${VALUE}"; then ...
Opinión personal: nunca utilizar [[
. Suprime mensajes de error importantes y no es portátil a diferentes shells. Además, como se ve por la existencia de esta pregunta, es confusa. Se puede argumentar que la confusión aquí es causada por la gramática del shell y el oscuro comportamiento de [
, y estoy de acuerdo. [
También es confuso. Puedes evitar mucha confusión si evitas ambos [[
y [
y siempre usas test
.
Prueba esto:
if [ "${STATUS}" -ne 100 -a "${STRING}" = "${VALUE}" ]
o
if [ "${STATUS}" -ne 100 ] && [ "${STRING}" = "${VALUE}" ]