Debian 11 默认使用 systemd 和 ifupdown 配置网络。我对 systemd 如何实现感兴趣network-online.target
。
# systemctl show network-online.target | grep -E 'After|Wants'
Wants=networking.service
After=networking.service network.target [email protected]
我可以看到存在依赖关系networking.service
,并且目标排在之后[email protected]
。
# systemctl show networking.service | grep ExecStart
ExecStart={ path=/sbin/ifup ; argv[]=/sbin/ifup -a --read-environment ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
ExecStart={ path=/bin/sh ; argv[]=/bin/sh -c if [ -f /run/network/restart-hotplug ]; then /sbin/ifup -a --read-environment --allow=hotplug; fi ; ignore_errors=yes ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
ExecStartEx={ path=/sbin/ifup ; argv[]=/sbin/ifup -a --read-environment ; flags= ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
ExecStartEx={ path=/bin/sh ; argv[]=/bin/sh -c if [ -f /run/network/restart-hotplug ]; then /sbin/ifup -a --read-environment --allow=hotplug; fi ; flags=ignore-failure ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
依赖关系基本上只是运行ifup -a
。
如果我检查[email protected]
,我会发现它是一个实例化的服务:
# systemctl cat [email protected]
# /lib/systemd/system/[email protected]
[Unit]
Description=ifup for %I
After=local-fs.target network-pre.target apparmor.service systemd-sysctl.service
Before=network.target shutdown.target network-online.target
Conflicts=shutdown.target
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
DefaultDependencies=no
IgnoreOnIsolate=yes
[Service]
# avoid stopping on shutdown via stopping system-ifup.slice
Slice=system.slice
ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
ExecStop=/sbin/ifdown %I
RemainAfterExit=true
TimeoutStartSec=5min
并且它排在之后,并绑定到sys-subsystem-net-devices-ens192.device
,但这个单元没有实际的文件:
# systemctl show sys-subsystem-net-devices-ens192.device | grep ens192
SysFSPath=/sys/devices/pci0000:00/0000:00:16.0/0000:0b:00.0/net/ens192
Id=sys-subsystem-net-devices-ens192.device
Names=sys-subsystem-net-devices-ens192.device
[email protected]
[email protected]
# systemctl cat sys-subsystem-net-devices-ens192.device
No files found for sys-subsystem-net-devices-ens192.device.
我可以看到man systemd.device
它们是通过 udev 自动创建的,但是没有提及它们是如何绑定到实例化服务或围绕实例化服务进行排序的。
我还剩下这两个问题似乎无法找到答案:
- 告诉 systemd 使用的文件/配置在哪里[电子邮件保护]
BoundBy
设备单元中的 和? 2.和Before
之间没有顺序;为什么两者都存在,为什么最终运行的是,而不是?networking.service
[email protected]
[email protected]
dhclient
networking.service
谢谢!
答案1
并且它被排序在 sys-subsystem-net-devices-ens192.device 之后并与其绑定,但是这个单元没有实际的文件:
.device 单元是虚拟的,代表 udev 状态。每个被TAG+="systemd"
udev 规则标记的设备都会导致 .device 单元出现 - 当特定设备的 udev 规则处理完成时,.device 单元变为“活动”状态。
.device 单元可以通过 udev 属性设置依赖项,例如,ENV{SYSTEMD_WANTS}+="..."
从相应单元添加 Wants= 依赖项。
但即使 .device 单元不“存在”,它们能具有由.wants/
符号链接设置的依赖项;例如,有可能sys-foo.device.wants/
(可能在 /run/systemd/generator 中)就像有一样multi-user.target.wants/
。
(具体来说,对于网络接口,整个“/sys/subsystem”也是由 udev 规则产生的别名ENV{SYSTEMD_ALIAS}
。曾有计划让 /sys/subsystem 存在于内核中,但没有通过。)
我可以从 man systemd.device 中看到这些是通过 udev 自动创建的,但没有提到它们如何绑定到实例化服务或围绕实例化服务进行排序。
如果设备有“BoundBy”,那只是意味着其他该单元有一个BindsTo=
适用于该设备的。
“BoundBy=”、“WantedBy=”、“RequiredBy=”不是真正的设置——它们从未明确设置,无论是通过 udev 还是其他方式;它们只反映了入站依赖项,即 BindsTo=、Wants= 和 Requires=。
Before= 和 After= 有类似情况。设备单元报告“Before=ifup@”因为ifup@ 有“After=device”;Before= 没有明确设置。
networking.service 和[电子邮件保护];为什么两者都存在
networking.service 的存在是因为人们习惯于使用旧 Debian 版本中的 /etc/init.d/networking – ifupdown 包含它,以便人们可以“重新启动网络”。
为什么[电子邮件保护]是最终运行 dhclient 而不是 networking.service 的程序
一个 .service 只能监控一个“主”进程。由于 ifupdown 没有中央监督进程,只有一堆独立的 dhclient 实例,因此每个实例都需要有自己的 .service。(将它们分开也有助于解决硬件依赖性问题,因为接口不会同时出现 - 完全可以有一些在启动时可用,而有些稍后再连接。)
答案2
告诉 systemd 使用的文件/配置在哪里[电子邮件保护]?
您的 /etc/network/interfaces 文件似乎使用 allow-hotplug 而不是 auto 配置 ens192。Debian 有 udev 规则(在 /lib/udev/rules.d 中查找 ifupdown.rules),这些规则会导致它运行 /lib/udev/ifupdown-hotplug ,从而启动 ifup@ens192 。在 ifupdown-hotplug 脚本中,查找
exec systemctl --no-block start $(systemd-escape --template [email protected] $TARGET_IFACE)
networking.service 和[电子邮件保护];为什么两者都存在,为什么[电子邮件保护]是最终运行 dhclient 而不是 networking.service 的程序
我不是专家,但粗略看一下代码,我的理解是[电子邮件保护]设置使用“allow-hotplug”配置的接口,而 networking.service 设置使用“auto”配置的接口。尝试在 /etc/network/interfaces 中将 ens192 从 allow-hotplug 切换为 auto,并检查哪个服务启动了 dhclient 以进行确认。
答案3
关于你的问题
为什么最终运行的是,而不是?
/lib/systemd/system/[email protected]
dhclient
networking.service
TL;DR:恕我直言,这是因为 Debian 11dhclient
默认安装了可执行文件;执行。如果必须执行与 DHCP 相关的内容,并且已安装,则将优先使用而不是任何其他可能可用的“dhcp 工具”。/lib/systemd/system/[email protected]
ifup
ifup
dhclient
ifup
dhclient
解释
/lib/systemd/system/[email protected]
看起来像是Debian 11 靶心系统:
[Unit]
Description=ifup for %I
After=local-fs.target network-pre.target apparmor.service systemd-sysctl.service
Before=network.target shutdown.target network-online.target
Conflicts=shutdown.target
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
DefaultDependencies=no
IgnoreOnIsolate=yes
[Service]
# avoid stopping on shutdown via stopping system-ifup.slice
Slice=system.slice
ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
ExecStop=/sbin/ifdown %I
RemainAfterExit=true
TimeoutStartSec=5min
因此ExecStart=...
执行ifup
命令。
man 8 ifup
内容如下:
ifup 和 ifdown 命令可用于根据接口定义配置(或分别取消配置)网络接口在文件中
/etc/network/interfaces
。
在我的系统上,/etc/network/interfaces
包括以下内容:
# ...
source /etc/network/interfaces.d/*
# ...
# The primary network interface
allow-hotplug enp0s3
iface enp0s3 inet dhcp
# ...
关于,... dhcp
iface enp0s3 inet dhcp
man 5 interfaces
提供以下信息:
可以使用 [dhcp] 方法通过以下任何工具通过 DHCP 获取地址:dh客户端、泵、udhcpc、dhcpcd。(它们是按照优先顺序排列的。)如果你有一个复杂的DHCP设置,你应该请注意,其中一些客户端使用自己的配置文件,不通过 ifup 获取其配置信息。
据我观察,当我使用可启动 ISO 映像安装程序安装 Debian 11 时debian-11.6.0-amd64-netinst.iso
,原始安装已经包含/sbin/dhclient
(并且由于/sbin
是 的符号链接/usr/sbin/
,它实际上位于/usr/sbin/dhclient
)。
使用
for pid in $(pidof dhclient); do ps -fp $pid; pstree -lapstc $pid; echo; done
我可以看到/sbin/dhclient
被催生systemd(在我的例子中,由于有两个接口,因此有两个正在运行dh客户端过程,因此使用 for 循环来显示每个过程的详细信息)。
dpkg -S /sbin/dhclient
表明/sbin/dhclient
由易于软件包isc-dhcp-client
,它是在初始 Debian 安装期间安装的。