一场由 Cursor Remote 引发的生产服务器卡死:从 I/O 阻塞到根因定位
这次事故最麻烦的地方不是服务器卡死本身而是它留下的表象几乎都指向磁盘。生产服务器先后出现两次严重卡顿。故障发生时接口超时、数据库连接失败、Docker 命令迟迟不返回连 SSH 都很难登录。重启后所有服务又恢复正常磁盘检查也没有发现硬件错误。如果只看故障末期很容易得出“云磁盘性能不够”或者“数据库把磁盘打满了”的结论。但最后定位到的触发源既不是数据库也不是业务容器而是一组运行在宿主机上的 Cursor Remote 进程。有人连接服务器时把/当成了远程工作区Cursor 的 Extension Host、File Watcher 和 Agent Worker 开始面对整台服务器的文件系统工作。它们的内存不断增长在一台 16 GB、没有 Swap 的机器上最终把系统拖进了页面回收和磁盘读取风暴。下面记录完整的排查过程。文中的服务器地址、账号和业务名称都已脱敏时间统一使用 UTC需要换算北京时间时加 8 小时。故障现象所有服务一起变慢第一次故障恢复后我们最初怀疑的是某个业务任务瞬间放大了数据库压力。因为当时能看到的现象包括PostgreSQL 和 MongoDB 响应异常Docker 命令超时应用接口大量超时SSH 连接困难重启服务器后立即恢复。几天后问题再次出现而且症状几乎相同。第二次事故发生后我们没有立即把重点放到某个应用日志上而是先回答一个更基础的问题服务器到底在等什么CPU 使用率高并不一定代表计算繁忙。如果大量 CPU 时间落在 I/O Wait说明处理器本身没有工作而是在等磁盘完成请求。通过sar查看历史 CPU 数据后故障高峰的 I/O Wait 一度达到约 84%。对于一台只有 2 vCPU 的机器系统负载却上升到 3585同时有 2078 个任务处于阻塞状态。这一组数据说明卡顿的直接表现是磁盘 I/O 阻塞而不是普通的 CPU 计算瓶颈。sar-usar-q磁盘确实被打满了但这还不是根因继续查看块设备历史数据OS Disk 在故障期出现了非常明显的饱和读取吞吐约 129 MB/s磁盘队列深度约 180405平均等待时间约 193527 msCPU I/O Wait 超过 80%。sar-d-p如果停在这里结论很可能是“磁盘规格不够”。但磁盘繁忙只说明有大量读写请求无法解释这些请求为什么突然出现。尤其这次主要是读而不是持续写入。数据库批处理、日志爆量和备份任务通常会留下比较明显的写入特征这与现场数据并不完全一致。于是排查方向从“谁在读磁盘”前移了一层系统为什么需要在短时间内重新读取这么多数据真正的转折匿名内存从 5 GB 涨到 15 GBsar -r ALL保留了故障前完整的内存变化。第二次事故中宿主机匿名内存出现了一条非常规律的上升曲线09:20 kbanonpg ≈ 5.12 GB 09:30 kbanonpg ≈ 6.07 GB 10:30 kbanonpg ≈ 8.22 GB 11:30 kbanonpg ≈ 10.80 GB 12:30 kbanonpg ≈ 13.17 GB 13:20 kbanonpg ≈ 15.09 GB服务器总内存约 16 GB而且当时没有配置任何 Swap。随着匿名内存上涨系统可回收的文件缓存和 Slab 不断下降可用内存最终只剩几百 MB。sar-rALLfree-m这解释了为什么最终表现为磁盘读满。匿名内存无法被直接丢弃又没有 Swap 可以换出内核只能尽可能回收 Page Cache。业务进程随后再次访问刚被回收的文件页时只能从磁盘重新读取。内存越紧张缓存回收越激进缓存越少重新读盘越频繁最终形成页面回收、Major Page Fault 和磁盘读取相互放大的恶性循环。系统日志里也反复出现了对应信号systemd-journald: Under memory pressure, flushing caches.到这里可以确定严重 I/O 阻塞是内存耗尽之后的结果。接下来真正要找的是谁制造了这 10 GB 左右的匿名内存。先排除 Docker容器总内存不升反降生产服务基本都运行在 Docker 中因此最先检查的是各容器内存。我们部署了一个轻量黑匣子周期性保存docker stats、容器 PID 映射和pidstat输出。把 Docker 数据与sar时间线对齐后结果与最初预期相反。在宿主机匿名内存从约 5.12 GB 增长到 15.09 GB 的同一时段16 个容器的内存总量从约 4.86 GB 降到了 4.50 GB09:00 全部容器约 4.86 GB 09:30 全部容器约 4.87 GB 11:00 全部容器约 4.76 GB 12:00 全部容器约 4.63 GB 13:20 全部容器约 4.50 GB业务 API、Elasticsearch、PostgreSQL 和 MongoDB 都没有出现与宿主机内存曲线相匹配的增长。Celery Worker 曾在另一个时间点短暂达到约 1.99 GB这确实是需要治理的资源风险但它发生得更早随后已经回落无法解释后面持续增加的 10 GB 匿名内存。因此 Celery 不是这次事故的直接触发源。这一步排除了整个容器层。问题进程一定运行在宿主机上。从宿主机进程中找到 Cursor Remote服务器重启后历史进程的 RSS 已经消失原来的黑匣子又只记录了pidstat -d没有记录进程内存。因此无法直接回看“哪个 PID 占了多少 GB”。我们只能把剩余证据按时间重新拼起来从sar找到匿名内存开始增长的分钟从 Docker 数据证明增长不在容器内从宿主机持久日志查找同一时间启动的进程用pidstat验证这些进程当时是否持续读盘。在宿主机进程列表中除了 Azure Agent 和 Docker 守护进程还存在一组位于用户目录下的 Node.js 进程~/.cursor-server/.../server-main.js ~/.cursor-server/.../bootstrap-fork --typefileWatcher ~/.cursor-server/.../bootstrap-fork --typeextensionHost这就是 Cursor 通过 Remote SSH 连接 Linux 服务器时安装的远程组件。Remote Server 负责连接和文件访问Extension Host 运行远程扩展File Watcher 监听工作区文件变化Agent Worker 为 Cursor Agent 提供远程工作区能力。真正关键的证据来自 Cursor 自己的日志。Cursor 把整台服务器当成了工作区第二次事故中Cursor Remote 会话在 09:21 启动09:21:34 Extension host agent started 09:21:37 Launched Extension Host Process 2757769 09:21:40 File Watcher: Permission denied (path: /) 09:21:53 [cursor-agent-worker] Workspace roots: /匿名内存在 09:20 时还保持在约 5.12 GB09:30 已经升到约 6.07 GB之后一路增长到 15 GB。进程启动时间与内存曲线的起点几乎完全重合。问题就出在这行日志Workspace roots: /远程工作区不是某个代码目录而是 Linux 根目录/。这意味着 Cursor 的文件监听和扩展宿主面对的是整台服务器包括/etc、/var、/home、/proc、/sys以及/var/lib/docker下的大量容器数据。从日志看Cursor Grep 因为/不是 Git 仓库而初始化失败代码索引 Watcher 也没有成功建立所以不能简单地把责任归给某一个“代码索引扩展”。真正持续存在的是 Extension Host、Universal File Watcher 和 Agent Worker 这一组进程。Agent Worker 每隔一段时间都会再次记录Workspace roots: /File Watcher 则持续尝试处理根文件系统。pidstat也记录到了对应 PID 的磁盘活动Extension Host PID 2757769 平均读取约 4.27 MB/s 峰值约 18.7 MB/s 另一个 Cursor Node 进程 PID 2757576 平均读取约 4.79 MB/s 峰值约 15.7 MB/s在系统进入抖动后Cursor 日志开始连续出现客户端重连。由于 Remote Server 为断线客户端保留数小时的重连窗口即使本地 Cursor 窗口已经关闭远端进程也不一定立即退出。更早的日志还留下了一条直接证据Cursor Extension Host 曾经在这台服务器上发生过 V8 Heap OOM。FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory第二条时间线验证不是一次偶然巧合只靠一次时间重合还不够。我们重新检查了第一次事故的sar和 Cursor 日志。第一次事故中匿名内存在 00:50 时约为 5.14 GB。Cursor Agent Worker 于 00:57 启动并记录Workspace roots: /01:00 匿名内存升到约 5.83 GB之后持续增长04:50 达到约 15.16 GB服务器随即进入严重阻塞。00:50 匿名内存约 5.14 GB 00:57 Cursor 工作区根目录确认为 / 01:00 匿名内存约 5.83 GB 04:50 匿名内存约 15.16 GB两次事故具有相同的起点、相同的增长曲线和相同的最终表现Cursor Remote 打开/后宿主机匿名内存开始线性增长直到机器进入内存压力和 I/O 风暴。这使根因证据从“相关性”变成了可重复的共同模式。完整故障链最终还原出的过程如下Cursor Remote 将 / 作为工作区 ↓ Extension Host、File Watcher、Agent Worker 处理整台文件系统 ↓ 宿主机 Cursor Node 进程匿名内存持续增长 ↓ 16 GB 内存耗尽且没有 Swap ↓ 内核大量回收 Page Cache 和其他可回收页面 ↓ 业务进程产生 Major Page Fault反复从 OS Disk 重新读取 ↓ 磁盘吞吐、队列深度和延迟达到上限 ↓ Docker、数据库、SSH 和 journald 一起阻塞这里需要区分三个概念直接根因Cursor Remote 错误地将/作为工作区引发宿主机进程无边界增长放大因素服务器只有 16 GB 内存、没有 Swap、宿主机进程没有内存限制故障表现OS Disk 饱和、数据库超时、Docker 无响应和 SSH 失联。如果只处理磁盘或数据库只能暂时缓解症状无法阻止问题再次发生。处理方案1. 生产服务器不再使用 Cursor Remote最直接的处理是停止在生产环境通过 Cursor Remote 开发。普通 SSH、SCP、SSH 隧道和只读诊断脚本不会启动.cursor-server进程可以继续使用。如果确实需要远程编辑也必须只打开明确的项目目录绝不能选择/、/home、/var或/var/lib/docker。关闭本地 Cursor 后还要确认服务器没有遗留进程ps-ef|grep/.cursor-server/|grep-vgrep2. 增加 4 GB Swap 作为缓冲我们在 Azure 临时资源盘/mnt上增加了 4 GB Swap并将vm.swappiness设置为 10swapon--showfree-hsysctlvm.swappiness最终状态为Swap: 4.0 GiB当前使用 0 B vm.swappiness 10Swap 不是根因修复。它的作用是在未来再次发生异常内存增长时为运维登录、告警和进程终止留出时间避免机器直接进入不可操作状态。Azure 临时资源盘可能在 Stop/Deallocate 后清空因此同时配置了 cloud-init per-boot 脚本在启动时自动重建 Swap。3. 改进黑匣子原来的黑匣子记录了每进程 I/O却没有记录 RSS导致重启后无法直接看到历史内存责任进程。后续采集至少应包括pidstat-r-dps-eopid,ppid,rss,vsz,etime,comm,args--sort-rssdockerstats --no-stream每条记录都需要时间戳同时保存 PID、PPID、完整命令行和 cgroup/容器映射。采集命令本身要设置超时避免系统已经卡顿时监控进程反过来增加负担。4. 增加资源边界开发工具不应该和生产业务共享无限制的宿主机资源。即使以后偶尔需要远程工具也应使用独立账号或 systemd slice为其配置MemoryHigh和MemoryMax。业务容器同样需要逐步增加内存限制。虽然它们不是这次事故的根因但 Celery Worker 出现过接近 2 GB 的峰值没有边界的容器仍然可能制造下一次内存事故。这次排查留下的几个经验第一不要把最后出现的指标当成最初原因。磁盘队列和延迟确实很高但这次磁盘只是替内存问题“背锅”。从 I/O 阻塞继续向前追直到解释请求为什么产生才找到了真正的触发源。第二容器化环境不能只看容器。宿主机上的编辑器、监控 Agent、运维脚本和远程扩展都可能消耗大量资源。容器总内存稳定是这次排查最重要的转折点。第三重启会消除最有价值的进程现场。服务器恢复后仍然可以依靠sysstat、持久日志和时间线完成定位但如果黑匣子提前记录 RSS、命令行和 cgroup整个过程会简单很多。最后生产服务器不是远程开发机。将/作为 IDE 工作区看起来只是一次路径选择错误实际却把整个操作系统、Docker 数据目录和运行时文件都交给了文件监听与扩展系统。在资源充足的开发机上这可能只表现为编辑器变慢在一台没有 Swap、同时承载数据库和业务容器的生产服务器上它足以拖死整台机器。

相关新闻

绿的谐波们,望向万里之外的一家工厂

绿的谐波们,望向万里之外的一家工厂

导语:绿的谐波们的业绩,与马斯克能否兑现承诺息息相关。加州弗里蒙特与浙江杭州,两者的直线距离超一万公里。不过,在即将到来的具身智能时代,这两地极有可能会因一款产品而产生紧密的联动。目前,特斯拉弗里…

2026/10/18 8:11:35 阅读更多 →
AI 应用不是接个模型就完事:Java 后端必须补上的 8 个工程能力

AI 应用不是接个模型就完事:Java 后端必须补上的 8 个工程能力

摘要:模型调用只是入口,真正上线要补日志、Trace、权限、限流、降级、成本、评测和灰度。 这篇文章不按概念百科写,而是从 Java 后端和企业 AI 应用落地角度,拆清楚它解决的问题、真实场景、架构边界、代码建模、常见坑和上线检查…

2026/10/18 8:11:41 阅读更多 →
YOLOv11改进 | 主干/Backbone篇 | 大核心卷积UniRepLknet目标检测网络(适配yolov11全系列轻量化)

YOLOv11改进 | 主干/Backbone篇 | 大核心卷积UniRepLknet目标检测网络(适配yolov11全系列轻量化)

开始讲解之前推荐一下我的专栏,本专栏的内容支持(分类、检测、分割、追踪、关键点检测),专栏目前为限时折扣,欢迎大家订阅本专栏,本专栏每周更新3-5篇最新机制,更有包含我所有改进的文件和交流群提供给大家。 一、本文介绍 本文给大家带来的改进机制是特征提取网络UniRep…

2026/10/17 21:38:02 阅读更多 →

最新新闻

open-code-review:用规则引擎驱动高效代码审查的实践指南

open-code-review:用规则引擎驱动高效代码审查的实践指南

很多团队对代码审查(code review)的态度,长期处于“知道很重要,但就是做不好”的状态。我也一样,在经历了若干个项目、数不清的review讨论之后,才意识到问题根本不在于大家愿不愿意review,而是缺…

2026/10/19 21:44:57 阅读更多 →
Cesium for UE4坐标系转换全解析:从经纬高到虚幻世界坐标

Cesium for UE4坐标系转换全解析:从经纬高到虚幻世界坐标

1. 从经纬度到虚幻单位:Cesium for UE4 坐标系到底在折腾什么如果你刚把 Cesium for UE4 插件拖进引擎,兴冲冲地加载了一块真实地形,结果发现相机飞到了十万八千里外,或者模型像被揉皱的纸团一样扭曲,那大概率不是插件…

2026/10/19 21:43:55 阅读更多 →
open-code-review:构建人机协作的高效代码审查体系

open-code-review:构建人机协作的高效代码审查体系

1. 为什么代码审查总是形同虚设——open-code-review想解决的真实问题1.1 代码审查在工程实践中的尴尬现状我在一线做研发和带团队的时间加起来超过十年,换过几家公司,也看过不少代码评审流程从制定到瓦解的全过程。几乎所有团队在创业初期都说要做代码审…

2026/10/19 21:41:53 阅读更多 →
DVWA暴力破解四个级别详解:从无防护到账户锁定的攻防演进

DVWA暴力破解四个级别详解:从无防护到账户锁定的攻防演进

1. 从一次登录框测试说起:暴力破解到底在破什么很多人第一次接触DVWA的暴力破解模块,注意力都放在“怎么把密码跑出来”上,结果跑通一次之后,脑子里留下的只有Burp的Intruder界面和一堆字典文件,换个环境就不知道从哪下…

2026/10/19 21:40:51 阅读更多 →
如何做好开放式Code Review:一套可落地的团队评审实践

如何做好开放式Code Review:一套可落地的团队评审实践

1. 为什么我坚持把 Code Review 做成“开放式”的先聊点实在的。我做了十几年开发,带过团队,也经历过各种规模的评审流程,从两个人结对互相看代码,到几十人团队的正式评审会议,都试过。一个特别明显的感受是&#xff1…

2026/10/19 21:39:49 阅读更多 →
WinForms DataGridView下拉框动态绑定与联动实战

WinForms DataGridView下拉框动态绑定与联动实战

简介:本资源是一份面向C#初学者与Windows桌面开发者的实用代码实践包,聚焦解决DataGridView控件中动态集成下拉列表(ComboBox)这一高频交互需求,适用于数据录入界面、配置管理模块等实际业务场景。压缩包共22个文件&am…

2026/10/19 21:39:49 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →