Bagaimana cara menjalankan skrip ketika ada perubahan pada IP lokal Anda?

15

Sebelum menandai sebagai duplikat: ini bukan tentang DNS dinamis atau hal serupa.

Saya tahu cara menjalankan skrip setiap kali jaringan saya naik; ini adalah masalah sederhana untuk menambahkan skrip di direktori/etc/NetworkManager/dispatcher.d seperti ini:

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

Dalam kasus saya, myscript sangat sederhana ifconfig -a > ~/Dropbox/myifconfig.txt--- saya menggunakannya karena saya perlu mengetahui IP lokal saya dari mana saja di Universitas, dan itu akan sering berubah.

Sejauh ini bagus, sistemnya bekerja ok. Namun sayangnya DHCP di sini dikonfigurasi sehingga IP kadang-kadang berubah tanpa turun / naik dari antarmuka. Dalam hal ini skrip (secara logis) tidak berjalan, dan file tidak diperbarui.

Saya tidak bisa menggunakan pendekatan DynDNS karena perubahan ada di IP lokal , bukan yang terlihat secara eksternal.

Saya bisa polling, dengan hanya meletakkan script di cron dan menjalankannya setiap menit atau menulis yang sedikit lebih kompleks (... jika IP diubah tulis file jika tidak melakukan apa-apa) dan meletakkannya lagi sebagai tugas latar belakang, tetapi tidak elegan. Jadi pertanyaannya adalah:

Apakah ada cara untuk memicu skrip ketika IP lokal saya berubah?

PEMBARUAN 1

Saya mencoba memasukkan skrip /etc/dhcp/dhclient-enter-hooks.d/, berdasarkan yang ada /etc/dhcp/dhclient-enter-hooks.d/resolvconf, tetapi tidak akan dipicu. Saya curiga (konfirmasi diperlukan) bahwa NM (manajer jaringan) sedang melakukan negosiasi dhcp dengan sendirinya, tanpa memanggil perintah dhcp ...

Rmano
sumber
1
sepertinya itu harus dimungkinkan melalui dhclient-enter-hooks.dskrip ... tapi saya belum pernah mencobanya! /etc/dhcp/dhclient-enter-hooks.d/resolvconfSkrip yang ada mungkin membantu dalam hal sintaks dan sinyal apa yang harus dicari ( "$reason" == "BOUND"mungkin?)
steeldriver
@steeldriver tampaknya skrip tidak terpicu. Saya curiga NM menangani penanganan DHCP ... akan melihat-lihat. Bagaimanapun, terima kasih.
Rmano

Jawaban:

10

Menurut halaman manual untuk NetmorkManager, salah satu acara adalah

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

Saya pikir Anda bisa berubah

up) 

untuk

dhcp4-change|up)
Jeffery Williams
sumber
Ini (semacam) bekerja. Script dipicu bahkan agak terlalu banyak; bahkan pembaruan tanpa perubahan IP akan memicunya. Saya membayangkan saya harus melakukan sedikit bash scripting. Moral: baca semua konten halaman manual!
Rmano
Akan menunggu sedikit (Anda tidak pernah tahu ...) dan kemudian menetapkan hadiahnya. Terima kasih!
Rmano
dalam pengalaman saya pada 14,04, saya hanya bisa menerima acara untuk naik turun seperti itu. Peristiwa lain tidak pernah memicu skrip di update.d
init_js
4

Saya menyediakan skrip yang mendengarkan sinyal dbus, yang akan memungkinkan Anda untuk bereaksi lebih cepat daripada jika Anda melakukan polling untuk perubahan pada konfigurasi jaringan Anda saat ini. Ini membantu pada sistem di mana skrip / etc / tidak dieksekusi ketika Anda menginginkannya (seperti pada sistem 14.04 saya).

enter / exit hooks.d saya tidak berfungsi

NetworkManager mulai dhclient dengan flag -sf /usr/lib/NetworkManager/nm-dhcp-client.actionyang tampaknya mengesampingkan perilaku normal kait masuk / keluar. Perilaku default dengan dhclient adalah untuk memanggil skrip/etc/dhcp/dhclient-{enter,exit}-hooks.d . Itu tidak dipanggil sama sekali di sistem saya.

skrip NetworkManager dispatcher.d saya juga tidak berfungsi

Namun NM tidak meminta set script yang berbeda, di /etc/NetworkManager/dispatcher.d, untuk menginformasikan berbagai peristiwa. Halaman manual NetworkManager (8) mendefinisikan dhcp4-changedan dhcp6-changetindakan yang tampaknya melakukan apa yang Anda inginkan. Terlepas dari apa yang dikatakan halaman manual tersebut, setidaknya pada sistem saya, hanya saja updan downtindakan dapat dilakukan. Saya tidak bisa membuat skrip-skrip itu diaktifkan. Jadi ini bukan jalan yang bagus untuk memonitor perubahan IP.

jadi, mengintip langsung pada sinyal dbus yang dipancarkan oleh NM

nm-dhcp-client.action( sumber ), dari baris perintah, cukup mengkonversi semua variabel lingkungan yang ditetapkan oleh dhclient menjadi sinyal dbus. Variabel lingkungan tersebut didefinisikan dalam man dhclient-script(8). Salah satu yang menarik adalah$new_ip_address . Apa yang dapat Anda lakukan, seperti yang disarankan oleh @Bernhard, adalah memantau sinyal dan bertindak sesuai dengan isinya.

Berikut adalah program yang akan mengintip semua data acara yang ditandai oleh biner itu:

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

Output dbus-monitor tidak mudah untuk diuraikan dalam skrip. Mungkin lebih mudah untuk memicu keberadaan kata kunci tertentu, misalnya new_ip_address, dan dari sana menggunakan alat yang berbeda untuk mendapatkan informasi yang berubah (mis. Ip atau 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"
)
...

Cobalah!

init_js
sumber
Terima kasih banyak! Untungnya (bagi saya) saya kembali ke rumah di mana saya dapat mengontrol server DHCP saya ... tapi saya akan mencobanya karena mempelajari tentang DBus adalah salah satu hal dalam antrian saya, dan Anda adalah awal yang luar biasa.
Rmano
3

Pendekatan polling dengan skrip python. Ide dasarnya adalah untuk terus mengurai output ip -4 -o add show <INTERFACE>dan membandingkan hasil saat ini dengan iterasi sebelumnya

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

Meskipun NetworkManager menggunakan dhclient, ia menyediakan biner sendiri sebagai pengganti skrip dhclient. (Untuk referensi: Anda dapat menemukan biner NM di /usr/lib/NetworkManager/nm-dhcp-client.action).

Mungkin Anda bisa mengambil pendekatan yang berbeda: NM mengeluarkan sinyal DBus pada semua acara. Anda dapat mendengarkan pada sistem DBus untuk acara yang sesuai dan memicu skrip Anda berdasarkan ini ...

Bernhard
sumber