Wie führe ich ein Skript aus, wenn sich deine lokale IP ändert?

15

Vor dem Markieren als Duplikat: Hier geht es nicht um dynamisches DNS oder ähnliches.

Ich kann jedes Mal ein Skript ausführen, wenn mein Netzwerk hochfährt. Es ist ganz einfach, ein Skript in das Verzeichnis /etc/NetworkManager/dispatcher.dwie dieses einzufügen:

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

In meinem Fall myscriptist es sehr einfach ifconfig -a > ~/Dropbox/myifconfig.txt- ich benutze es, weil ich meine lokale IP von überall in der Universität kennen muss, und es wird sich oft ändern.

Soweit so gut, das System funktioniert einwandfrei. Aber leider ist das DHCP hier so konfiguriert, dass die IP irgendwann ohne ein Down / Up der Schnittstelle geändert wird. In diesem Fall wird das Skript (logisch) nicht ausgeführt und die Datei wird nicht aktualisiert.

Ich kann keinen DynDNS-Ansatz verwenden, da sich die Änderung auf die lokale IP bezieht und nicht auf die extern sichtbare.

Ich könnte abfragen, indem ich einfach das Skript in cron lege und es jede Minute ausführe oder ein etwas komplexeres schreibe (... wenn die IP geändert wird, schreibe die Datei sonst nichts) und es erneut als Hintergrundaufgabe ablege, aber es ist nicht elegant. Die Frage ist also:

Gibt es eine Möglichkeit, ein Skript auszulösen, wenn sich meine lokale IP ändert?

UPDATE 1

Ich habe versucht, ein Skript /etc/dhcp/dhclient-enter-hooks.d/basierend auf dem vorhandenen einzufügen /etc/dhcp/dhclient-enter-hooks.d/resolvconf, aber es wird nicht ausgelöst. Ich vermute (Bestätigung erforderlich), dass NM (Netzwerkmanager) die DHCP-Aushandlung selbst durchführt, ohne den DHCP-Befehl aufzurufen ...

Rmano
quelle
1
es sieht so aus, als ob es über ein Skript möglich sein solltedhclient-enter-hooks.d ... aber ich habe es nie ausprobiert! Das vorhandene /etc/dhcp/dhclient-enter-hooks.d/resolvconfSkript könnte in Bezug auf die Syntax und die zu "$reason" == "BOUND"
suchenden
@steeldriver Es scheint, dass das Skript nicht ausgelöst wird. Ich vermute, dass NM sich um das DHCP-Handling kümmert ... wird sich umsehen. Danke trotzdem.
Rmano

Antworten:

10

Laut der Manpage für NetmorkManager ist eines der Ereignisse

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

Ich denke du kannst dich einfach ändern

up) 

zu

dhcp4-change|up)
Jeffery Williams
quelle
Es funktioniert. Das Skript wird sogar ein bisschen zu viel ausgelöst; Sogar eine Erneuerung ohne Änderung der IP wird sie auslösen. Ich stelle mir vor, ich muss ein bisschen mehr Bash-Scripting machen. Moral: Lies den gesamten Inhalt der Manpage!
Rmano
Wartet ein bisschen (man weiß es nie ...) und weist dann das Kopfgeld zu. Vielen Dank!
Rmano
nach meiner erfahrung am 14.04 kann ich auf diese weise immer nur ereignisse für auf und ab empfangen. Die anderen Ereignisse lösen in update.d
init_js
4

Ich stelle ein Skript zur Verfügung, das dbus-Signale abhört, sodass Sie schneller reagieren können, als wenn Sie nach Änderungen an Ihrer aktuellen Netzwerkkonfiguration suchen würden. Es hilft auf Systemen, auf denen Skripte / etc / nicht ausgeführt werden, wenn Sie dies möchten (wie auf meinem 14.04-System).

Meine Ein- / Ausstiegshaken funktionieren nicht

NetworkManager startet dhclient mit dem Flag, -sf /usr/lib/NetworkManager/nm-dhcp-client.actiondas das normale Ein- / Ausstiegsverhalten zu überschreiben scheint. Das Standardverhalten mit dhclient ist das Aufrufen von Skripten /etc/dhcp/dhclient-{enter,exit}-hooks.d. Diese werden auf meinem System überhaupt nicht aufgerufen.

Auch meine NetworkManager-Skripte "dispatcher.d" funktionieren nicht

NM ruft jedoch einen anderen Satz von Skripten auf /etc/NetworkManager/dispatcher.d, um über verschiedene Ereignisse zu informieren. Der Networkmanager (8) man - Seite definiert dhcp4-changeund dhcp6-changeAktionen , die genau das zu tun scheint , was Sie wollen. Trotz allem , was zumindest die Manpage sagt, auf meinem System, nur upund downbekommen Aktionen aufgerufen. Ich kann diese Skripte nicht dazu bringen, auf irgendetwas anderes zu schießen. Daher ist dies auch kein guter Weg, um IP-Änderungen zu überwachen.

Schnüffeln Sie also direkt auf den von NM ausgegebenen D-Bus-Signalen

nm-dhcp-client.action( source ) konvertiert von der Befehlszeile aus einfach alle Umgebungsvariablen, die von dhclient festgelegt wurden, in ein dbus-Signal. Diese Umgebungsvariablen sind in man dhclient-script(8) definiert. Eines von besonderem Interesse ist $new_ip_address. Wie von @Bernhard vorgeschlagen, können Sie das Signal überwachen und auf der Grundlage seines Inhalts entsprechend handeln.

Hier ist ein Programm, das alle von dieser Binärdatei signalisierten Ereignisdaten aufspürt:

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

Die Ausgabe von dbus-monitor ist nicht einfach in Skripten zu analysieren. Vielleicht ist es einfacher, das Vorhandensein eines bestimmten Schlüsselworts auszulösen, z. B. new_ip_address, und von dort aus verschiedene Tools zu verwenden, um die geänderten Informationen abzurufen (z. B. ip oder 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"
)
...

Versuch es einmal!

init_js
quelle
Danke vielmals! Zum Glück (für mich) bin ich wieder zu Hause, wo ich meinen DHCP-Server steuern kann ... aber ich werde es versuchen, denn das Erlernen von DBus ist eine der Aufgaben in meiner Warteschlange, und Ihre ist ein wunderbarer Anfang.
Rmano
3

Polling-Ansatz mit Python-Skript. Die Grundidee besteht darin, die Ausgabe des ip -4 -o add show <INTERFACE>aktuellen Ergebnisses kontinuierlich zu analysieren und mit der vorherigen Iteration zu vergleichen

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

Obwohl NetworkManager dhclient verwendet, stellt es seine eigenen Binärdateien als Ersatz für die dhclient-Skripte bereit. (Als Referenz: Sie finden die NM-Binärdatei unter /usr/lib/NetworkManager/nm-dhcp-client.action).

Vielleicht könnten Sie einen anderen Ansatz wählen: NM gibt bei allen Ereignissen ein DBus-Signal aus. Sie könnten auf dem System-DBus nach dem passenden Ereignis suchen und Ihr Skript auf dieser Basis auslösen ...

Bernhard
quelle