จะรันสคริปต์ได้อย่างไรเมื่อมีการเปลี่ยนแปลง IP ท้องถิ่นของคุณ


15

ก่อนทำเครื่องหมายว่าซ้ำ: นี่ไม่เกี่ยวกับ DNS แบบไดนามิกหรือสิ่งที่คล้ายกัน

ฉันรู้วิธีเรียกใช้สคริปต์ทุกครั้งที่เครือข่ายของฉันทำงาน มันเป็นเรื่องง่ายของการเพิ่มสคริปต์ในไดเรกทอรี/etc/NetworkManager/dispatcher.dเช่นนี้

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

ในกรณีของฉันmyscriptมันง่ายมากifconfig -a > ~/Dropbox/myifconfig.txt--- ฉันใช้เพราะฉันต้องการรู้ IP ท้องถิ่นของฉันจากทุกที่ในมหาวิทยาลัยและมันจะเปลี่ยนบ่อย

จนถึงตอนนี้ระบบใช้งานได้ดี แต่น่าเสียดาย DHCP ที่นี่มีการกำหนดค่าเพื่อให้ IP บางครั้งมีการเปลี่ยนแปลงได้โดยไม่ต้องลง / ขึ้นของอินเตอร์เฟซ ในกรณีนั้นสคริปต์ไม่ทำงาน (ตามหลักเหตุผล) และไฟล์ไม่ได้รับการอัพเดต

ฉันไม่สามารถใช้วิธี DynDNS ได้เนื่องจากการเปลี่ยนแปลงนั้นอยู่ในIP ท้องถิ่นไม่ใช่วิธีที่มองเห็นจากภายนอก

ฉันสามารถสำรวจความคิดเห็นโดยเพียงแค่วางสคริปต์ใน cron และดำเนินการทุกนาทีหรือเขียนหนึ่งที่ซับซ้อนมากขึ้นเล็กน้อย (... หาก IP มีการเปลี่ยนแปลงเขียนไฟล์อย่างอื่นไม่ทำอะไรเลย) และวางมันอีกครั้งเป็นงานพื้นหลัง แต่มัน ไม่สง่างาม ดังนั้นคำถามคือ:

มีวิธีใดบ้างที่จะทริกเกอร์สคริปต์เมื่อ IP ในพื้นที่ของฉันเปลี่ยนแปลง

อัพเดท 1

ฉันพยายามใส่สคริปต์/etc/dhcp/dhclient-enter-hooks.d/ตามที่มีอยู่/etc/dhcp/dhclient-enter-hooks.d/resolvconfแล้ว แต่จะไม่ถูกทริกเกอร์ ฉันสงสัย (ต้องการการยืนยัน) ว่า NM (ตัวจัดการเครือข่าย) กำลังทำการเจรจาด้วยตนเองโดยไม่ต้องเรียกคำสั่ง dhcp ...


1
ดูเหมือนว่าจะเป็นไปได้ผ่านdhclient-enter-hooks.dสคริปต์ ... แต่ฉันไม่เคยลองเลย! /etc/dhcp/dhclient-enter-hooks.d/resolvconfสคริปต์ที่มีอยู่อาจมีประโยชน์ในแง่ของไวยากรณ์และสัญญาณใดที่จะมองหา ( "$reason" == "BOUND"อาจ?)
steeldriver

@steeldriver ดูเหมือนว่าสคริปต์จะไม่ถูกเรียกใช้ ฉันสงสัยว่า NM จะดูแลการจัดการ DHCP ... จะมองไปรอบ ๆ ขอบคุณอยู่ดี
Rmano

คำตอบ:


10

ตามหน้า man ของ NetmorkManager หนึ่งในเหตุการณ์คือ

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

ฉันคิดว่าคุณสามารถเปลี่ยนแปลงได้

up) 

ถึง

dhcp4-change|up)

มันทำงานได้ดี สคริปต์ถูกเรียกใช้แม้แต่น้อยเกินไป แม้การต่ออายุโดยไม่มีการเปลี่ยนแปลงใน IP จะทำให้มัน ฉันคิดว่าฉันจะต้องทำสคริปต์ทุบตีอีกเล็กน้อย คุณธรรม: อ่านเนื้อหาทั้งหมดของหน้า man!
Rmano

จะรอสักครู่ (คุณไม่มีทางรู้ว่า ... ) แล้วกำหนดค่าหัว ขอบคุณ!
Rmano

จากประสบการณ์ของฉันในวันที่ 14.04 ฉันสามารถรับเหตุการณ์ได้ตลอดทางขึ้น ๆ ลง ๆ เท่านั้น กิจกรรมอื่น ๆ จะไม่เรียกสคริปต์ใน update.d
init_js

4

ฉันกำลังให้สคริปต์ที่ฟังสัญญาณ dbus ซึ่งจะช่วยให้คุณตอบสนองได้เร็วกว่าที่คุณสำรวจความคิดเห็นสำหรับการเปลี่ยนแปลงการกำหนดค่าเครือข่ายปัจจุบันของคุณ ช่วยในระบบที่สคริปต์ / etc / ไม่ถูกเรียกใช้เมื่อคุณต้องการให้พวกเขา (เช่นในระบบ 14.04 ของฉัน)

hooks enter / exit ของฉันไม่ทำงาน

NetworkManager เริ่ม dhclient ด้วยการตั้งค่าสถานะ-sf /usr/lib/NetworkManager/nm-dhcp-client.actionซึ่งดูเหมือนจะแทนที่ลักษณะการทำงานของ hook ป้อน / ออกปกติ พฤติกรรมเริ่มต้นกับ dhclient /etc/dhcp/dhclient-{enter,exit}-hooks.dคือการเรียกสคริปต์ใน สิ่งเหล่านั้นไม่ได้ถูกเรียกบนระบบของฉันเลย

สคริปต์ NetworkManager dispatcher.d ของฉันไม่ทำงาน

อย่างไรก็ตาม NM เรียกใช้สคริปต์ชุด/etc/NetworkManager/dispatcher.dอื่นเพื่อแจ้งเหตุการณ์ต่าง ๆ หน้า man NetworkManager (8) กำหนดdhcp4-changeและdhcp6-changeการกระทำที่ดูเหมือนจะทำสิ่งที่คุณต้องการ แม้จะมีสิ่งที่ manpage พูด แต่อย่างน้อยในระบบของฉันเท่านั้นupและdownการกระทำที่ถูกเรียกใช้ ฉันไม่สามารถรับสคริปต์เหล่านี้เพื่อยิงสิ่งอื่นใดได้ ดังนั้นนี่จึงไม่ใช่หนทางที่ดีในการตรวจสอบการเปลี่ยนแปลง IP เช่นกัน

ดังนั้นสอดแนมโดยตรงกับสัญญาณ dbus ที่ส่งออกโดย NM

nm-dhcp-client.action( แหล่งที่มา ) จากบรรทัดคำสั่งเพียงแปลงตัวแปรสภาพแวดล้อมทั้งหมดที่กำหนดโดย dhclient เป็นสัญญาณ dbus ตัวแปรสภาพแวดล้อมเหล่านั้นถูกกำหนดในman dhclient-script(8) สิ่งที่น่าสนใจอย่างหนึ่งคือ$new_ip_addressหนึ่งในความสนใจเป็นพิเศษคือสิ่งที่คุณสามารถทำได้ตามคำแนะนำของ @Bernhard คือการตรวจสอบสัญญาณและดำเนินการตามเนื้อหา

นี่คือโปรแกรมที่จะสอดแนมข้อมูลเหตุการณ์ทั้งหมดที่ส่งสัญญาณโดยไบนารีนั้น

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

เอาต์พุตของ dbus-monitor ไม่ตรงไปตรงมาเพื่อวิเคราะห์คำในสคริปต์ บางทีการเรียกใช้คำหลักบางคำอาจง่ายกว่าเช่นnew_ip_addressและจากที่นั่นใช้เครื่องมือต่าง ๆ เพื่อรับข้อมูลที่เปลี่ยนแปลง (เช่น ip หรือ 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"
)
...

ลองยิงดู!


ขอบคุณมาก! โชคดี (สำหรับฉัน) ฉันกลับมาที่บ้านที่ฉันสามารถควบคุมเซิร์ฟเวอร์ DHCP ของฉันได้ แต่ฉันจะให้มันยิงเพราะการเรียนรู้เกี่ยวกับ DBus เป็นหนึ่งในสิ่งที่อยู่ในคิวของฉันและคุณเป็นจุดเริ่มต้นที่ยอดเยี่ยม
Rmano

3

วิธีการสำรวจด้วยสคริปต์ไพ ธ อน แนวคิดพื้นฐานคือการแยกวิเคราะห์เอาต์พุตอย่างต่อเนื่องip -4 -o add show <INTERFACE>และเปรียบเทียบผลลัพธ์ปัจจุบันกับการวนซ้ำก่อนหน้า

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

1

แม้ว่า NetworkManager ใช้ dhclient แต่ก็มีไบนารีของตัวเองเพื่อแทนที่สคริปต์ dhclient (สำหรับการอ้างอิง: คุณสามารถค้นหาไบนารี NM ได้ที่/usr/lib/NetworkManager/nm-dhcp-client.action)

บางทีคุณอาจใช้วิธีอื่น: NM กำลังออกสัญญาณ DBus ในทุกเหตุการณ์ คุณสามารถฟังระบบ DBus สำหรับเหตุการณ์ที่เหมาะสมและเรียกสคริปต์ของคุณตามนี้ ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.