WSL2 Mirrored 模式下 Synopsys License 启动失败:localhost 路由异常修复记录
前言
之前我在 WSL2 Ubuntu 中运行 Synopsys 工具,并通过 FlexNet License Server 提供 License。
在 WSL2 默认 NAT 网络模式下,Synopsys License 可以正常启动,但 WSL 无法方便地使用 Windows 主机上的代理。将 WSL 切换到mirrored网络模式后,代理恢复正常,但 Synopsys License Server 无法启动,Verdi、VCS 等工具也无法获取 License。
最终定位发现,这并不是 License 文件、HostID 或 DNS 配置错误,而是 WSL Mirrored 模式下的 localhost 策略路由异常。
本文记录问题原因和最终解决方法。
一、问题现象
License 文件中的服务器配置如下:
SERVER LAPTOP-CEUP9426 00155dec9c9b 27000 DAEMON snpslmd /home/synopsys/scl/2018.06/linux64/bin/snpslmd启动 License 服务后,lmgrd能够正常运行并监听27000端口:
ps-ef|grep-E'[l]mgrd|[s]npslmd'只能看到:
/home/synopsys/scl/2018.06/linux64/bin/lmgrd ...但看不到snpslmd进程。
查看 systemd 日志:
journalctl-usynopsys-license.service-b-n30--no-pager可以看到:
snpslmd exited with status 76 (Not able to resolve local host) This error probably results from: 1. DNS server not able to resolve localhost. 2. /etc/hosts file does not contain an entry for localhost.从日志看,似乎是localhost或 DNS 配置存在问题。
但实际检查发现,主机名和 localhost 都可以正常解析:
getent ahostsv4 localhost getent ahostsv4 LAPTOP-CEUP9426输出类似:
127.0.0.1 STREAM localhost 127.0.1.1 STREAM LAPTOP-CEUP9426License 对应的 HostID 也能被正确识别:
/home/synopsys/scl/2018.06/linux64/bin/lmhostid-ether输出中包含:
00155dec9c9b因此问题并不是 HostID 或/etc/hosts配置错误。
二、真正原因
为了确认snpslmd退出前究竟做了什么,使用strace跟踪 License Server:
strace-ff-s256\-o/tmp/synopsys.trace\-etrace=network,ioctl,file,process\/home/synopsys/scl/2018.06/linux64/bin/lmgrd\-z\-c/home/synopsys/scl/2018.06/admin/license/Synopsys.dat在跟踪结果中发现了关键错误:
connect( 53, { sa_family=AF_INET, sin_port=htons(45116), sin_addr=inet_addr("127.0.0.1") }, 16 ) = -1 EHOSTUNREACH (No route to host)snpslmd启动时会进行一次本地网络自检:
启动一个本地 TCP 监听端口 ↓ 连接 127.0.0.1 上的该端口 ↓ 检查本机回环网络是否正常但在当前 WSL Mirrored 模式下,连接127.0.0.1返回了:
No route to host为了进一步确认,使用 Python 创建一个只监听127.0.0.1的服务,再从本机连接:
importsocket server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(("127.0.0.1",0))server.listen(1)port=server.getsockname()[1]client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)client.connect(("127.0.0.1",port))结果同样失败:
OSError: [Errno 113] No route to host这说明问题并不是 Synopsys License 特有问题,而是当前 WSL 中最基本的 IPv4 localhost 通信已经异常。
三、WSL Mirrored 的策略路由异常
查看访问127.0.0.1时使用的路由:
iproute get127.0.0.1异常情况下输出为:
127.0.0.1 via 169.254.73.152 dev loopback0 table 127正常的 Linux localhost 流量应该走:
local 127.0.0.1 dev lo table local继续查看策略路由:
iprule show可以看到 Mirrored 模式生成了下面的规则:
1: from all ipproto tcp lookup 127 1: from all ipproto udp lookup 127 2: from all lookup local查看 table 127:
iproute show table127输出:
127.0.0.1 via 169.254.73.152 dev loopback0而正常的 local 路由表中实际上存在:
iproute show tablelocallocal 127.0.0.1 dev lo问题就在于策略路由的优先级。
访问127.0.0.1时,系统先匹配:
lookup 127因此流量被送往:
loopback0而不是标准的 Linux 回环接口:
lo最终导致:
127.0.0.1 ↓ table 127 ↓ loopback0 ↓ No route to hostsnpslmd检测到本地自连接失败后退出,并给出了比较具有误导性的错误:
Not able to resolve local host所以真正的问题不是 DNS,而是:
WSL Mirrored 模式下,访问
127.0.0.1的策略路由优先进入了 table 127,导致 localhost 流量没有走标准的 lo 回环接口。
四、临时修复方法
添加三条优先级更高的规则,让127.0.0.0/8优先查询标准的 local 路由表:
sudoipruleaddpref0to127.0.0.0/8 lookuplocalsudoipruleaddpref0\to127.0.0.0/8\ipproto tcp\lookuplocalsudoipruleaddpref0\to127.0.0.0/8\ipproto udp\lookuplocalsudoiproute flush cache重新检查路由:
iproute get127.0.0.1此时输出恢复正常:
local 127.0.0.1 dev lo table local src 127.0.0.1再次启动 Synopsys License:
sudosystemctl start synopsys-license.service查看进程:
ps-ef|grep-E'[l]mgrd|[s]npslmd'可以同时看到:
lmgrd snpslmd检查 License 状态:
/home/synopsys/scl/2018.06/linux64/bin/lmstat\-a\-c27000@localhost输出:
license server UP (MASTER) Vendor daemon status: snpslmd: UP此时 Verdi、VCS 等 Synopsys 工具已经可以正常打开。
五、创建自动修复脚本
上面的ip rule在执行wsl --shutdown后会消失,因此需要配置开机自动恢复。
创建脚本:
sudonvim /usr/local/sbin/fix-wsl-mirrored-loopback.sh写入:
#!/usr/bin/env bashset-euopipefailadd_rule_if_missing(){localrule="$1"if!iprule show|grep-Fq"$rule";thenipruleaddpref0$rulefi}# 让 127.0.0.0/8 优先查询 Linux 标准 local 路由表。add_rule_if_missing"to 127.0.0.0/8 lookup local"add_rule_if_missing\"to 127.0.0.0/8 ipproto tcp lookup local"add_rule_if_missing\"to 127.0.0.0/8 ipproto udp lookup local"iproute flush cache# 将最终路由输出到 systemd 日志中,便于检查。iproute get127.0.0.1增加执行权限:
sudochmod755\/usr/local/sbin/fix-wsl-mirrored-loopback.sh手动测试:
sudo/usr/local/sbin/fix-wsl-mirrored-loopback.sh因为脚本会先检查规则是否存在,所以可以重复执行,不会不断添加重复规则。
检查规则:
iprule show|grep'127.0.0.0/8'输出:
0: from all to 127.0.0.0/8 lookup local 0: from all to 127.0.0.0/8 ipproto tcp lookup local 0: from all to 127.0.0.0/8 ipproto udp lookup local六、创建 systemd 服务
创建服务文件:
sudonvim\/etc/systemd/system/wsl-mirrored-loopback-fix.service内容如下:
[Unit] Description=Fix WSL Mirrored localhost routing Wants=network-online.target After=network-online.target Before=synopsys-license.service [Service] Type=oneshot ExecStart=/usr/local/sbin/fix-wsl-mirrored-loopback.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target重新加载并启用服务:
sudosystemctl daemon-reloadsudosystemctlenable--now\wsl-mirrored-loopback-fix.service检查状态:
systemctl status\wsl-mirrored-loopback-fix.service\--no-pager-l正常情况下显示:
Active: active (exited)这是正常现象,因为该服务类型是:
Type=oneshot脚本执行完成后进程会退出,但 systemd 会记录服务已经成功完成。
七、让 License 服务等待路由修复完成
为了保证每次启动 License 前 localhost 路由都已修复,可以为 License 服务增加 systemd 依赖。
创建 drop-in 目录:
sudomkdir-p\/etc/systemd/system/synopsys-license.service.d创建依赖配置:
sudonvim\/etc/systemd/system/synopsys-license.service.d/10-loopback-fix.conf写入:
[Unit] Requires=wsl-mirrored-loopback-fix.service After=wsl-mirrored-loopback-fix.service这样 systemd 会按照下面的顺序执行:
WSL Mirrored 网络启动 ↓ wsl-mirrored-loopback-fix.service ↓ 修复 localhost 路由 ↓ synopsys-license.service ↓ lmgrd 和 snpslmd重新加载:
sudosystemctl daemon-reload八、增加 License 重启间隔
在测试过程中发现,如果连续多次执行:
sudosystemctl restart synopsys-license.service旧的lmgrd可能还没有完全释放27000端口,systemd 就启动了新实例,从而出现:
Failed to open the TCP port number in the license.可以为 License 服务增加重启延迟。
创建:
sudonvim\/etc/systemd/system/synopsys-license.service.d/20-restart-delay.conf内容:
[Service] Restart=on-failure RestartSec=3重新加载:
sudosystemctl daemon-reload检查配置:
systemctl show synopsys-license.service\-pRestart\-pRestartUSec预期输出:
Restart=on-failure RestartUSec=3s如果需要手动重启 License,建议使用:
sudosystemctl stop synopsys-license.servicesleep2sudosystemctl start synopsys-license.service相比连续执行restart,这种方式可以给旧进程和端口留出释放时间。
九、冷启动验证
完成配置后,在 Windows PowerShell 中执行:
wsl--shutdown重新打开 Ubuntu。
检查路由修复服务:
systemctl status\wsl-mirrored-loopback-fix.service\--no-pager-l输出:
Active: active (exited)检查 localhost 路由:
iproute get127.0.0.1输出:
local 127.0.0.1 dev lo table local src 127.0.0.1检查自动生成的规则:
iprule show|grep'127.0.0.0/8'输出:
0: from all to 127.0.0.0/8 lookup local 0: from all to 127.0.0.0/8 ipproto tcp lookup local 0: from all to 127.0.0.0/8 ipproto udp lookup local检查 License 进程:
ps-ef|grep-E'[l]mgrd|[s]npslmd'能够同时看到:
lmgrd snpslmd最后检查 License 状态:
/home/synopsys/scl/2018.06/linux64/bin/lmstat\-a\-c27000@localhost输出:
license server UP (MASTER) snpslmd: UP说明冷启动自动修复和 License 自动启动都已经成功。
十、总结
本次问题表面上的报错是:
Not able to resolve local host但实际原因并不是 DNS、/etc/hosts、License 文件或 HostID 配置错误。
真正原因是:
WSL2 Mirrored 模式生成的策略路由优先将
127.0.0.1发送到 table 127 和 loopback0,导致 Linux 本机 localhost TCP 自连接返回No route to host。
而 Synopsys 的snpslmd在启动过程中需要通过127.0.0.1进行本地自连接检查,因此检查失败后直接退出。
最终解决方式是:
为 127.0.0.0/8 添加更高优先级的 local 路由规则 ↓ 通过 systemd 在 WSL 启动后自动执行修复脚本 ↓ 让 Synopsys License 服务依赖路由修复服务最终实现了以下功能同时正常使用:
- WSL2 Mirrored 网络模式;
- Windows 代理自动继承;
- Synopsys FlexNet License;
- Verdi、VCS 等 Synopsys EDA 工具。
