ローカル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ではなくローカル IPで行われるためです。

スクリプトをcronに入れて1分ごとに実行するか、少し複雑なスクリプトを書いて(...エレガントではありません。質問は次のとおりです。

ローカル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 14年

@steeldriverは、スクリプトがトリガーされていないようです。私はNMがDHCP処理の面倒を見ているのではないかと疑っています。とにかくありがとう。
Rmano 14年

回答:


10

NetmorkManagerのmanページによると、イベントの1つは

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

簡単に変えられると思う

up) 

dhcp4-change|up)

それは(ソート)動作します。スクリプトは少しでもトリガーされます。IPを変更せずに更新してもトリガーされます。もう少しbashスクリプトを実行する必要があると思います。道徳:マニュアルページのすべての内容を読んでください!
Rmano

少し待って(あなたは決して知らない...)、そして賞金を割り当てます。ありがとう!
Rmano 14年

14.04での私の経験では、そのように上下するイベントしか受信できません。他のイベントupdate.dで決してトリガースクリプト
init_js

4

dbusシグナルをリッスンするスクリプトを提供しています。これにより、現在のネットワーク構成の変更をポーリングする場合よりも迅速に対応できます。これは、スクリプト/ etc /を実行したいときに実行したくない場合に役立ちます(私の14.04システムのように)。

出入りするhooks.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-changedhcp6-changeあなたが望むものを正確に実行するように見えるアクションを定義します。マンページに書かれていることにもかかわらず、少なくとも私のシステムではupdownアクションのみが呼び出されます。これらのスクリプトを他のもので起動させることはできません。したがって、これはIPの変更を監視するのに最適な手段でもありません。

そのため、NMが発信するdbus信号を直接スヌープします

nm-dhcp-client.actionsource)、コマンドラインから、単にdhclientによって設定されたすべての環境変数をdbusシグナルに変換します。これらの環境変数はman dhclient-script(8)で定義されています。特に興味深いものの1つです$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について学ぶことは私の待ち行列の1つであり、皆さんの素晴らしいスタートであるため、試してみます。
Rmano

3

Pythonスクリプトを使用したポーリングアプローチ。基本的な考え方は、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-scriptsの代わりとして独自のバイナリを提供しています。(参考:NMバイナリはにあります/usr/lib/NetworkManager/nm-dhcp-client.action)。

別のアプローチを取ることもできます。NMはすべてのイベントでDBusシグナルを発行しています。適切なイベントをシステムDBusでリッスンし、これに基づいてスクリプトをトリガーできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.