如何通过U-Boot向systemd提供eth0的IP地址?
你的思路是完全可行的,但问题出在 systemd 234版本对.network配置文件的环境变量支持有限,加上你之前的配置方式存在适配问题,导致网络配置卡住。下面我会详细拆解问题原因,并给出两种可落地的解决方案:
为什么之前的配置会卡住?
systemd 234的systemd-networkd服务不支持直接在.network配置文件中引用环境变量(比如你写的${ipaddr})。当系统启动时,配置文件里的变量无法被解析为实际IP,导致systemd-networkd无法完成网络配置,进而触发了「Starting Wait for Network to be Configured...」的超时等待,最终卡住。
另外,你传递参数的方式也需要调整:U-Boot里的${ipaddr}需要被提前展开为具体IP值再传给内核,否则内核命令行里只会保留${ipaddr}字符串,而不是实际的IP地址。
解决方案一:使用内核原生ip=参数(推荐)
这种方法无需依赖systemd的环境变量机制,直接让内核在启动阶段配置网络,systemd-networkd只需要不覆盖该配置即可,实现最简单可靠。
1. 在U-Boot中配置内核命令行
修改U-Boot的bootargs,添加内核原生的ip参数,格式如下:
# 假设U-Boot中已有ipaddr、gatewayip、netmask环境变量 setenv bootargs ${bootargs} ip=${ipaddr}::${gatewayip}:${netmask}::eth0:none
参数格式说明:ip=<客户端IP>::<网关IP>:<子网掩码>::<网卡名>:none,其中::表示忽略对应字段(比如这里忽略了主机名和DNS),none表示禁用DHCP。如果不需要网关,可以简化为:
setenv bootargs ${bootargs} ip=${ipaddr}/${netmask}:::none:eth0
2. 修改systemd-networkd配置
修改/lib/systemd/network/wired.network,确保它不会覆盖内核已经配置的IP:
[Match] Name=eth0 [Network] DHCP=no LinkLocalAddressing=no # 注释或删除原来的静态IP配置行 # Address=192.168.0.100/24
这样systemd-networkd会保留内核初始化的网络配置,不会尝试重新配置,自然不会卡住。
解决方案二:用systemd oneshot服务动态生成配置
如果必须通过systemd.setenv传递变量,可以通过oneshot服务在systemd-networkd启动前生成有效的.network配置文件,绕过版本限制。
1. 在U-Boot中传递环境变量
在U-Boot中设置bootargs,将IP(带子网)传递给systemd:
# 直接展开U-Boot的ipaddr和netmask变量 setenv bootargs ${bootargs} systemd.setenv=STATIC_IP=${ipaddr}/${netmask}
执行printenv bootargs确认输出中是具体的IP值(比如STATIC_IP=192.168.0.100/24),而不是未展开的${ipaddr}。
2. 创建oneshot服务
新建/etc/systemd/system/setup-static-ip.service文件,内容如下:
[Unit] Description=Generate static IP config from kernel command line Before=systemd-networkd.service Requires=systemd-networkd.service [Service] Type=oneshot # 生成临时配置文件到/run目录(重启后自动消失,不会被rootfs镜像覆盖) ExecStart=/bin/sh -c 'cat > /run/systemd/network/01-wired.network <<EOF [Match] Name=eth0 [Network] Address=${STATIC_IP} # 按需添加网关和DNS # Gateway=192.168.0.1 # DNS=8.8.8.8 EOF' # 重载systemd-networkd让新配置生效 ExecStart=/bin/systemctl reload-or-restart systemd-networkd.service [Install] WantedBy=multi-user.target
3. 禁用原有配置避免冲突
# 删除或重命名原有的静态配置文件 rm /lib/systemd/network/wired.network # 启用新的oneshot服务 systemctl enable setup-static-ip.service
内容的提问来源于stack exchange,提问作者flederwiesel




