로컬 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가 언젠가 변경되도록 구성 됩니다. 이 경우 스크립트는 (논리적으로) 실행되지 않으며 파일은 업데이트되지 않습니다.

변경 사항이 외부 IP가 아닌 로컬 IP 에 있기 때문에 DynDNS 접근 방식을 사용할 수 없습니다 .

나는 단순히 cron에 스크립트를 넣고 매분마다 스크립트를 실행하거나 약간 더 복잡한 스크립트를 작성하거나 (IP가 변경되면 파일을 작성하지 않으면 아무것도하지 않음) 백그라운드 작업으로 다시 넣어서 폴링 할 수 있지만 우아하지 않습니다. 따라서 질문은 다음과 같습니다.

로컬 IP가 변경 될 때 스크립트를 트리거 할 수있는 방법이 있습니까?

업데이트 1

/etc/dhcp/dhclient-enter-hooks.d/기존에 따라에 스크립트를 넣으려고했지만 /etc/dhcp/dhclient-enter-hooks.d/resolvconf트리거되지 않습니다. NM (네트워크 관리자)이 dhcp 명령을 호출하지 않고 자체적으로 dhcp 협상을 수행하고 있다고 의심합니다 (확인 필요).


1
스크립트 를 통해 가능 해야하는 것처럼 보이지만 dhclient-enter-hooks.d... 한번도 시도한 적이 없습니다! 기존 /etc/dhcp/dhclient-enter-hooks.d/resolvconf스크립트 구문의 측면에서 도움이 될 수있는 어떤 신호 것은 찾기 위해 ( "$reason" == "BOUND"아마도?)
steeldriver

@steeldriver 스크립트가 트리거되지 않은 것 같습니다. NM이 DHCP 처리를 담당한다고 생각합니다. 어쨌든 고마워
Rmano

답변:


10

NetmorkManager의 매뉴얼 페이지에 따르면 이벤트 중 하나는

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

간단하게 바꿀 수 있다고 생각합니다

up) 

dhcp4-change|up)

그것은 (정렬) 작동합니다. 스크립트가 너무 많이 트리거되었습니다. IP를 변경하지 않고 갱신하더라도 트리거됩니다. 나는 조금 더 bash 스크립팅을해야한다고 생각합니다. 도덕 : 매뉴얼 페이지의 모든 내용을 읽으십시오 !
Rmano

조금 기다렸다가 (아무도 모르지만 ...) 현상금을 할당합니다. 감사!
Rmano

14.04에 대한 나의 경험에서, 나는 그런 식으로 위아래로만 이벤트를받을 수 있습니다. 다른 이벤트는 update.d에서 스크립트를 트리거하지 않습니다
init_js

4

dbus 신호를 수신하는 스크립트를 제공하므로 현재 네트워크 구성의 변경 사항을 폴링하는 것보다 빠르게 반응 할 수 있습니다. 원할 때 / etc / 스크립트가 실행되지 않는 시스템 (내 14.04 시스템에서와 같이)에서 도움이됩니다.

내 입장 / 퇴장 훅 .d 작동하지 않습니다

NetworkManager는 -sf /usr/lib/NetworkManager/nm-dhcp-client.action정상적인 입력 / 종료 후크 동작을 대체하는 것으로 보이는 플래그로 dhclient를 시작합니다 . dhclient의 기본 동작은에서 스크립트를 호출하는 것입니다 /etc/dhcp/dhclient-{enter,exit}-hooks.d. 그것들은 내 시스템에서 전혀 호출되지 않습니다.

내 NetworkManager dispatcher.d 스크립트가 작동하지 않습니다

그러나 NM은에서 /etc/NetworkManager/dispatcher.d다양한 이벤트를 알리기 위해 다른 스크립트 세트를 호출 합니다. NetworkManager (8) 매뉴얼 페이지는 원하는대로 정확하게 수행 할 수있는 작업을 정의 dhcp4-change하고 dhcp6-change수행 합니다 . 맨 페이지의 말씀에도 불구하고, 내 시스템에 적어도 만 up하고 down행동은 호출 얻을. 그 스크립트를 다른 곳에서 실행할 수 없습니다. 따라서 이것은 IP 변경을 모니터링하기에 좋은 방법이 아닙니다.

따라서 NM에서 방출 된 dbus 신호에서 직접 스누핑

nm-dhcp-client.action( source )는 명령 행에서 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.