如何利用systemd/networkctl在特定网络接口进入routable状态时执行脚本?
如何利用systemd/networkctl在特定网络接口进入routable状态时执行脚本?
我来给你几个亲测靠谱的方案,专门解决你遇到的这个棘手问题——设备始终处于active状态,没法靠device单元触发,sysfs的path单元也不生效的情况:
方法一:用systemd-networkd-dispatcher直接对接状态事件
这是最精准的方式,因为systemd-networkd本身就会把接口状态变化的事件派发给dispatcher目录里的脚本,完全不需要你自己轮询:
- 先给目标状态创建对应的目录(routable状态的专属目录):
sudo mkdir -p /etc/systemd/networkd-dispatcher/routable.d - 在这个目录里创建你的触发脚本,文件名开头可以加数字控制执行优先级(比如
99-my-interface-script.sh):#!/bin/bash # 替换成你要监控的接口名,比如eth0、wlan0 TARGET_IF="eth0" if [ "$INTERFACE" = "$TARGET_IF" ]; then # 这里写你要执行的具体逻辑 echo "[$(date)] 接口$TARGET_IF进入routable状态,执行脚本" >> /var/log/interface-trigger.log # 比如调用你自己的脚本:/path/to/your/custom-script.sh fi - 给脚本加上可执行权限:
sudo chmod +x /etc/systemd/networkd-dispatcher/routable.d/99-my-interface-script.sh - 重启dispatcher服务让配置生效:
sudo systemctl restart systemd-networkd-dispatcher.service
之后每次你的接口进入routable状态,这个脚本就会自动触发,完全不用管设备是不是一直active。
方法二:自定义systemd服务+状态监听脚本
如果需要更灵活的逻辑(比如监听状态变化的整个过程),可以写一个简单的监听脚本配合systemd服务:
- 先创建监听脚本
/usr/local/bin/watch-interface-routable.sh:#!/bin/bash TARGET_IF="$1" if [ -z "$TARGET_IF" ]; then echo "请传入目标接口名作为参数" exit 1 fi # 循环监听接口状态 while true; do # 用networkctl获取当前接口状态 CURRENT_STATE=$(networkctl status "$TARGET_IF" | awk '/State:/ {print $2}') if [ "$CURRENT_STATE" = "routable" ]; then # 执行你的自定义逻辑 /path/to/your/script.sh # 如果只需要触发一次,就加break;如果要持续监听状态变化(比如从routable变其他再变回来再触发),就删掉break break fi sleep 2 # 每2秒检查一次,可根据需求调整间隔 done - 给脚本加执行权限:
sudo chmod +x /usr/local/bin/watch-interface-routable.sh - 创建systemd服务文件
/etc/systemd/system/interface-routable-trigger.service:[Unit] Description=监听指定接口进入routable状态并执行脚本 After=systemd-networkd.service [Service] Type=oneshot RemainAfterExit=yes # 替换成你的接口名 ExecStart=/usr/local/bin/watch-interface-routable.sh eth0 # 如果需要重新触发检查,可以用systemctl reload这个服务 ExecReload=/usr/local/bin/watch-interface-routable.sh eth0 [Install] WantedBy=multi-user.target - 启用并启动服务:
sudo systemctl enable --now interface-routable-trigger.service
一些小提醒
- 所有脚本都必须设置可执行权限,否则systemd或dispatcher没法运行它们
- 用networkd-dispatcher时,文件名开头的数字决定执行顺序,数字越大越晚执行,比如00-开头的会先于99-开头的脚本
- 测试的时候可以用
networkctl down eth0 && networkctl up eth0手动切换接口状态,验证脚本是否正常触发
备注:内容来源于stack exchange,提问作者Jochen
相关产品推荐
相关产品推荐

