.png)
¿Cómo puedo canalizar comandos y, dentro del script, decidir si se debe romper la tubería o no?
Es similar aesta pregunta. Pero en lugar de eso, awk
me gustaría usar mi propio script:
check_ip | update_bind9
check_ip
Debe encontrar la IP externa ( curl -s ifconfig.co
) y compararla con la IP almacenada en un archivo ( ~/.ip
).
Aquí está la pregunta principal:
Si la IP ha cambiado, check_ip
debe pasar la IP a través de la tubería. Si no, debería romper la tubería.
¿ check_ip
Eso rompe la tubería o update_bind9
ignora la llamada si no se llama con la IP?
Hice algunas pruebas, llamando: check_ip | echo "ok"
.
Lo intenté exit 0
, exit 1
, return true
, return false
. Lo intenté set -e
. Sin éxito.
Respuesta1
Todos los componentes de una tubería.comenzar simultáneamente– el segundo comando siempre se iniciará sin importar lo que suceda en el primer comando.
Entonces es el segundo comando el que necesita manejar la entrada estándar vacía.
Pero yo diría que las pipas no son una buena opción para esto en primer lugar.
(¿Quizás estás confundiendo |
(tubería) con ||
(booleano OR)? Este últimoesfrecuentemente se usa como una alternativa más corta a si/entonces, por ejemplo, x || y
solo llamará a y cuando x falle – y de manera similar, x && y
solo llamará a y cuando x tenga éxito.)
En general, deberías utilizar un bloque si/entonces. Por ejemplo, si check_ip
devuelve 0 (éxito) cuando las direcciones son diferentes pero 1 (fracaso) cuando son iguales, se vería así:
if addr=$(check_ip); then
echo "$addr" | update_bind9
fi
Alternativamente, si update_bind9 puede determinar la dirección por sí solo (sin leer la entrada estándar), sería así:
if check_ip_needs_updating; then
update_bind9
fi
Respuesta2
esta otra respuestaes bueno. Sin embargo, si realmente necesita canalizar de forma condicional, es posible que encuentreifne
útil:
ifne
ejecuta el siguiente comando si y solo si la entrada estándar no está vacía.
En tu caso será como check_ip | ifne update_bind9
.
Lo más probable ifne
es que no esté instalado en su Linux de forma predeterminada. En mi Debian 10 está en el moreutils
paquete. Uno puede pensar que una herramienta adicional es totalmente excesiva, ya que podemos almacenar la salida de check_ip
en una variable y reutilizarla condicionalmente, como en la respuesta mencionada:
if addr=$(check_ip); then echo "$addr" | update_bind9 fi
La condición puede ser [ -n "$addr" ]
cualquiera; Lo importante es que usamos una variable. Un código como el anterior puede resolver su problema, pero en general presenta al menos tres problemas. Supongamos command1 | command2
en lugar de check_ip | update_bind9
. La solución se generaliza a:
if foo=$(command1); then
echo "$foo" | command2
fi
Y luego:
foo=$(command1)
eliminará todas las nuevas líneas finales de la salida decommand1
. Entoncesecho "$foo"
(oprintf … "$foo"
) agregará exactamente un carácter de nueva línea (o un número fijo de ellos, respectivamente). Por este motivo,command2
es posible que no obtenga el resultado exacto decommand1
.command1
puede producir una salida que contenga caracteres NUL. Bash no puede almacenar NUL en una variable (la mayoría de los shells no pueden; zsh sí). Si aparece NUL,command2
no obtendrá el resultado exacto decommand1
.command1
puede producir un flujo enorme o incluso interminable, por lo que puede que no sea posible almacenarlo en una variable.
Usar un archivo en lugar de la variable resuelve todos los problemas excepto el último. command1 | ifne command2
es inmune a los tres problemas.