最近在部署 OpenWrt 旁路由时,遇到网络间歇性断开、日志大量报错:
socket: too many open files
fcntl: too many open files
network is unreachable
packet loss
经排查发现,核心问题是 ShellCrash 启动的 CrashCore 进程文件描述符上限过低,导致 TCP/UDP 透明代理在连接暴涨时触发 EMFILE 错误。
问题分析
- CrashCore 默认
Max open files为 4096(见/proc/<PID>/limits)。 - 当旁路由作为全网网关,UDP/TUN/QUIC 连接较多时,很容易超过上限。
- 日志中大量的 UDP、IPv6 失败提示,表明连接数高峰期 FD 耗尽。
修复
修改 /etc/init.d/shellcrash 启动脚本,增加 procd limits 参数:
- 打开启动脚本:
vi /etc/init.d/shellcrash
- 在
start_service()中找到procd_open_instance区块:
procd_open_instance
procd_set_param user $USER
procd_set_param respawn
procd_set_param command $COMMAND
procd_set_param stderr 0
procd_set_param stdout 0
procd_close_instance
- 增加
nofile限制:
procd_open_instance
procd_set_param user $USER
procd_set_param respawn
procd_set_param limits nofile="1048576 1048576"
procd_set_param command $COMMAND
procd_set_param stderr 0
procd_set_param stdout 0
procd_close_instance
- 在
start_service()下方开头加ulimit -n 1048576,双保险。 - 重启服务:
/etc/init.d/shellcrash restart
- 验证:
PID=$(pidof CrashCore)
cat /proc/$PID/limits | grep "open files"
输出应为:
Max open files 1048576 1048576 files
补充建议
- 如果旁路由不使用 IPv6,可以在 CrashCore 配置中关闭 IPv6,减少 FD 压力。
- UDP/TUN/QUIC 透明代理在高连接数场景下容易暴涨,可以考虑暂时关闭或限速。
- 持续观察日志,确保不再出现
too many open files。
结论:
通过提升 CrashCore 文件描述符上限,并合理配置网络协议,成功解决了旁路由断网问题。OpenWrt 下使用 procd 启动的服务,需要通过 procd_set_param limits 指定资源上限,而不仅仅依赖 ulimit。