米米的博客

做了一点微小的工作

我在一台阿里云轻量云服务器上部署了 VS Code Server,用于远程开发。这台服务器配置为 2 核 CPU + 2GB 内存,我额外添加了 8GB 的 swap,希望应对 VS Code Server 启动后的内存压力。然而,在实际使用中,每次通过 SSH 启动 VS Code Server 后不久,服务器就会失去响应,SSH 连接中断,必须强制重启机器。

起初我怀疑是内存不足或 swap 设置不当导致的系统崩溃,但深入排查之后,发现真正的问题其实来自系统对 inotify 监听器数量的限制。通过调整 fs.inotify.max_user_watches 参数,问题得以彻底解决。

下面是我的排查过程与最终的解决方案。

初步怀疑:内存不足和 swap 设置

由于 VS Code Server 启动时会拉起大量语言服务器、插件和文件监听器,在初次遇到 SSH 连接中断后,我第一时间怀疑是内存不足导致的。通过 dmesgfree -h 查看系统日志和内存状态,发现 VS Code Server 启动后确实存在内存紧张的情况。

我尝试通过增加 swap 空间到 8GB 来缓解压力,具体做法可以参考之前的文章Linux 下增加、删除 Swap 文件。然而,问题依旧没有解决。SSH 连接依然在 VS Code 启动后不久被挂起,系统无法及时响应新连接,甚至无法正常关机。

进一步调查:监控进程和系统调用

我观察到在 VS Code Server 启动后,nodetsserver 进程数量迅速上升,内存占用随之增高,同时系统 I / O 等待时间变得非常长。用 vmstatps 工具查看系统状态时,也看到了频繁的文件访问和上下文切换。

这让我开始怀疑是否是文件系统监听器数量过多导致系统资源耗尽。VS Code 和许多语言服务器会使用 inotify 机制监听文件变化,用于自动刷新和提示功能。而 Linux 对每个用户可以创建的 inotify 监听器数量是有限制的。

找到真正的问题:inotify 限制过低

通过查看 /proc/sys/fs/inotify/max_user_watches,我发现默认值仅为 8192。这对于一个包含多个项目文件夹和自动索引的开发环境来说,远远不够。

一旦监听器数量超限,VS Code Server 中的插件和语言服务器就会频繁尝试重新监听文件,占用大量资源,最终导致系统进入无法响应的状态。这也解释了为什么增加 swap 并没有改善情况:问题其实不是内存不足本身。

解决方案:提高 max_user_watches 限额

确定问题之后,我通过以下方式修改了系统配置:

首先临时调整参数:

1
sudo sysctl fs.inotify.max_user_watches=65536

然后将其写入配置文件以永久生效:

1
2
echo fs.inotify.max_user_watches=65536 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

重启服务器后再次连接 VS Code Server,问题彻底消失。无论打开多少项目或运行多少扩展,服务器都能够稳定运行,系统资源使用保持正常。

总结

云服务器内存有限时运行 VS Code Server,常见的建议是增加 swap、限制语言服务器内存或禁用部分扩展。然而,如果系统在 VS Code 启动后迅速失去响应,除了内存问题,还应特别注意 inotify 的限制。

在我遇到的案例中,虽然最初误以为是内存瓶颈,最终发现是 fs.inotify.max_user_watches 太低导致的资源耗尽。只需简单提升监听器上限,就能让 VS Code Server 在低配服务器上运行得更加稳定流畅。

如果你也在远程开发中遇到类似问题,不妨检查一下这个关键参数。

本文将介绍在 OpenWrt 路由器上托管清华校园网认证的 LuCI 插件 luci-app-auth-thu。该插件的底层由 GoAuthing 实现登录与保活,而 LuCI 界面则负责提供下载核心、配置、查看日志等操作。

背景与定位

清华校园网采用了 srun4k 门户进行准入认证。在将 OpenWrt 接入校园网时,为了方便在设备断电或重启后自动登录并保持在线,可以使用 GoAuthing 这个命令行工具。GoAuthing 提供了适用于 OpenWrt 的 init 脚本,且可以通过 UCI 读取校园网账号配置。其发布页长期维护了多体系结构的预编译二进制,也非常方便在各类路由器设备上使用。但是,GoAuthing 的安装配置和命令行界面都需要较高的学习成本,因此一个图形化的前端界面可以大幅简化用户的操作流程,提升用户体验。

LuCI 插件

luci-app-auth-thu 的目标是让 GoAuthing 在 OpenWrt 上更加易用。提供的核心功能包括:

  1. 自动下载 GoAuthing 核心,包含自动识别 CPU 架构、从 GitHub 获取最新版本号、模板变量替换与多源回退;
  2. Web 界面配置与开关服务,实时显示运行状态与核心版本;
  3. 账户与密码写入 UCI,保持 Router 侧独立在线;
  4. 运行日志可视化。在「日志」页面中,自动调用 logread 展示相关日志。

如何部署

  1. 在路由器装好 luci-app-auth-thu 插件后,先在「基础设置」填入校园网账户与密码,开启服务,确认状态正常;
  2. 如果你没有 GoAuthing 核心,直接用「下载核心」按钮:插件会识别架构、拉取最新版本号,并按配置的多源地址顺序尝试;
  3. 观察「日志」页面,确认登录成功、保活正常;之后若 WAN 断开重连,触发器会自动 reload 服务。

最近,笔者家中的一辆 2015 款奔驰 CLA200 汽车出现了「辅助蓄电池故障」的警告。咨询 4S 店后得知,这一故障是因为辅助蓄电池电压不足导致,通常是损坏了,需要更换。CLA200 的辅助蓄电池是一个单独的小电瓶,更换过程较为复杂。由于 4S 店报价较高,且电瓶没有现货需要等待预定,因此笔者决定自己动手更换。

辅助蓄电池故障警告

购买辅助蓄电池

通过咨询多家淘宝上售卖相关电瓶配件的店铺,得知需要更换的电瓶外观如下所示。这款电瓶售价普遍在 200 多元。笔者挑选了一家看上去比较靠谱的店铺进行购买,但是也没有很好的办法验证真伪,毕竟这个电瓶看上去就很容易用旧的翻新。只能希望不要出现安全隐患。

辅助蓄电池外观

更换过程

与其它一些奔驰汽车不同,CLA200 的辅助蓄电池位于副驾驶的脚底,而不是后备箱中。在更换时,需要先将副驾驶侧的地垫揭开。

揭开地垫

这时,地垫下面的情况就很清楚了,左上角部分的塑料保护盖下方就是辅助蓄电池,还可以看到两侧的接线端子。

辅助蓄电池位置

阅读全文 »

AdGuard Home 是一个自托管的广告拦截器,旨在 DNS 层面通过拦截跟踪域名和广告域名来提升用户隐私和网络体验。它可以运行在本地网络的网关或旁路由上,无需在每个终端设备上单独安装插件。AdGuard Home 提供了多个平台的二进制文件和安装指引,方便用户部署。

OpenWrt 默认的软件源提供了 AdGuard Home 的软件包,用户可以通过 opkg 安装。但是,要提升使用体验,还需要配合防火墙等设置。为了让 AdGuard Home 更好地融入 OpenWrt 的生态,社区开发了 LuCI 插件来提供图形化界面。

插件的发展历史

最早由 rufengsuixing 开发的 luci-app-adguardhome,在 LuCI 界面中实现了安装 / 更新核心、端口与重定向策略、日志查看、YAML 配置编辑、计划任务等选项,可一键进行部署。这一版本在 2020 年后停止了更新。
随后,社区分支由 kongfl888 延续维护,功能框架基本一致,持续发版至 2022 年,方便了众多固件集成打包。

我的 fork

我在 kongfl888 的基础上继续了 luci-app-adguardhome 的开发,主要聚焦以下改进:

  1. 兼容性与可视化
    将「重定向 53 端口」的功能直接通过系统防火墙进行配置,对 fw4 / nftables 友好,并可以支持 IPv6 重定向;更新界面布局、提示,让运行状态与问题原因更直观。

  2. 配置与运维体验
    将诸多的配置选项按照功能分页展示,默认配置更加精简和清晰;把「系统升级保留文件」的表单重构为更优雅的动态列表并兼容旧配置格式;清理历史遗留代码并进行重构。

  3. 账号与日志
    完善 Web 口令变更流程与提示,避免误操作;统一临时文件命名与读取游标;在 YAML 配置校验失败时给出更清晰的错误信息,便于排错。

目前在我的仓库 README 中,对上述功能与组合使用方式(例如与 OpenClash/代理类插件并用时的上游/重定向关系)也做了集中说明,并提供可直接安装的发布包。欢迎使用:stevenjoezhang/luci-app-adguardhome

笔者近期在 OpenWrt 路由器上配置了 Cloudflare IP 优选工具 luci-app-cloudflarespeedtest,但是在使用过程中发现还是有一些影响体验的小问题没有解决。由于原仓库已经被作者归档并只读,因此我 fork 了该项目,并在此基础上做了一些改进。
本文将介绍该工具的背景、功能以及我在 fork 版本上做的修改。我的仓库地址是:stevenjoezhang/luci-app-cloudflarespeedtest

CloudflareSpeedTest 是什么

CloudflareSpeedTest 的目标很直接:在 Cloudflare 公布的大量 IP 里,自动测试延迟与下载速度,筛出最适合当前网络的 IP(支持 IPv4/IPv6)。项目 README 也强调了「自选优选 IP」的定位:先测延迟/丢包,再做实际下载测速,最终输出可二次处理的结果列表,方便用脚本或其它工具继续接管。一种典型的应用场景是,配合 DNS 服务器或代理出站工具(如 SSR+、Passwall 等),检测到要访问的网站是托管在 Cloudflare 上的,就自动切换到最快的出口 IP。这样,就可以实现对相关网站访问的加速。

原版 LuCI 插件

mingxiaoyu/luci-app-cloudflarespeedtest 的功能是把上述测速流程放到 OpenWrt 路由器的 Web 界面(LuCI)里,支持可视化配置、Crontab 定时运行,并自动把优选 IP 回写到常见代理出站插件中等,以在 OpenWrt 上实现「按计划自动换最快出口」。该仓库已在 2024 年归档并只读,意味着作者不再维护。

我的 fork

我在原版停止维护后 fork 了一版,并围绕可视化、可用性、可维护性做了多处调整。下面对关键改动进行汇总说明。

体验与易用性

  • 展示图表 & 历史曲线:加入历史数据图表,将延迟 / 速度曲线以子图形式展现,便于对比多次测速的趋势与稳定性。
  • 状态与日志更清晰:优化状态展示与日志格式,告警 / 进度更直观,便于排错。
  • 界面细节优化:统一风格、更新按钮模板,减少表单噪音。
  • 核心下载支持:加入自动下载核心二进制的功能,减少依赖,方便直接以 ipk 软件包形式安装,降低首次部署门槛,让「开箱即用」更顺滑。

配置与参数

  • 参数名称规范化:对 speedhour 等参数进行重命名,使其更加贴近实际含义,避免混淆。
  • 选项梳理与文案更新:优化选项组织结构与默认值;改进多语言翻译与 README。

工程与维护

  • 依赖与结构:更新依赖、理顺目录与引用路径,方便二次开发与打包发布;同时优化基于 GitHub Actions 的 CI workflow,保证可重复构建。

结语

如果你已经在用 OpenWrt 做出站路由,不妨把 fork 版的 luci-app-cloudflarespeedtest 装起来跑一跑 —— 历史曲线、速度阈值与更清晰的日志,相信能帮你更快地找到更快更稳定的那一个 Cloudflare IP。

0%