根据发行版,调用ip link set <iface> up
(或 down;还有 ifup / ifdown)将查看各种配置文件(Debian 上的 /etc/network/interfaces 我认为,Gentoo 有 /etc/conf.d/net...),并进行更改(例如与 DHCP 交互等)
据我所见strace
,该ip
命令直接与内核对话(是这样吗?)。但最终,有人启动这些 shell 脚本/读取配置。这背后的机制是什么?init 系统是否在某些内核接口上侦听 up/down 状态更改并启动这些脚本?或者有什么不同吗?
正如您所描述的那样,调用只是通过rtnetlink APIip link set <iface> up
与内核进行最少的通信(这不仅与路由有关,还与链接、地址等有关。这里就是这样),以管理方式启动接口。较旧的工具使用已弃用的(针对网络)ioctl API(此处为)向内核提出相同的要求。RTM_NEWLINK
ifconfig
SIOCGIFFLAGS
这些命令是低级命令,仅执行所要求的操作,仅此而已。
ifup
是ifupdown(或备用ifupdown2 )套件的一部分(在 Debian 上),并且在不同的 Linux 发行版上有不同的实现。它们只是一套脚本,可能会调用ip link set ...
自身,并且其中一些脚本可能还会直接使用其他可用的工具(例如NetworkManager)。所以你绝对不能把它们放在同一水平上:ip link set ... up
根本不是ifup ...
。
现在,其他网络工具(例如NetworkManager)如何交互并知道发生了什么?因为他们通过rtnetlink要求内核获得他们感兴趣的一些网络事件的通知。netlink API 实现支持多播:这意味着单个消息可以被多个感兴趣的各方(属于用户空间或内核)有效地接收,因此这简化了事件的实现。
通常,当某些东西(此处ip link set ... up
)向内核发送消息时,内核会回复一条消息,该消息被多播给感兴趣的各方:该命令收到ip link
此消息,而且所有等待的工具现在都知道“刚刚启动了一个接口” “(我将忽略管理状态启动与操作状态启动之间的差异)。
可以使用由等待ip monitor
来自内核的网络事件的命令的输出驱动的事件循环在脚本中执行相同的操作。当然,真正可解析的输出会更好,遗憾的是,虽然许多其他iproute2子命令支持 JSON 输出(使用-json
),但ip monitor
.
这是一个基本的shell 示例,ip monitor link
每当对该接口进行更改时,都会显示该接口的操作状态(即使它与其操作状态无关......这是一个基本示例)。由于它正在解析不可靠的输出,因此预计它在某些情况下会失败:
#!/bin/sh
ip -o monitor link | while read -r index interface status remaining; do
iface=$(printf '%s\n' "$interface" | sed -E 's/(@.*)?:$//')
operstate=$(printf '%s\n' "$remaining" | grep -Eo ' state [^ ]+' | sed 's/^ state //')
printf '%s %s\n' "$iface" "$operstate"
done
Run Code Online (Sandbox Code Playgroud)
当上面的脚本运行时,在其他地方尝试这些命令:
# ip link add test1 type veth peer name test2
# ip link set test1 up
# ip link set test2 up
# ip link delete test1 # script doesn't handle correctly lines starting with Deleted
Run Code Online (Sandbox Code Playgroud)
地址、路由等也是可能的。这就是NetworkManager等工具对命令的反应方式ip link set <iface> up
。