¿Cómo ejecutar un script cuando hay un cambio en su IP local?

15

Antes de marcar como duplicado: no se trata de DNS dinámico o cosas similares.

Sé cómo ejecutar un script cada vez que mi red sube; es una simple cuestión de agregar un script en el directorio /etc/NetworkManager/dispatcher.dcomo este:

#!/bin/bash

IF=$1
STATUS=$2

case "$2" in
        up)
        logger -s "NM Script up $IF triggered"
        su rmano -c /home/romano/bin/myscript 
        ;;
        down)
        logger -s "NM Script down $IF triggered"
        ;;
        *)
        ;;
esac

En mi caso, myscriptes muy simple: ifconfig -a > ~/Dropbox/myifconfig.txtlo uso porque necesito saber mi IP local de todas partes de la Universidad, y cambiará con frecuencia.

Hasta ahora todo bien, el sistema funciona bien. Pero desafortunadamente, el DHCP aquí está configurado para que la IP se cambie en algún momento sin una interfaz inactiva. En ese caso, el script no se ejecuta (lógicamente) y el archivo no se actualiza.

No puedo usar un enfoque DynDNS porque el cambio está en la IP local , no en la externamente visible.

Podría sondear, simplemente poniendo el script en cron y ejecutándolo cada minuto o escribiendo uno un poco más complejo (... si se cambia la IP, escriba el archivo, de lo contrario no haga nada) y vuelva a colocarlo como una tarea en segundo plano, pero No es elegante. Entonces la pregunta es:

¿Hay alguna forma de activar un script cuando cambia mi IP local?

ACTUALIZACIÓN 1

Traté de poner un script /etc/dhcp/dhclient-enter-hooks.d/, basado en el existente /etc/dhcp/dhclient-enter-hooks.d/resolvconf, pero no se activará. Sospecho (se necesita confirmación) que NM (administrador de red) está haciendo la negociación dhcp por sí mismo, sin llamar al comando dhcp ...

Rmano
fuente
1
parece que debería ser posible a través de un dhclient-enter-hooks.dscript ... ¡pero nunca lo he probado! El /etc/dhcp/dhclient-enter-hooks.d/resolvconfscript existente podría ser útil en términos de sintaxis y qué señales buscar ( "$reason" == "BOUND"¿tal vez?)
steeldriver
@steeldriver parece que el script no se activa. Sospecho que NM se encarga del manejo de DHCP ... mirará a su alrededor. Gracias de cualquier manera.
Rmano

Respuestas:

10

Según la página de manual de NetmorkManager, uno de los eventos es

dhcp4-change
          The DHCPv4 lease has changed (renewed, rebound, etc).

Creo que simplemente puedes cambiar

up) 

a

dhcp4-change|up)
Jeffery Williams
fuente
Funciona (más o menos). La secuencia de comandos se activa incluso un poco demasiado; incluso una renovación sin cambios en IP lo activará. Me imagino que tendré que hacer un poco más de secuencias de comandos bash. Moraleja: ¡lea todo el contenido de la página de manual!
Rmano
Esperará un poco (nunca se sabe ...) y luego asignará la recompensa. ¡Gracias!
Rmano
en mi experiencia el 14.04, solo puedo recibir eventos de arriba a abajo de esa manera. los otros eventos nunca activan scripts en update.d
init_js
4

Proporciono un script que escucha las señales dbus, lo que le permitirá reaccionar más rápido que si tuviera que sondear los cambios en la configuración actual de su red. Ayuda en los sistemas donde los scripts / etc / no se ejecutan cuando lo desea (como en mi sistema 14.04).

mis ganchos de entrada / salida.d no funcionan

NetworkManager inicia dhclient con el indicador -sf /usr/lib/NetworkManager/nm-dhcp-client.actionque parece anular el comportamiento normal de enlace de entrada / salida. El comportamiento predeterminado con dhclient es llamar a los scripts /etc/dhcp/dhclient-{enter,exit}-hooks.d. Esos no reciben ninguna llamada en mi sistema.

mis scripts de NetworkManager dispatcher.d tampoco funcionan

Sin embargo, NM invoca un conjunto diferente de scripts, en /etc/NetworkManager/dispatcher.d, para informar sobre varios eventos. La página del comando man NetworkManager (8) define dhcp4-changey dhcp6-changeacciones que parecen hacer exactamente lo que usted desea. A pesar de lo que dice la página de manual, en mi sistema al menos, solo upy las downacciones se invocan. No puedo hacer que esos guiones disparen sobre otra cosa. Por lo tanto, esta tampoco es una gran vía para monitorear los cambios de IP.

entonces, espíe directamente sobre las señales dbus emitidas por NM

nm-dhcp-client.action( fuente ), desde la línea de comandos, simplemente convierte todas las variables de entorno establecidas por dhclient en una señal dbus. Esas variables de entorno se definen en man dhclient-script(8). Uno de particular interés es $new_ip_address. Lo que podría hacer, como lo sugiere @Bernhard, es monitorear la señal y actuar en consecuencia según su contenido.

Aquí hay un programa que analizará todos los datos de eventos señalados por ese binario:

#!/bin/bash -e

#
# This script listens for the org.freedesktop.nm_dhcp_client signal.
# The signal is emitted every time dhclient-script would execute.
# It has the same contents as the environment passed to
# dhclient-script (8). Refer to manpage for variables of interest.
#

# "org.freedesktop.nm_dhcp_client" is an undocumented signal name,
# as far as I could tell. it is emitted by nm-dhcp-client.action,
# which is from the NetworkManager package source code.
# 

# detail: todo cleanup subprocess on exit. if the parent exits, 
#       the subprocess will linger until it tries to print
#       at which point it will get SIGPIPE and clean itself.
#       trap on bash's EXIT signal to do proper cleanup.


mkfifo /tmp/monitor-nm-change

(
    dbus-monitor --system "type='signal',interface='org.freedesktop.nm_dhcp_client'"
) > /tmp/monitor-nm-change &

exec </tmp/monitor-nm-change
rm /tmp/monitor-nm-change

while read EVENT; do
    #change this condition to the event you're interested in
    if echo "$EVENT" | grep -q BOUND6; then
        # do something interesting
        echo "current ipv6 addresses:"
        ip addr show | grep inet6
    fi
done

La salida de dbus-monitor no es fácil de analizar en scripts. Quizás sea más fácil disparar ante la presencia de una determinada palabra (s) clave, por ejemplo new_ip_address, y desde allí utilizar diferentes herramientas para obtener la información que cambió (por ejemplo, ip o ifconfig).

# example output data from dbus-monitor for that signal
...
dict entry(
string "new_routers"
variant             array of bytes "192.168.2.11"
)
dict entry(
string "new_subnet_mask"
variant             array of bytes "255.255.255.0"
)
dict entry(
string "new_network_number"
variant             array of bytes "192.168.2.0"
)
dict entry(
string "new_ip_address"
variant             array of bytes "192.168.2.4"
)
dict entry(
string "pid"
variant             array of bytes "12114"
)
dict entry(
string "reason"
variant             array of bytes "REBOOT"
)
dict entry(
string "interface"
variant             array of bytes "eth0"
)
...

¡Dale un tiro!

init_js
fuente
¡Muchas gracias! Afortunadamente (para mí), estoy de vuelta en casa, donde puedo controlar mi servidor DHCP ... pero lo intentaré porque aprender sobre DBus es una de las cosas en mi lista, y el tuyo es un comienzo maravilloso.
Rmano
3

Enfoque de sondeo con script de python. La idea básica es analizar continuamente la salida ip -4 -o add show <INTERFACE>y comparar el resultado actual con la iteración anterior

#!/usr/bin/env python3
import subprocess
import sys

def get_ip():
    # Simple function that parses output
    # of ip command and returns interface ip
    # replace wlan7 with your interface
    command = 'ip -4 -o addr show wlan7'.split()
    ip = None
    try:
        ip = subprocess.check_output(command).decode().split()[3]
    except IndexError:
        return
    finally:
        if ip:
           return ip

def main():
    # do while loop
    # Exits only when change occurs
    address = get_ip()
    while address == get_ip():
          address = get_ip()

    # Trigger script once we're out of loop
    subprocess.call(['zenity','--info','--text','IP CHANGED'])


if __name__ == '__main__':
    # use while loop if yout want this script to run
    # continuously
    while True:
        try:
            main()
        except KeyboardInterrupt:
            sys.exit()
Sergiy Kolodyazhnyy
fuente
1

Aunque NetworkManager está utilizando dhclient, proporciona sus propios binarios como reemplazo de los scripts dhclient. (Para referencia: puede encontrar el binario NM en/usr/lib/NetworkManager/nm-dhcp-client.action ).

Tal vez podría adoptar un enfoque diferente: NM está emitiendo una señal DBus en todos los eventos. Puede escuchar en el sistema DBus el evento apropiado y activar su script en base a esto ...

Bernhard
fuente