当本地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协商,而没有调用dhcp命令...


1
看起来应该可以通过dhclient-enter-hooks.d脚本实现...但是我从未尝试过!现有的/etc/dhcp/dhclient-enter-hooks.d/resolvconf脚本可能会对语法和寻找什么信号("$reason" == "BOUND"可能是?)有所帮助
Steeldriver 2014年

@steeldriver似乎未触发脚本。我怀疑NM负责DHCP处理...会四处看看。不管怎么说,还是要谢谢你。
Rmano

Answers:


10

根据NetmorkManager的手册页,事件之一是

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

我想你可以改变

up) 

dhcp4-change|up)

它(排序)有效。脚本触发得太多了。即使没有IP更改的续约也会触发它。我想我将不得不做更多的bash脚本编写。道德:阅读手册页的所有内容!
Rmano 2014年

请稍等(您永远不会知道...),然后分配赏金。谢谢!
Rmano 2014年

根据我在14.04上的经验,我只能通过这种方式接收上下事件。其他事件永远不会触发update.d中的脚本
init_js,2013年

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)中定义。特别令人感兴趣的是$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

使用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上监听适当的事件,并基于此触发脚本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.