<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Troubleshooting on 魔都水滴</title>
    <link>https://blog.margrop.net/tag/troubleshooting/</link>
    <description>Recent content in Troubleshooting on 魔都水滴</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-CN</language>
    <lastBuildDate>Wed, 29 Jul 2026 20:30:00 +0800</lastBuildDate>
    <atom:link href="https://blog.margrop.net/tag/troubleshooting/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>电脑从不“突然坏掉”：看懂日志，十分钟学会像侦探一样排障</title>
      <link>https://blog.margrop.net/post/%E7%9C%8B%E6%97%A5%E5%BF%97-log-reading-art/</link>
      <pubDate>Wed, 29 Jul 2026 20:30:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/%E7%9C%8B%E6%97%A5%E5%BF%97-log-reading-art/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;电脑很少会“毫无征兆地坏掉”。大多数时候，它早就把线索写进了日志：某个磁盘逐渐变满、某个服务先出现警告、某次 DNS 查询失败、某个进程反复启动又退出。真正的排障，不是看到红色报错就马上重装系统，而是像侦探一样回答五个问题：&lt;strong&gt;什么时候发生？谁发生了？严重程度怎样？前后还发生了什么？修好后能不能验证？&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这篇文章不把日志讲成只有工程师才懂的黑话，而是把它比作电脑每天写的日记。你会看到 Windows 11、Ubuntu 26.04 和 macOS 26 的真实采集输出，拿到三套不依赖第三方服务的只读脚本，还能把同一套思路交给 Agent 自动执行。即使你是小学生，也应该能看懂其中大部分；如果你是开发者或运维人员，则可以直接把方法带回生产环境。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>重启不是玄学：电脑为什么一关一开，就像治好了 99% 的毛病？</title>
      <link>https://blog.margrop.net/post/why-restart-fixes-99-percent-%E9%87%8D%E5%90%AF/</link>
      <pubDate>Wed, 29 Jul 2026 08:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/why-restart-fixes-99-percent-%E9%87%8D%E5%90%AF/</guid>
      <description>先说结论&#xA;重启不是魔法，也不是把所有故障都修好了。它更像是把一间住了很久、已经乱到找不到东西的房间清空：借出去但没归还的物品被收走，排队的人重新取号，临时便签被撕掉，门锁和电器重新检查。系统因此回到了一个更干净、更容易预测的起点。&#xA;所以，“重启解决了问题”通常意味着：故障藏在易失状态里，而不是硬件已经坏掉、配置一直错误或程序本身存在根因。&#xA;你一定见过这样的场景：浏览器突然打不开新标签页，文件明明存在却提示“正在使用”，远程桌面连不上，风扇像小飞机一样转，内存还剩很多却不停卡顿。你先关一个窗口，再关几个程序，最后抱着“试试看”的心态重启。&#xA;电脑重新亮起来后，刚才那个很难解释的毛病消失了。&#xA;这就是大家常说的“重启能解决 99% 的问题”。它当然不是一个经过严格统计的 99%，而是一种非常生动的工程经验：很多问题不是永久损坏，而是系统在长时间运行中积累了太多没有及时清理的临时状态。&#xA;图 1：重启像把“住乱了”的系统清场复位。原创配图。&#xA;把电脑想成一间一直有人使用的房间 刚搬进去时，房间很整齐。桌上只有一台电脑，柜子里有几份文件，门口有两双鞋。&#xA;但如果这间房连续住三个月，却从来不做大扫除，会发生什么？&#xA;快递盒越来越多，虽然每个盒子都不大，但过道被堵住了。 借出去的剪刀、充电器和钥匙没有归还，东西并没有“消失”，只是没人知道它在哪里。 门口排着很多人，已经离开的客人还占着号码。 桌上贴满旧便签，大家仍然按照过期的便签做决定。 两个人各自拿着一把钥匙，互相等对方先开门，谁都不愿意松手。 系统里的“房间”就是内存、文件句柄、网络连接、线程、锁、缓存、驱动状态和各种服务上下文。它们有一个共同特点：启动时会被建立，运行中会被修改，退出或重启时才有机会统一回收。&#xA;下面这张图把最常见的四种“乱”放在了一起。&#xA;图 2：状态泄漏、内存碎片、连接堆积，以及锁和旧缓存，是重启经常能缓解的四类问题。&#xA;状态泄漏：借出去的东西没有放回原位 “泄漏”不一定是水从水管里流出来。对程序来说，泄漏更像是“借了资源，但忘了归还”。&#xA;程序打开一个文件，系统会给它一个文件描述符；程序创建一个网络连接，系统会保存连接状态；程序申请一块内存，分配器会记住这块空间归谁使用。如果程序退出时没有正确关闭，或者它一直运行、从来不退出，那么这些资源就可能持续占着位置。&#xA;一次泄漏可能小得几乎看不见。比如每处理一千个请求只多留一个句柄，一天之后可能没有任何感觉；几周之后，系统却开始提示“打开文件太多”“无法创建线程”或“连接失败”。&#xA;这就是为什么重启一个服务有时比“再点一次按钮”有效：服务进程结束后，操作系统会回收该进程名下的内存、句柄、线程和连接。房间里那些没有登记归还的物品，会随着住客离开而被物业统一收走。&#xA;macOS 的 vm_stat 会把虚拟内存拆成很多页来观察；Linux 则常见 /proc/meminfo、free 和进程的 RSS。它们不是“电脑健康分数”，而是帮助我们确认房间里到底堆了什么。&#xA;图 3：真实的 macOS vm_stat 输出。数字会随机器和时间变化，重点是观察趋势，不是迷信某个固定值。&#xA;内存碎片：柜子还有缝，却塞不进大箱子 很多人看到“可用内存还有几 GB”，就会问：既然还有空间，为什么程序还是申请失败？&#xA;因为“总空位”不等于“连续的大空位”。&#xA;把内存想成一个有很多格子的柜子。程序先放入一个小盒子，又拿走另一个盒子，再放入一个大箱子。经过很多次申请和释放以后，柜子可能到处都有小缝，但没有一块连续的空位能放下大箱子。&#xA;这就是内存碎片最容易理解的版本。真实系统比这个复杂：用户态分配器、内核页分配器、不同大小的对象、内存映射和缓存都会影响布局。现代操作系统会尽力复用和整理空间，但整理本身也需要时间，并且并非所有内存都能随便移动。&#xA;图 4：蓝色格子表示已占用区域，浅色格子是分散的空位；“还有空位”并不代表能满足连续大块分配。&#xA;Linux 内核文档把 compaction（内存压缩整理）描述为把可移动页搬到一起，从而形成更大的连续空闲区域。这个过程像把衣柜里的小衣物先集中到一侧，让另一侧腾出完整空间，但它不是免费的：搬东西需要 CPU，也受不可移动页、正在使用的页和分配时机影响。&#xA;因此，重启有时会让内存表现“突然变好”，并不是重启凭空创造了内存，而是旧进程、旧映射和旧缓存全部结束后，新的进程在更干净的布局上重新分配。&#xA;图 5：真实的 Ubuntu free -h 与 ss -s 汇总。文章只保留统计项，不展示地址或机器名。&#xA;连接堆积：窗口有限，旧号码却没清掉 网络连接可以想成银行窗口。&#xA;服务器只有有限数量的连接槽位、文件描述符、线程和端口。一个请求来了，系统为它分配资源；请求结束后，资源应当尽快归还。但实际网络里还有重传、超时、半关闭、连接复用和 TIME-WAIT 等状态。某些状态本来就是协议设计的一部分，不是错误；问题在于它们的数量、持续时间和业务流量不匹配。&#xA;RFC 9293 说明了 TCP 状态机中的 TIME-WAIT：主动关闭连接的一方需要在一段时间内保留状态，以避免旧报文干扰后续连接。生活中，这就像快递柜不会在包裹刚取走的一秒钟就立刻把编号交给另一个人，系统要留一点时间确认“旧包裹真的结束了”。</description>
    </item>
    <item>
      <title>把一台慢成蜗牛的 Docker 镜像代理从 5 分 14 秒干到 0.6 秒:我踩过的三个坑和一段 5 行的 cron</title>
      <link>https://blog.margrop.net/post/docker-registry-mirror-rebuild-2026/</link>
      <pubDate>Sat, 13 Jun 2026 07:20:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/docker-registry-mirror-rebuild-2026/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;我在家里的自建小集群上跑着一个 &lt;code&gt;registry:2&lt;/code&gt; 的 pull-through 代理,平时给局域网里的几台机器和 NAS 当 Docker Hub 镜像源用,用了快两年一直挺稳。&lt;strong&gt;直到有一天,它拉一个 5MB 的 alpine 镜像要 5 分 14 秒。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这篇文章记录我&lt;strong&gt;怎么查到根因&lt;/strong&gt;、&lt;strong&gt;换了哪些方案&lt;/strong&gt;、&lt;strong&gt;为什么每一版都没让我满意&lt;/strong&gt;、&lt;strong&gt;最后怎么用一个 5 行的 bash 脚本 + 每天一次的 cron 把它彻底稳下来&lt;/strong&gt;。整个排查过程 100% 是我在自己的机器上跑出来的真实数据,不是我抄 README、不是我看博客道听途说。&lt;/p&gt;&#xA;&lt;p&gt;关键决策点都贴了实测数据。如果你也在自建 docker 镜像代理,或者你公司的 devops 团队在维护一个内部 registry 镜像,文末的 Q&amp;amp;A 段能帮你省掉至少 3 小时的踩坑。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>VPN 连上了，内网域名却死活访问不了？一次 macOS 路由表排查完整复盘</title>
      <link>https://blog.margrop.net/post/macos-routing-table-vpn-troubleshooting/</link>
      <pubDate>Mon, 01 Jun 2026 18:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/macos-routing-table-vpn-troubleshooting/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;一句话总结：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;macOS 上同时跑了两个 VPN（&lt;code&gt;utun0&lt;/code&gt;、&lt;code&gt;utun15&lt;/code&gt;），其中 &lt;code&gt;utun0&lt;/code&gt; 推送了一条 &lt;code&gt;10.0.0.0/8&lt;/code&gt; 的聚合路由，把目标 &lt;code&gt;10.x.x.x&lt;/code&gt; 全部&amp;quot;吃&amp;quot;掉了——而我真正想走的是 &lt;code&gt;utun15&lt;/code&gt; 对端的内网。DNS 能解析，TCP/ICMP 就是不通。&lt;strong&gt;&lt;code&gt;route -n get&lt;/code&gt; 是定位这类问题的第一把刀&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>一次 tmux &#43; opencode 中文变下划线的排障：不是字体坏了，而是 client_utf8=0</title>
      <link>https://blog.margrop.net/post/tmux-opencode-chinese-underscore-fix/</link>
      <pubDate>Tue, 28 Apr 2026 18:40:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/tmux-opencode-chinese-underscore-fix/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这次问题不是 opencode 不支持中文，也不是终端字体突然坏了，而是 tmux 当前 client 被判定为“不支持 UTF-8”。证据是 &lt;code&gt;tmux display-message -p &#39;client_utf8=#{client_utf8}&#39;&lt;/code&gt; 返回了 &lt;code&gt;client_utf8=0&lt;/code&gt;。在这种状态下，tmux 会把非 ASCII 字符替换成下划线，所以中文在 opencode 的 TUI 里看起来就像全部变成了 &lt;code&gt;_&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;这篇文章记录一次很小、但很典型的终端排障：同一台 Mac 上，直接运行 &lt;code&gt;opencode&lt;/code&gt; 时中文显示正常；先进入 tmux，再运行 &lt;code&gt;opencode&lt;/code&gt;，中文就全部变成下划线。&lt;/p&gt;&#xA;&lt;p&gt;这种问题非常容易误判。第一反应通常是怀疑字体、终端模拟器、opencode 版本、主题、Nerd Font、宽字符宽度，甚至怀疑是不是某个 TUI 框架把 CJK 字符处理坏了。但这次真正的关键点只有一个：&lt;strong&gt;tmux 自己是否愿意把 UTF-8 字符写回外层终端。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;为了不泄露任何私人环境信息，下面的命令输出都做了抽象化处理，不包含真实主机名、内网地址、会话名、密钥、账号或项目路径。保留的只有与问题本身有关的技术事实。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
