我的树莓派 Pi Zero 2 W 偶尔 SSH 连不上。症状是 raspberrypi.local 无响应。
第一反应:DHCP 挂了?
结论:不是。
真正的凶手
SSH 进去翻 NetworkManager 日志:
journalctl -u NetworkManager --no-pager -n 150关键时间线:
23:01:01 dhcp4: state changed new lease, address=192.168.1.167 ← DHCP 正常23:07:20 supplicant: completed -> disconnected ← WiFi 突然断开23:07:22 supplicant: 4way_handshake 开始 ← 尝试重连23:07:32 supplicant: 4way_handshake -> disconnected ← 10秒超时!23:07:32 "no secrets: No agents were available for this request"23:07:32 "Activation: failed for connection 'preconfigured'"真相不是 DHCP 的问题。是 WPA 4-way handshake 超时。
WiFi 断开后尝试重连,WPA 握手花了 10 秒超时。然后 NetworkManager 觉得需要用户重新输入密码——但这是一台无头的树莓派,没有”用户”可以输入任何东西。
于是 NM 直接放弃了。而且不会自动重试。
我的 Pi 因此离线了 整整 9 天,直到我手动重启。
信号本身也不太行
$ cat /proc/net/wirelesswlan0: quality=53 signal=-57dBm retry=139-57 dBm 不算强,139 次 retry 说明链路抖动频繁。Pi Zero 2 W 的 BCM43430 芯片本来就不是什么高端货。
修复 Pi:三板斧
1. NM 无限重试
sudo nmcli connection modify preconfigured connection.autoconnect-retries 0默认只重试 4 次就放弃。设为 0 = 永不放弃。
2. 关闭 WiFi 省电
sudo nmcli connection modify preconfigured wifi.powersave 2省电模式是很多树莓派 WiFi 断连的元凶。
3. Watchdog 定时器
写了个脚本,每 5 分钟 ping 一下网关,不通就重启 NetworkManager:
#!/bin/bashset -euo pipefailGATEWAY=$(ip route | grep default | awk '{print $3}')if ! ping -c 3 -W 5 "$GATEWAY" > /dev/null 2>&1; then logger -t wifi-watchdog "Gateway unreachable, restarting NM" systemctl restart NetworkManagerfi用 systemd timer 每 5 分钟跑一次。最坏情况下 5 分钟自动恢复,不再出现 9 天失联。
顺手搭个 AP
Pi 旁边有一台斐讯 N1 刷了 OpenWrt,通过网线连着主路由器。WiFi 卡(BCM43455)闲着没用。
想法很简单:让 N1 当 WiFi AP,Pi 连它,信号好了 DHCP 自然也稳了。
然后就掉进了坑里。
坑 1:hostapd 根本没装
改好 /etc/config/wireless,满心欢喜重启 WiFi:
./mac80211.sh: eval: line 575: /usr/sbin/hostapd: not foundDevice setup failed: HOSTAPD_START_FAILEDAP 模式需要 hostapd。这台机器只有 hostapd-common(配置文件),没有二进制文件。
TIPOpenWrt 的 WiFi AP 模式依赖 hostapd 守护进程。如果你的固件是精简版,可能需要手动安装。
坑 2:opkg 仓库已死
$ opkg update*** Failed to download the package list from http://downloads.openwrt.org/snapshots/packages/...这是 2022 年 12 月的 flippy 定制 SNAPSHOT 构建。官方 snapshot 仓库早就滚动更新了,旧的包列表不存在了。
解决:手动指向 OpenWrt 22.03.7 的 archive 仓库,这是最接近的 release 版本。
坑 3:opkg 拒绝安装
cannot find dependency libnl-tiny1 for hostapd-basic-opensslincompatible with the architectures configuredflippy 构建的 libnl-tiny 包名叫 libnl-tiny2022-11-01,而官方 release 的依赖写的是 libnl-tiny1。名字不一样,opkg 就认为找不到依赖。
加 --force-depends --nodeps 也没用——opkg 还有一层架构校验直接拒绝。
解决:暴力拆包。ipk 本质上就是个 ar 归档:
ar x hostapd-basic-openssl.ipktar xzf data.tar.gz -C /手动把二进制文件解压到系统目录。
坑 4:动态库版本不匹配
Error loading shared library libubox.so.20220515: No such file or directoryhostapd 编译时链接的是 libubox.so.20220515,系统上的是 libubox.so.20220927。
解决:一个符号链接搞定:
ln -sf /lib/libubox.so.20220927 /lib/libubox.so.20220515终于:
$ /usr/sbin/hostapd -vhostapd v2.10坑 5:netifd 不认这个 hostapd
以为装好 hostapd 就行了?OpenWrt 的 netifd 通过 mac80211.sh 启动 hostapd 时,会用 ubus 接口通信。但我们手动安装的 hostapd 编译时没有启用 ubus 支持。
Command failed: Request timed outCommand failed: Not foundDevice setup failed: HOSTAPD_START_FAILED直接手动运行却完全正常:
$ /usr/sbin/hostapd -d /tmp/test.confwlan0: interface state HT_SCAN->ENABLEDwlan0: AP-ENABLED解决:绕过 netifd,写自己的 init.d 服务直接启动 hostapd。在 uci 里把 radio 设为 disabled,让 netifd 不要插手。
坑 6:Pi 只支持 2.4GHz
最初配的是 5GHz channel 36 VHT80,信号好带宽大。
AP 启动了。Pi 扫不到。
因为 Pi Zero 2 W 的 BCM43430 只支持 2.4GHz。
改配置,切 2.4GHz,重启。
坑 7:HT40 不支持 SHORT-GI-40
Driver does not support configured HT capability [SHORT-GI-40]wlan0: Unable to setup interface.BCM43455 在 2.4GHz 模式下不支持 Short GI 40MHz。而且因为周围有一堆邻居的 WiFi,HT40 也自动降级成了 HT20。
最终的 hostapd 配置极其朴素:
driver=nl80211interface=wlan0bridge=br-lanssid=Fios-4DCwD-IoThw_mode=gchannel=1ieee80211n=1ht_capab=[HT40+][SHORT-GI-20]country_code=USwpa=2wpa_key_mgmt=WPA-PSKwpa_pairwise=CCMP最终效果
Pi 连上 OpenWrt AP 后:
| 指标 | 之前(主路由器) | 之后(OpenWrt AP) |
|---|---|---|
| 信号强度 | -55 dBm | -32 dBm |
| WiFi retry | 230 | 0 |
| 扫描信号 | 61% | 100% |
锁定 BSSID 防止 Pi 漫游到主路由器的同名 SSID:
sudo nmcli connection modify 'Fios-4DCwD-IoT' \ 802-11-wireless.bssid FC:7C:02:91:3E:B3踩坑总结
| # | 表象 | 真因 |
|---|---|---|
| 0 | DHCP 失败 | WPA 握手超时 + NM 不重试 |
| 1 | AP 启动失败 | hostapd 二进制缺失 |
| 2 | 装不了包 | SNAPSHOT 仓库已滚动更新 |
| 3 | opkg 拒绝 | flippy 与官方 release 的依赖命名不同 |
| 4 | hostapd 崩溃 | libubox 版本号不匹配 |
| 5 | netifd 调不动 | hostapd 无 ubus 支持 |
| 6 | Pi 扫不到 AP | BCM43430 只支持 2.4GHz |
| 7 | 2.4GHz 也失败 | SHORT-GI-40 不支持 |
一个”DHCP 有时候失败”的问题,最后变成了七层嵌套的排查链。
经验
- 无头设备一定要设
autoconnect-retries 0和关闭 WiFi 省电 (或者你的wifi信号好也行)- flippy/自定义 OpenWrt 构建的包管理基本是残废的,做好手动拆包的心理准备
- 先查目标设备支持什么频段再配 AP。