esperando la red en un script bash


9

Estoy ejecutando un script que depende de que la red esté activa y se monte un recurso compartido de red. El script se ejecuta al iniciar sesión (lo que ocurre automáticamente después del arranque). El problema es que para cuando se ejecuta el script, por lo general todavía no tengo una dirección IP (DHCP). Por el momento, solo duermo el script durante 15 segundos, pero no me gusta este enfoque en absoluto, ya que quiero poder decirle al usuario si algo está mal.

Mi plan es un bucle mientras aún no tengo una dirección IP y continuar cuando lo tenga. Crucialmente, tiene que expirar después de un tiempo. Lo que se me ocurrió es hacerlo, if [ ifconfig | grep "192.168.100" ];pero lo que sucede es que grepconsume el ];y no le gusta. Entonces bash también se molesta, porque no puede encontrar ];qué grep comió. Y luego ni siquiera he implementado el tiempo de espera.

Alguien sugirió mantener una variable y dormir, por ejemplo, un segundo en cada iteración y aumentar esta variable cada vez. Aquí está mi script completo (que no funciona) (soy bastante nuevo en bash scripting):

x=0
while [ ifconfig | grep "192.168.100." > /dev/null ]; do
    echo "no nework"
    if "$x" -gt 200; then
        #Time out here
        exit 1
    x=$((x+1))
    sleep .1
    fi
done

#continue with rest of script...

¡Cualquier indicador en la dirección correcta sería muy apreciado!


1
Si su init es systemd, escriba un archivo de servicio que espere network-online.target...
jasonwryan

no es necesario redirigir la grepsalida a /dev/null. Use la -qopción en su lugar. Y tampoco me molesta que ifconfig sea una buena idea. ¿Por qué no usar pingen su lugar?
prisa el

pingpuede fallar dependiendo de la red en cuestión. Es mejor simplemente verificar la configuración en ejecución del sistema.
Bratchley

Respuestas:


8

Sintaxis de Shell

Parece estar confundido con respecto a los condicionales en los scripts de shell. Cada comando de shell tiene un estado de salida, que es un número entero entre 0 y 255, donde 0 significa éxito y cualquier otro valor significa error. Las declaraciones como ify whileque esperan operandos booleanos inspeccionan el estado de salida del comando y tratan 0 (éxito) como verdadero y cualquier otro valor (falla) como falso.

Por ejemplo, el grepcomando devuelve 0 si se encuentra el patrón y 1 si no se encuentra el patrón. Entonces

while ifconfig | grep "192.168.100." > /dev/null; do 

repite el ciclo siempre que el patrón 192.168.100.se encuentre en la salida de ifconfig. Tenga en cuenta que el patrón 192.168.100.coincide con cadenas como 192x168 1007, porque .en una expresión regular coincide con cualquier carácter; para buscar una cadena literal, pase la opción -Fa grep. Para invertir la condición, poner !al frente.

while ! ifconfig | grep -F "192.168.100." > /dev/null; do 

Además en el script, desea comparar el valor de una variable con un número. Utiliza el -gtoperador, que es parte de la sintaxis de las expresiones condicionales entendidas por el testcomando. El testcomando devuelve 0 si la expresión condicional es verdadera y 1 si la expresión condicional es falsa.

if test "$x" -gt 200; then

Es costumbre usar el nombre alternativo [para el testcomando. Este nombre espera que el comando termine con el parámetro ]. Las dos formas de escribir este comando son exactamente equivalentes.

if [ "$x" -gt 200 ]; then

Bash también ofrece una tercera forma de escribir este comando, con la sintaxis especial [[ … ]]. Esta sintaxis especial puede admitir algunos operadores más que [, ya que [es un comando ordinario sujeto a las reglas de análisis habituales, mientras que [[ … ]]es parte de la sintaxis de shell.

Nuevamente, tenga en cuenta que [es para expresiones condicionales , que son una sintaxis con operadores como -n, -gt... [no significa "valor booleano": cualquier comando tiene un valor booleano (¿estado de salida = 0?).

Detectando que la red está activa

Su forma de detectar que la red está activa no es sólida. En particular, tenga en cuenta que su script se activará tan pronto como cualquier interfaz de red adquiera una dirección IP dentro del rango especificado. En particular, es muy posible que el DNS no esté activo en ese momento, y mucho menos cualquier recurso compartido de red montado.

¿Realmente necesita ejecutar estos comandos cuando alguien inicia sesión? Es más fácil hacer que un comando se ejecute automáticamente cuando se abre la red. La forma de hacerlo depende de su distribución y de si usa NetworkManager.

Si necesita ejecutar estos comandos como parte de los scripts de inicio de sesión, pruebe el recurso que realmente necesita, no la presencia de una dirección IP. Por ejemplo, si desea probar si /net/somenode/somedirestá montado, use

while ! grep -q /net/somenode/somedir </proc/mounts; do
  sleep 1
done

Si tienes advenedizo o systemd ...

entonces puedes usarlo. Por ejemplo, con Upstart , marque su trabajo como start on net-device-up eth0(reemplácelo eth0por el nombre de la interfaz que proporciona la conectividad de red deseada). Con Systemd, vea ¿ Causa que se ejecute un script después de que se haya iniciado la conexión en red?


Supongo que /net/debería ser /proc/net?
sebix

@sebix No, ¿por qué lo haría? No estoy hablando de la configuración de red de Linux. Estoy dando un ejemplo de un punto de montaje para un sistema de archivos remoto, /netes una ubicación común para dichos puntos de montaje.
Gilles 'SO- deja de ser malvado'

Ok, entonces necesitas una unidad de red montada. ¿Existe también una solución más genérica?
sebix

@sebix ¿Una solución para qué? Requerir una unidad de red montada fue un ejemplo de un objetivo, no un ejemplo de una solución.
Gilles 'SO- deja de ser malvado'

1

Solo cuente la salida de ip add showPor ejemplo:

root@xxxxxxlp01 ~ $ ip add sh dev eth3 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth1 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet
    inet xxx.xxx.64.91/24 brd xxx.xxx.95.255 scope global eth0
    inet6 fe80::224:e8ff:fe78:4dfb/64 scope link
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet | wc -l
2

Luego puede simplemente ramificarse en el número de línea devuelta según corresponda. Probablemente solo verifique si fue cero, y si es así, duerma y repita el ciclo.

Código no probado para ilustración:

while [ 1 ]; do

  if [ $(ip add sh dev eth0 | grep inet | wc -l) -ne 0 ]; then
     break
  fi

  sleep 1

done

1

Ping devolverá una respuesta 0 si al menos un intento fue exitoso. Puede considerar hacer ping al servidor al que se está conectando hasta que sea exitoso.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.