最近在 WSL2 + ROS2 Humble + Webots 环境中运行 webots_ros2_universal_robot 示例时,发现 webots-controller 启动后立刻退出。日志显示它自动使用了一个明显不对的地址:
[ERROR] [webots_controller_UR5e-3]: process has died [pid 2087, exit code 1, cmd '/opt/ros/humble/share/webots_ros2_driver/scripts/webots-controller --robot-name=UR5e --protocol=tcp --ip-address=10.255.255.254 --port=1234 ...']但当前 WSL2 中明明存在正确可用的业务网卡地址,例如:
eth3 = 192.168.10.88eth1 = 192.168.192.160
一开始很容易怀疑是 Webots 选错了网卡,实际上问题更准确地说是:
webots_ros2_driver在 WSL2 下自动推断 Webots 主机地址时,错误地读取了/etc/resolv.conf中的nameserver,并把它当成了 Webots 服务器地址。
如果你的 /etc/resolv.conf 恰好包含:
nameserver 10.255.255.254那么最终 webots-controller 就会拿着这个错误地址去连接,导致启动失败。
问题现象
运行类似下面的命令启动 Webots 示例:
ros2 launch webots_ros2_universal_robot multirobot_launch.py控制器节点很快报错退出,日志中的关键部分如下:
[ERROR] [webots_controller_UR5e-3]: process has died [pid 2087, exit code 1, cmd '/opt/ros/humble/share/webots_ros2_driver/scripts/webots-controller --robot-name=UR5e --protocol=tcp --ip-address=10.255.255.254 --port=1234 ros2 --ros-args -r __ns:=/ur5e -p robot_description:=/opt/ros/humble/share/webots_ros2_universal_robot/resource/ur5e_with_gripper.urdf.xacro -p xacro_mappings:=['name:=UR5eWithGripper'] -p use_sim_time:=True -p set_robot_state_publisher:=True --params-file /opt/ros/humble/share/webots_ros2_universal_robot/resource/ros2_control_config.yaml']而 ifconfig 中实际存在多个 IPv4 地址,例如:
eth1: 192.168.192.160
eth3: 192.168.10.88看起来像是“地址选错了”,但继续深挖会发现,它根本不是从正常网卡选择逻辑里挑出来的。
为什么会出现 10.255.255.254
1. WSL2 可能自动生成 nameserver
在一些 WSL2 环境中,/etc/resolv.conf 里可能会出现这样的内容:
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 10.255.255.254这类地址本质上是 DNS 相关配置,并不是 Webots 服务地址。
2. webots_ros2_driver 误把 nameserver 当成 Webots 主机地址
webots_ros2_driver 在 WSL2 环境下会尝试自动获取 Windows 主机地址,以便 Linux 侧的 controller 去连接 Windows 侧运行的 Webots。
问题在于,它的推断逻辑会去读取 /etc/resolv.conf 的 nameserver,然后直接把它当成目标地址返回。
这就导致了:
如果
resolv.conf里是127.0.0.53,就会拿127.0.0.53如果是
8.8.8.8,就会拿8.8.8.8如果是
10.255.255.254,就会拿10.255.255.254
于是最终在启动参数中出现:
--ip-address=10.255.255.254这显然不是你真正的 Webots 主机地址,所以连接失败。
到底应该用哪个地址
这里要先分两种情况。
情况一:WSL2 使用 mirrored networking(镜像网络)
如果你开启了 mirrored networking,那么 最推荐的地址不是某张物理网卡的 IP,而是 127.0.0.1。
也就是说:
Windows 上运行 Webots
WSL2 中运行 ROS2 controller
两者之间直接通过
127.0.0.1通信
这种方式通常更稳定,也更符合 mirrored networking 的设计思路。
情况二:特殊 NAT / 多网卡 / 指定业务网络场景
如果你没有使用 mirrored networking,或者你的环境明确要求通过某张业务网卡通信,那么可以手工指定固定地址,例如:
192.168.10.88如何确认自己是否使用 mirrored networking
先在 Windows 用户目录查看:
%UserProfile%\.wslconfig如果里面有类似配置:
[wsl2]
networkingMode=mirrored说明当前 WSL2 启用了镜像网络模式。
例如可以配置成这样:
[wsl2]
networkingMode=mirrored
dnsTunneling=true
autoProxy=true
firewall=true修改后记得在 Windows PowerShell 中执行:
wsl --shutdown然后重新启动 WSL2,使配置生效。
为什么不建议去改 /etc/resolv.conf
有些排查思路会想到:既然 webots_ros2_driver 是从 /etc/resolv.conf 里读 nameserver,那我直接把里面内容改掉不就行了?
这种方式有两个问题:
1. 语义不对
/etc/resolv.conf 是 DNS 配置文件,不是 Webots 主机地址配置文件。
通过修改它来“顺便修好” Webots,属于误打误撞,不是正统修法。
2. WSL2 可能自动重建它
WSL2 会自动管理一些网络相关配置,/etc/resolv.conf 可能会被系统重新生成。
也就是说你手工改完,后面可能又被覆盖掉。
所以长期来看,更合理的方案是:
不要去伪造 DNS 配置,而是直接修正
webots_ros2_driver的地址推断逻辑。
最直接的解决方法:直接修改 webots_ros2_driver
这是我最终采用,也更推荐的方式。
适用场景
满足以下任一情况都可以直接使用:
启动时自动生成的
--ip-address明显不对日志里出现
10.255.255.254日志里出现
127.0.0.53日志里出现其它明显不是 Webots 主机的地址
已经确认问题来自
webots_ros2_driver自动推断逻辑
详细操作步骤
第一步:找到 utils.py
先在 WSL2 中执行以下面命令查安装文件:
dpkg -L ros-humble-webots-ros2-driver | grep 'utils.py'通常会落在类似路径:
/opt/ros/humble/local/lib/python3.10/dist-packages/webots_ros2_driver/utils.py第二步:备份原文件
修改系统安装文件前,先做备份:
sudo cp /opt/ros/humble/local/lib/python3.10/dist-packages/webots_ros2_driver/utils.py \
/opt/ros/humble/local/lib/python3.10/dist-packages/webots_ros2_driver/utils.py.bak如果你的实际路径不同,请替换成自己的路径。
第三步:打开文件编辑
使用 vim 编辑:
sudo vim /opt/ros/humble/local/lib/python3.10/dist-packages/webots_ros2_driver/utils.py搜索下面这个函数:
def get_wsl_ip_address():你大概率会在里面看到与读取 /etc/resolv.conf 有关的逻辑,如:
def get_wsl_ip_address():
try:
file = open('/etc/resolv.conf', 'r')
except IOError:
# /etc/resolv.conf doesn't exist, can't be read, etc.
# Use the default resolver configuration.
return '127.0.0.1'
try:
for line in file:
if len(line) == 0 or line[0] == '#' or line[0] == ';':
continue
tokens = line.split()
if len(tokens) == 0:
continue
if tokens[0] == 'nameserver':
file.close()
if len(tokens[1]) == 0:
return '127.0.0.1'
return tokens[1]
finally:
file.close()第四步:改成固定返回值
这里有三种写法,按你的环境选择。
方案 A:mirrored networking 场景,推荐返回 127.0.0.1
如果你的 WSL2 使用的是 mirrored networking,最推荐改成:
def get_wsl_ip_address():
return "127.0.0.1"这是最简单也最稳的方案。
方案 B:明确指定某张业务网卡,例如 192.168.10.88
如果你的环境必须通过固定网段访问,也可以直接写死成:
def get_wsl_ip_address():
return "192.168.10.88"这种方式适合:
你不是 mirrored networking
或者 Windows / Webots 端只能通过该网段连通
方案 C:做成可配置版本(推荐)
如果你不想每次都改源码,可以写成环境变量优先:
import os
def get_wsl_ip_address():
return os.environ.get("WEBOTS_HOST_IP", "127.0.0.1")这样后续需要切业务地址只需切换环境变量即可:
export WEBOTS_HOST_IP=192.168.10.88或者:
export WEBOTS_HOST_IP=127.0.0.1这比反复改源码更灵活。
重启并验证
修改完成后,重新执行启动命令:
ros2 launch webots_ros2_universal_robot multirobot_launch.py重点观察日志里 controller 的启动参数,确认 --ip-address 已经不再是:
10.255.255.254而变成了你期望的值,例如:
127.0.0.1或者:
192.168.10.88快速自检
1. 检查 /etc/resolv.conf
cat /etc/resolv.conf如果你看到:
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 10.255.255.254那就说明当前系统确实存在 WSL2 生成 nameserver 的情况。
2. 测试目标端口连通性
假设 Webots controller 监听的是 1234 端口,可以测试:
nc -vz 127.0.0.1 1234
nc -vz 192.168.10.88 1234如果你是 mirrored networking,建议优先验证:
127.0.0.1:1234如果只有指定业务网卡地址能通,那就把 get_wsl_ip_address() 固定成对应 IP。
问题总结
这次问题的本质不是:
Webots 自动选错了
eth3或者 Linux 网卡优先级异常
真正的问题是:
WSL2 环境中
/etc/resolv.conf可能存在10.255.255.254这样的 nameserverwebots_ros2_driver在 WSL2 下错误地读取了该 nameserver并将它当成 Webots 主机地址传给
webots-controller最终导致 controller 连接失败并退出
所以,最稳的处理方式不是去“修 DNS”,而是:
直接修复
webots_ros2_driver的地址推断逻辑,避免它继续误用/etc/resolv.conf。
参考
Cyberbotics 社区关于
webots_ros2_driver在 WSL2 下错误读取resolv.confnameserver 的问题讨论Microsoft WSL 关于 mirrored networking 与 localhost 通信说明
Microsoft WSL 关于
resolv.conf/ 网络自动管理相关说明
注:本文重点是记录问题现象与实际有效的修复手段,适合当前环境快速落地。如果后续官方修复了
webots_ros2_driver的 WSL2 地址推断逻辑,建议优先升级官方版本,避免长期维护本地补丁。
评论区