重複としてマークする前:これはnotダイナミック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がいつか変更されるように設定されていますインターフェイスのダウン/アップなし。その場合、スクリプトは(論理的に)実行されず、ファイルは更新されません。
変更はlocal IPであり、外部から見えるIPではないため、DynDNSアプローチを使用できません。
スクリプトをcronに入れて毎分実行するか、少し複雑なものを書いて(... IPが変更された場合はファイルに書き込み、それ以外は何もしない)、バックグラウンドタスクとして再び置くことで、ポーリングできますが、エレガントではありません。質問は次のとおりです。
ローカルIPが変更されたときにスクリプトをトリガーする方法はありますか?
更新1
既存の/etc/dhcp/dhclient-enter-hooks.d/
に基づいて/etc/dhcp/dhclient-enter-hooks.d/resolvconf
にスクリプトを配置しようとしましたが、トリガーされません。 NM(ネットワークマネージャー)がdhcpコマンドを呼び出さずに、それ自体でdhcpネゴシエーションを行っていると思われます(確認が必要)。
NetmorkManagerのmanページによると、イベントの1つは
dhcp4-change
The DHCPv4 lease has changed (renewed, rebound, etc).
簡単に変えられると思う
up)
に
dhcp4-change|up)
Dbusシグナルをリッスンするスクリプトを提供しています。これにより、現在のネットワーク構成の変更をポーリングする場合よりも迅速に対応できます。これは、スクリプト/ etc /を希望するときに実行されないシステムで役立ちます(私の14.04システムのように)。
Enter/Exit 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-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"
)
...
試してみます!
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 __== '__main__':
# use while loop if yout want this script to run
# continuously
while True:
try:
main()
except KeyboardInterrupt:
sys.exit()
NetworkManagerはdhclientを使用していますが、dhclient-scriptsの代わりとして独自のバイナリを提供しています。 (参照用:NMバイナリは/usr/lib/NetworkManager/nm-dhcp-client.action
にあります)。
別のアプローチをとることもできます。NMはすべてのイベントでDBusシグナルを発行しています。適切なイベントをシステムDBusでリッスンし、これに基づいてスクリプトをトリガーできます...