Comment exécuter un script en cas de changement de votre IP locale?

15

Avant de marquer comme doublon: il ne s'agit pas de DNS dynamique ou de choses similaires.

Je sais comment exécuter un script chaque fois que mes réseaux montent; il s'agit simplement d'ajouter un script dans le répertoire /etc/NetworkManager/dispatcher.dcomme celui-ci:

#!/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

Dans mon cas, myscriptc'est très simple ifconfig -a > ~/Dropbox/myifconfig.txt--- je l'utilise parce que j'ai besoin de connaître mon adresse IP locale de partout dans l'Université, et cela changera souvent.

Jusqu'ici tout va bien, le système fonctionne bien. Mais malheureusement, le DHCP ici est configuré de telle sorte que l'IP soit parfois modifiée sans interruption / montée de l'interface. Dans ce cas, le script n'est (logiquement) pas exécuté et le fichier n'est pas mis à jour.

Je ne peux pas utiliser une approche DynDNS car le changement est dans l' IP local , pas celui visible de l'extérieur.

Je pourrais interroger, en mettant simplement le script dans cron et en l'exécutant toutes les minutes ou en écrivant un légèrement plus complexe (... si l'IP est changé, écrivez le fichier sinon ne faites rien) et en le mettant à nouveau en tâche de fond, mais il n'est pas élégant. La question est donc:

Existe-t-il un moyen de déclencher un script lorsque mon adresse IP locale change?

MISE À JOUR 1

J'ai essayé de mettre un script /etc/dhcp/dhclient-enter-hooks.d/, basé sur l'existant /etc/dhcp/dhclient-enter-hooks.d/resolvconf, mais il ne sera pas déclenché. Je soupçonne (confirmation nécessaire) que NM (gestionnaire de réseau) fait lui-même la négociation dhcp, sans appeler la commande dhcp ...

Rmano
la source
1
il semble que cela devrait être possible via un dhclient-enter-hooks.dscript ... mais je ne l'ai jamais essayé! Le /etc/dhcp/dhclient-enter-hooks.d/resolvconfscript existant pourrait être utile en termes de syntaxe et quels signaux rechercher ( "$reason" == "BOUND"peut-être?)
Steeldriver
@steeldriver il semble que le script ne soit pas déclenché. Je soupçonne que NM s'occupe de la gestion DHCP ... va regarder autour de lui. Merci quand même.
Rmano

Réponses:

10

Selon la page de manuel de NetmorkManager, l'un des événements est

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

Je pense que vous pouvez simplement changer

up) 

à

dhcp4-change|up)
Jeffery Williams
la source
Cela (en quelque sorte) fonctionne. Le script est déclenché même un peu trop; même un renouvellement sans changement d'IP le déclenchera. J'imagine que je vais devoir faire un peu plus de script bash. Moral: lisez tout le contenu de la page de manuel!
Rmano
Attendra un peu (on ne sait jamais ...) puis attribuera la prime. Merci!
Rmano
d'après mon expérience le 14.04, je ne peux que recevoir des événements de haut en bas de cette façon. les autres événements ne déclenchent jamais de scripts dans update.d
init_js
4

Je fournis un script qui écoute les signaux dbus, ce qui vous permettra de réagir plus rapidement que si vous interrogiez les changements sur votre configuration réseau actuelle. Cela aide sur les systèmes où les scripts / etc / ne sont pas exécutés quand vous le souhaitez (comme sur mon système 14.04).

mon entrée / sortie hooks.d ne fonctionne pas

NetworkManager démarre dhclient avec l'indicateur -sf /usr/lib/NetworkManager/nm-dhcp-client.actionqui semble remplacer le comportement normal du hook d'entrée / sortie. Le comportement par défaut avec dhclient est d'appeler des scripts /etc/dhcp/dhclient-{enter,exit}-hooks.d. Ceux-ci ne sont pas du tout appelés sur mon système.

mes scripts NetworkManager dispatcher.d ne fonctionnent pas non plus

NM invoque cependant un ensemble différent de scripts, dans /etc/NetworkManager/dispatcher.d, pour informer de divers événements. La page définit l'homme NetworkManager (8) dhcp4-changeet les dhcp6-changeactions qui semblent faire exactement ce que vous voulez. En dépit de ce que dit la page de manuel, sur mon système au moins, seulement upet les downactions s'invoquées. Je ne peux pas faire tirer ces scripts sur autre chose. Ce n'est donc pas non plus une excellente avenue pour surveiller les changements IP.

donc, snoop directement sur les signaux dbus émis par NM

nm-dhcp-client.action( source ), à partir de la ligne de commande, convertit simplement toutes les variables d'environnement définies par dhclient en un signal dbus. Ces variables d'environnement sont définies dans man dhclient-script(8). Un intérêt particulier est $new_ip_address. Ce que vous pourriez faire, comme suggéré par @Bernhard, est de surveiller le signal et d'agir en fonction de son contenu.

Voici un programme qui espionne toutes les données d'événement signalées par ce binaire:

#!/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 sortie de dbus-monitor n'est pas simple à analyser dans les scripts. Il est peut-être plus facile de déclencher la présence d'un certain mot-clé (s), par exemple new_ip_address, et à partir de là, utiliser différents outils pour obtenir les informations qui ont changé (par exemple ip ou 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"
)
...

Donner un coup de feu!

init_js
la source
Merci beaucoup! Heureusement (pour moi), je suis de retour à la maison où je peux contrôler mon serveur DHCP ... mais je vais lui donner un coup de feu parce que l'apprentissage de DBus est l'une des choses dans ma file d'attente, et la vôtre est un merveilleux début.
Rmano
3

Approche d'interrogation avec script python. L'idée de base est d'analyser en continu la sortie ip -4 -o add show <INTERFACE>et de comparer le résultat actuel avec l'itération précédente

#!/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
la source
1

Bien que NetworkManager utilise dhclient, il fournit ses propres fichiers binaires en remplacement des scripts dhclient. (Pour référence: vous pouvez trouver le binaire NM à /usr/lib/NetworkManager/nm-dhcp-client.action).

Vous pourriez peut-être adopter une approche différente: NM émet un signal DBus sur tous les événements. Vous pouvez écouter sur le système DBus l'événement approprié et déclencher votre script en fonction de cela ...

Bernhard
la source