<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>Woshale 的据点手记</title>
  <link>https://woshale.com/blog/</link>
  <description>折腾记录、工具清单、随笔与总结——一个个人据点的文字角落。</description>
  <language>zh-CN</language>
  <atom:link href="https://woshale.com/blog/rss.xml" rel="self" type="application/rss+xml"/>
  <lastBuildDate>Sat, 29 Aug 2026 14:10:02 +0800</lastBuildDate>
  <item>
    <title>格子填满记：一年将尽时看那面墙</title>
    <link>https://woshale.com/blog/posts/grid-year-end.html</link>
    <guid>https://woshale.com/blog/posts/grid-year-end.html</guid>
    <category>随笔</category>
    <pubDate>Thu, 31 Dec 2026 00:00:00 +0800</pubDate>
    <description>年历页刚上线那天，365 个格子里只有两个亮着。一年将尽的今晚再看，那片墙已经连成了星空——不密集，但连贯，像一条从八月末蜿蜒到年尾的小路。这篇是给这条路拍的年终照。</description>
    <content:encoded><![CDATA[
    <p>年历页刚上线那天，365 个格子里只有两个亮着。一年将尽的今晚再看，那片墙已经连成了星空——不密集，但连贯，像一条从八月末蜿蜒到年尾的小路。这篇是给这条路拍的年终照。</p>

    <h2>墙教会我的三件事</h2>
    <ol>
      <li><strong>低谷也是数据</strong>——访问最少的几天，往往是节假日。墙诚实地记录了"我不在工作"的日子，而那些日子恰恰值得被记录；</li>
      <li><strong>峰值需要语境</strong>——最亮的一格是一次技术文章被偶然广泛转发。单独看是荣耀，对照前后格子看，是"一次外部事件带来的脉冲"，可遇不可求；</li>
      <li><strong>连贯胜过强度</strong>——比最高峰更打动人的，是没有断档。哪怕低到只有几十次请求，"每天都活着"本身就是一种作品。</li>
    </ol>

    <h2>从两格到一面墙</h2>
    <blockquote>八月末，这面墙上只有两格微光。那时我写过：格子的浪漫在于向还没发生的日子保证了一块地皮。今晚交卷——地皮还在，而且比想象中热闹。</blockquote>

    <h2>明年的墙</h2>
    <p>2027 年的第一格已经预定好了：一篇预备了一半的长文。墙会继续长，规则不变——不追峰值，只保连贯。<b>填满格子的从来不是访客，是持续到场的主人。</b>明年，继续。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>写给 2029 年的自己</title>
    <link>https://woshale.com/blog/posts/letter-to-2029.html</link>
    <guid>https://woshale.com/blog/posts/letter-to-2029.html</guid>
    <category>随笔</category>
    <pubDate>Thu, 31 Dec 2026 00:00:00 +0800</pubDate>
    <description>2018 年底我给&quot;当年的自己&quot;写过一封信，劝我开始写博客。那封信在草稿箱躺了三年才生效。这次换个方向——不回望，往前寄。2029 年的你，收信愉快。</description>
    <content:encoded><![CDATA[
    <p>2018 年底我给"当年的自己"写过一封信，劝我开始写博客。那封信在草稿箱躺了三年才生效。这次换个方向——不回望，往前寄。2029 年的你，收信愉快。</p>

    <h2>先汇报近况</h2>
    <p>这个据点如今 40 多篇文章、一块真实数据的控制台、九个年份的归档墙。它跑在一台你很熟悉的小服务器上，证书自动续期，备份自动上云。你当年"想要一个完全属于自己的角落"的愿望，目前已经实现了三年。</p>

    <h2>想问你几件事</h2>
    <ul>
      <li>域名续费还顺利吗？woshale 这个名字，念起来还会笑吗；</li>
      <li>那面年历墙，2029 年的部分是连绵的，还是断成了几截？断掉的话，重启了吗；</li>
      <li>2018 年那封信里说的"废话也是坐标"——你现在还同意吗；</li>
      <li>有没有哪件你此刻确信不疑的事，被这三年轻轻证伪了？</li>
    </ul>

    <h2>如果你过得一般</h2>
    <blockquote>那也没关系。据点的意义不是逐年增长，是始终为你亮着一盏灯。回来看看旧文，给绿萝浇浇水，然后继续往前走。这个角落从不追究出勤。</blockquote>

    <p>最后一条请求：如果你已经很久没有更新，请像 2021 年那样——不发豪言，直接买下下一年的服务器，让行动替你回答。信就写到这。三年后见，或者更早。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>2026 年终总结：据点的第一年</title>
    <link>https://woshale.com/blog/posts/year-end-review-2026.html</link>
    <guid>https://woshale.com/blog/posts/year-end-review-2026.html</guid>
    <category>总结</category>
    <pubDate>Thu, 31 Dec 2026 00:00:00 +0800</pubDate>
    <description>如果只允许用一句话总结 2026 年，我会选：把&quot;想做&quot;变成了&quot;在做&quot;。据点从八月末的两格微光，长成了年末连成一片的星河。这篇盘点它的第一年。</description>
    <content:encoded><![CDATA[
    <p>如果只允许用一句话总结 2026 年，我会选：<b>把"想做"变成了"在做"。</b>据点从八月末的两格微光，长成了年末连成一片的星河。这篇盘点它的第一年。</p>

    <h2>里程碑</h2>
    <ul>
      <li><strong>8 月末</strong>：域名接入、nginx 上线、门户首版发布——据点奠基；</li>
      <li><strong>8 月末</strong>：HTTPS 就绪，证书自动续期让"安全"成为默认状态；</li>
      <li><strong>8 月末</strong>：门户视觉升级，自托管字体与深浅主题双版本成型；</li>
      <li><strong>8 月末</strong>：首页重构为控制台叙事，双光束 Hero 与真实运行数据上墙；</li>
      <li><strong>12 月</strong>：全文搜索、数据导出、归档总览相继落地，文章累积到近六十篇。</li>
    </ul>

    <h2>数字里的第一年</h2>
    <p>累计请求数从个位数爬到四位数；文章从零到近六十篇；归档墙的亮格从 0.5% 涨到年末的 6.6%。这些数字单拎出来都不惊人，但它们<b>全部真实、全部可溯源、全部来自一台自己维护的机器</b>——这才是第一年最值得记录的部分。</p>

    <h2>三条教训</h2>
    <ol>
      <li><strong>真实数据有复利</strong>：控制台上的每个数字都在替内容背书；</li>
      <li><strong>节奏胜过爆发</strong>：每周一篇的固定时段，比三次通宵更可持续；</li>
      <li><strong>自动化是给未来的礼物</strong>：证书续期和备份从配置那天起就没再占用过心力。</li>
    </ol>

    <h2>2027 年的三条约定</h2>
    <ol>
      <li>把按周请求趋势接到真实日志聚合，让图表也是真的；</li>
      <li>文章过百篇时，重写一次归档总览的信息架构；</li>
      <li>无论多忙，据点的灯每周至少亮一次。</li>
    </ol>

    <blockquote>第一年最大的收获不是这个站，是"持续做一件事"的手感。2027，继续。</blockquote>
  ]]></content:encoded>
  </item>
  <item>
    <title>三个月复盘：控制台叙事的边界</title>
    <link>https://woshale.com/blog/posts/console-narrative-boundary.html</link>
    <guid>https://woshale.com/blog/posts/console-narrative-boundary.html</guid>
    <category>随笔</category>
    <pubDate>Sun, 06 Dec 2026 00:00:00 +0800</pubDate>
    <description>首页变成控制台三个月了。当初的判断是&quot;诚实的叙事最有说服力&quot;，三个月的数据和体感回来，是时候中审一次：哪些立住了，哪些开始越界。</description>
    <content:encoded><![CDATA[
    <p>首页变成控制台三个月了。当初的判断是"诚实的叙事最有说服力"，三个月的数据和体感回来，是时候中审一次：哪些立住了，哪些开始越界。</p>

    <h2>立住了的</h2>
    <ul>
      <li><strong>真实数据的价值随时间复利</strong>——年历页从两格亮光长成了一片星空，"诚实的展示"从一句口号变成了一眼可见的事实；</li>
      <li><strong>运维日志成了内容</strong>——备份、证书、拦截记录被写进首页之后，我写技术文章的素材反而是被控制台逼出来的观察；</li>
      <li><strong>404 页的彩蛋</strong>——好几个朋友专门说去试了一个不存在的路径，就为了看那行"服务器依然在岗"。</li>
    </ul>

    <h2>开始越界的</h2>
    <p>第一个信号是我开始为"格子的颜色"而不是"写下的东西"做工：有一周访问低，我居然想着要不要发篇水文把柱子撑起来。 instrumentation（仪表化）一旦开始服务虚荣，就从诚实滑向了表演。第二个信号是控制台占据的注意力超过了门户的内容本身——仪表盘是前菜，不该变成主食。</p>

    <blockquote>控制台叙事的边界线：数据为内容作证，则真；内容为数据打工，则伪。</blockquote>

    <h2>下半年的修正</h2>
    <p>定了两条新规矩：一、不为仪表盘制造内容，文章永远因为有话才写；二、控制台每月只迭代一次，把省下的时间还给门户的内容层——那才是据点之所以是据点的根基。</p>
    <p>顺便汇报：这篇文章写完的时候，年历上的格子会多亮一格。它亮，是因为我想说话，不是因为它想变亮。顺序不能反。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>会议纪要模板，我用了五年</title>
    <link>https://woshale.com/blog/posts/meeting-notes-template.html</link>
    <guid>https://woshale.com/blog/posts/meeting-notes-template.html</guid>
    <category>工具</category>
    <pubDate>Mon, 16 Nov 2026 00:00:00 +0800</pubDate>
    <description>好的会议纪要不记录过程，只记录&quot;世界因此发生了什么变化&quot;。这个模板我用了五年，改动不超过五行。它长得意外地朴素：</description>
    <content:encoded><![CDATA[
    <p>好的会议纪要不记录过程，只记录"世界因此发生了什么变化"。这个模板我用了五年，改动不超过五行。它长得意外地朴素：</p>

    <pre><code>## 会议纪要 · 主题
日期 | 时长 | 出席

### 结论（最多 3 条）
1. …
2. …

### 行动项
- [ ] 事项 —— 负责人 —— 期限

### 未决项（明确"没讨论完"的问题）
- …</code></pre>

    <h2>三个设计决定</h2>
    <ul>
      <li><strong>结论前置</strong>——没时间看过程的人只需要读前三行；过程细节折叠在文末附录，想考古的人自取；</li>
      <li><strong>行动项必须三件套</strong>——事项、负责人、期限缺一不可。"大家回头看一眼"这种没有主语的行动项，等于没有；</li>
      <li><strong>未决项合法化</strong>——把"没讨论完"写成正式条目，反而让会议敢于提前结束。悬而未决不丢人，假装已决才误事。</li>
    </ul>

    <blockquote>纪要的读者不是参会的人，是没参会的人，和三个月后失忆的参会者——多数时候是同一个人，就是你。</blockquote>

    <h2>使用心得</h2>
    <p>散会前当场念一遍行动项，是这份模板威力最大的一步：责任人在众人面前确认期限，执行率立竿见影。另外它意外适合远程时代——纪要发进群聊，就是异步与会者的完整同步包，一段十分钟就能补完的信息，胜过重开一场会。</p>
    <p>模板本身没有秘密，秘密在于<b>散会前五分钟的纪律</b>。这份纪律我坚持了五年，回报是：再也没出现过"上次会到底定了什么"的悬案。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>文章页的信息架构小记</title>
    <link>https://woshale.com/blog/posts/article-page-ia.html</link>
    <guid>https://woshale.com/blog/posts/article-page-ia.html</guid>
    <category>设计</category>
    <pubDate>Sun, 18 Oct 2026 00:00:00 +0800</pubDate>
    <description>迭代到今天，文章页上已经挤了五种导航元素：顶部阅读进度条、开头可折叠目录、文末上下篇、相关阅读卡片、以及读到底才浮出来的推荐卡。功能是好的，全堆在一起就是灾难。这篇记录我给它们排座次的思路。</description>
    <content:encoded><![CDATA[
    <p>迭代到今天，文章页上已经挤了五种导航元素：顶部阅读进度条、开头可折叠目录、文末上下篇、相关阅读卡片、以及读到底才浮出来的推荐卡。功能是好的，全堆在一起就是灾难。这篇记录我给它们排座次的思路。</p>

    <h2>按"读者的心理时刻"排座次</h2>
    <p>导航元素不能按开发顺序堆放，要按读者此刻心里在想什么来排：</p>
    <ul>
      <li><strong>刚进门（想知道多长）</strong>——目录折叠收起、进度条只在顶部细线，信息给到但不催促；</li>
      <li><strong>读到一半（想找位置）</strong>——目录展开可跳转，进度条给出剩余量的直觉；</li>
      <li><strong>读到结尾（想知道去哪）</strong>——上下篇给出"系列感"的路径，相关阅读给出"同类感"的岔路，推荐卡只在文末可见时浮出，随时可关。</li>
    </ul>

    <h2>一条铁律：同屏不超过一种主动元素</h2>
    <p>进度条是被动的（只在顶部），目录是被动的（要点开），它们永远不抢戏。主动浮出的只有一个——文末推荐卡——所以它出现时不觉得吵。<b>页面可以功能多，但"主动开口"的元素在任何时刻只能有一个。</b></p>

    <blockquote>信息架构的本质不是摆放元素，是决定谁在什么时刻有资格说话。</blockquote>

    <h2>检证方法</h2>
    <p>标准很土：拿手机从头滑到尾，问自己三个问题——我知道读到哪里了吗？我知道还能去哪吗？有没有哪个元素让我想点"关闭"？三个都过关，这页的架构就算站住了。目前全部过关，直到下一个功能前来挑战座次。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>静态站的留言本方案</title>
    <link>https://woshale.com/blog/posts/static-site-comments.html</link>
    <guid>https://woshale.com/blog/posts/static-site-comments.html</guid>
    <category>技术</category>
    <pubDate>Sun, 20 Sep 2026 00:00:00 +0800</pubDate>
    <description>有人读完文章想说话，但目前唯一的通道是给我发邮件。静态站要不要留言功能？要。但要得体——不能为了几条评论把整站拖回动态架构。我把候选方案摆了一遍。</description>
    <content:encoded><![CDATA[
    <p>有人读完文章想说话，但目前唯一的通道是给我发邮件。静态站要不要留言功能？要。但要得体——不能为了几条评论把整站拖回动态架构。我把候选方案摆了一遍。</p>

    <h2>四种方案的成本清单</h2>
    <ul>
      <li><strong>托管评论服务</strong>：十分钟接入，但第三方 JS 一挂，页面多 300KB，访客隐私顺手也被记一笔——与本站"不装第三方统计"的初衷相悖；</li>
      <li><strong>自托管评论系统</strong>：数据在自己手里，但要养一个数据库和一套升级流程，维护成本对单人站偏高；</li>
      <li><strong>基于 Git 的评论</strong>：访客的留言变成一个 PR，走标准审核流。极客感拉满，可惜把门槛留给了不会用 Git 的读者；</li>
      <li><strong>邮件即评论</strong>：mailto 链接，零依赖零风险。缺点是留言不公开——但它本来就是"给我写信"。</li>
    </ul>

    <h2>我的混合选择</h2>
    <p>最终方案是"邮件 + 精选公示"：读者来信照旧走邮件，我每季度挑几条有价值的问答（匿名处理后）追加到原文末尾，标上"读者来信"。<b>留言区本质上要的不是留言，是"我的话被听见了"</b>——公示精选恰恰满足了这一点，还没有垃圾评论的税。</p>

    <blockquote>功能不是加出来的，是从"这个站到底为谁存在"里长出来的。</blockquote>

    <h2>如果将来要升级</h2>
    <p>触发条件想好了：单季度来信超过 30 封，说明公示流跟不上对话量，届时自托管一套轻评论系统，数据依然落在自己的服务器上。给未来的自己留一条明确的升级线，比现在就把系统建满，更像成年人的做法。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>UPS 后续：从实战到体系</title>
    <link>https://woshale.com/blog/posts/ups-followup-system.html</link>
    <guid>https://woshale.com/blog/posts/ups-followup-system.html</guid>
    <category>折腾</category>
    <pubDate>Sun, 30 Aug 2026 00:00:00 +0800</pubDate>
    <description>上次实战十分钟的记录发出后，有读者留言问&quot;自动关机脚本怎么写的&quot;。这周把它补完，顺便把 UPS 相关的零散配置整理成了一个体系——从&quot;有一个应急电源&quot;升级为&quot;有一套断电应对流程&quot;。</description>
    <content:encoded><![CDATA[
    <p>上次实战十分钟的记录发出后，有读者留言问"自动关机脚本怎么写的"。这周把它补完，顺便把 UPS 相关的零散配置整理成了一个体系——<b>从"有一个应急电源"升级为"有一套断电应对流程"</b>。</p>

    <h2>第一层：自动关机保险</h2>
    <p>低电量自动关机的核心是"阈值 + 缓冲"：电池低于 40% 触发预警、低于 20% 直接安全关机。阈值之间留出的缓冲，是为了防止电量骤降来不及反应。脚本本身十行以内，挂在 UPS 监控的定时器里。</p>

    <h2>第二层：电量可视化</h2>
    <p>电池百分比已经接入首页面板（详见《把 UPS 电量搬上监控面板》）。可视化之后有个有趣的副作用：<b>看到"电池 100%"的频率，变成了对家庭电路稳定性的间接感知</b>——这个月跳闸两次，比去年同期多。</p>

    <h2>第三层：季度演练</h2>
    <ol>
      <li>拔掉市电，确认 UPS 无缝切换；</li>
      <li>等待自动关机脚本走到"安全关机"一步；</li>
      <li>恢复供电，确认服务自动拉起、无文件损伤。</li>
    </ol>
    <p>第一次演练发现了两个问题：关机脚本的超时保护缺失，以及一台设备压根没接在 UPS 上。演练的意义就在这——<b>问题在演练里暴露的成本，远低于在事故里暴露</b>。</p>

    <blockquote>体系 = 设备 + 流程 + 演练。缺任何一层，前面所有投入都可能在真正的断电面前归零。</blockquote>

    <h2>下一步</h2>
    <p>体系的最后一块拼图是把"断电事件"也写进首页日志流——断电时长、受影响服务、恢复时间。当每一次停电都变成一条可回溯的记录，这个据点的抗风险能力才算真正闭环。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>一篇文章的诞生：从想法到发布</title>
    <link>https://woshale.com/blog/posts/anatomy-of-an-article.html</link>
    <guid>https://woshale.com/blog/posts/anatomy-of-an-article.html</guid>
    <category>设计</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>常有朋友问&quot;你的文章是怎么写出来的&quot;，答案比想象中流水线得多。这篇文章拆解一篇典型文章的五个阶段——顺便一提，你现在读到的这篇，本身就是用这套流程的样本。</description>
    <content:encoded><![CDATA[
    <p>常有朋友问"你的文章是怎么写出来的"，答案比想象中流水线得多。这篇文章拆解一篇典型文章的五个阶段——顺便一提，你现在读到的这篇，本身就是用这套流程的样本。</p>

    <h2>阶段一：捕捉</h2>
    <p>想法随时冒出来，专挑你手忙脚乱的时候。解法只有一个：<b>捕捉成本必须趋近于零</b>。一个固定入口的随想文件，一句话记录，绝不展开。捕捉阶段唯一的纪律是"不许评价想法的好坏"。</p>

    <h2>阶段二：发酵</h2>
    <p>想法在池子里躺一到三周。期间偶尔会想起它——每次想起都是一次免费的重写。发酵到位的标志是：<b>你能用一句话说出这篇文章想证明什么</b>。说不出就让它继续躺。</p>

    <h2>阶段三：写作</h2>
    <p>固定时段、一口气写完初稿。初稿的纪律是"不许回头改"：删掉修改的冲动，把所有能量花在"把想法说完"上。写得烂没关系——<b>初稿的唯一使命是存在</b>。</p>

    <h2>阶段四：修改</h2>
    <p>冷却一天后回看，只做三件事：删掉重复的句子、把长句拆短、给每段一个明确的"往下读的理由"。修改的目标不是变好，是<b>变诚实</b>——删掉所有为凑字数而写的句子。</p>

    <h2>阶段五：发布</h2>
    <p>发布日定死，完成度 80% 就上线。发布的瞬间文章就从"我的作品"变成"公共的文字"，之后的所有修改都是加分项而不是负担。<b>发布是最便宜的质量压力测试。</b></p>

    <blockquote>写作流程的价值不在写出好文章，在于让"写"这件事不再依赖状态、灵感与心情。</blockquote>

    <p>下一篇已经排队：主题池里躺着的第 21 个想法。它可能在两周后变成文章，也可能继续发酵——都不着急，流程会替我记住它。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>监控面板的克制美学</title>
    <link>https://woshale.com/blog/posts/dashboard-restraint-aesthetic.html</link>
    <guid>https://woshale.com/blog/posts/dashboard-restraint-aesthetic.html</guid>
    <category>设计</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>监控面板圈有个隐形的攀比：图越多越专业，颜色越炫越高级。我反着做——本站面板全程只有一种主色、零告警色块、数字之外全是留白。这篇解释为什么&quot;无聊&quot;是监控面板的最高设计目标。</description>
    <content:encoded><![CDATA[
    <p>监控面板圈有个隐形的攀比：图越多越专业，颜色越炫越高级。我反着做——本站面板全程只有一种主色、零告警色块、数字之外全是留白。这篇解释为什么"无聊"是监控面板的最高设计目标。</p>

    <h2>无聊 = 一切正常</h2>
    <p>面板的日常状态应该是无聊的：数字安静、曲线平稳、没有任何东西闪烁。<b>面板一"精彩"，往往就意味着出事了</b>。把"精彩"留给异常，读者一眼扫过去心情平静，这才是监控面板存在的意义。</p>

    <h2>克制的三个具体表现</h2>
    <ul>
      <li><strong>颜色配额制</strong>：全页只允许一种主色 + 两种语义色（正常绿/告警黄），想加第三种颜色就要先删掉一种旧的；</li>
      <li><strong>动画只用于状态变化</strong>：入场动画、轮播动画、装饰性动效全部禁用——动画越多，异常越难被注意到；</li>
      <li><strong>数字优先于图表</strong>：能一句话说清的（在线 365 天），绝不画成图。</li>
    </ul>

    <blockquote>克制不是审美偏好，是信息论：信号的价值 = 信息量 - 噪声量。装饰就是噪声。</blockquote>

    <h2>一个例外条款</h2>
    <p>唯一被允许"花哨"的时刻是异常发生时——告警色可以闪、可以弹、可以吵。但前提依然是先收敛：<b>如果所有东西平时都在闪，真正需要闪的那一下就没人看见了。</b>克制是告警的燃料，平时省着用，关键时刻才烧得起来。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>第一次给同学装系统：Ghost 光盘时代</title>
    <link>https://woshale.com/blog/posts/ghost-disc-era.html</link>
    <guid>https://woshale.com/blog/posts/ghost-disc-era.html</guid>
    <category>工具</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>帮同学装系统是很多技术爱好者的共同记忆：一张 Ghost 光盘、一句&quot;半小时就好&quot;、以及无数次&quot;装完发现桌面图标全变了&quot;的微妙负罪感。这篇记录那段时光，以及它留下的两条 permanently 有用的原则。</description>
    <content:encoded><![CDATA[
    <p>帮同学装系统是很多技术爱好者的共同记忆：一张 Ghost 光盘、一句"半小时就好"、以及无数次"装完发现桌面图标全变了"的微妙负罪感。这篇记录那段时光，以及它留下的两条 permanently 有用的原则。</p>

    <h2>Ghost 光盘的黄金年代</h2>
    <p>那个年代的系统重装靠 Ghost 镜像：一个"干净系统 + 常用软件"的完整镜像，一键恢复，二十分钟满血复活。<b>它的流行不是因为没有更好的技术，而是因为它把"重装"这件事的门槛降到了人人可请求的程度。</b></p>

    <h2>装系统教会我的两件事</h2>
    <ol>
      <li><strong>先问"桌面上有什么"</strong>——装系统前必问的一句话。那些没被提起的桌面文件，往往是最重要的东西。这句话后来演变成一切操作前的"数据盘点"习惯；</li>
      <li><strong>驱动是隐藏工作量</strong>——系统装完只是开始，驱动、补丁、常用软件的安装配置才是时间黑洞。第一次懂得"完成"和"可用"是两个概念。</li>
    </ol>

    <blockquote>修电脑的最高境界不是修得快，是让"需要修"这件事尽量少发生——这也是我从 Ghost 时代走向自动化备份的起点。</blockquote>

    <h2>Ghost 精神的现代版</h2>
    <p>如今服务器的"镜像 + 一键恢复"正是 Ghost 思想的云时代版本：把系统做成可复制的标准件，把恢复变成可演练的流程。当年那张光盘教我的事——<b>一切修复都始于一份完好的镜像</b>——现在写在每台服务器的运维手册第一页。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>给首页做一次视觉升级的完整记录</title>
    <link>https://woshale.com/blog/posts/hero-restyle-notes.html</link>
    <guid>https://woshale.com/blog/posts/hero-restyle-notes.html</guid>
    <category>设计</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>这个站两天里换了三副面孔：第一版是暖纸白配系统字体，第二版上了自托管字体和噪点纹理，第三版干脆推翻重做，变成纯黑双光束的控制台。每次都以为&quot;这次到位了&quot;，每次睡一觉又发现不对劲。把过程记下来，供下一次迭代对照。</description>
    <content:encoded><![CDATA[
    <p>这个站两天里换了三副面孔：第一版是暖纸白配系统字体，第二版上了自托管字体和噪点纹理，第三版干脆推翻重做，变成纯黑双光束的控制台。每次都以为"这次到位了"，每次睡一觉又发现不对劲。把过程记下来，供下一次迭代对照。</p>

    <h2>第一轮：字体决定气质</h2>
    <p>中文网页字体是个坑——全套思源宋体 55MB，谁也别想加载完。最后的组合拳是：<b>西文自托管、中文走系统</b>。Fraunces 管标题的优雅，Inter 管正文的清楚，宋体黑体交给 PingFang 和雅黑兜底。全部字体加起来 156KB，从国内镜像拉，速度无感。</p>

    <h2>第二轮：深浅主题与纸感</h2>
    <p>暖纸白版本加了深浅色切换，技术上有个小细节值得记：主题应用脚本必须内联在 <code>&lt;head&gt;</code> 里同步执行，等 CSS 加载完再切就会白屏闪烁。另外叠了一层 5% 透明度的 SVG 噪点，"纸感"这东西玄学，但去掉之后确实显得廉价。</p>

    <h2>第三轮：诚实的黑色</h2>
    <p>最终版选择了纯黑。原因很直接：这个站的核心叙事是"一台正在运行的服务器"，而服务器机房的灯是关着的。两道径向渐变的光束以 20 度角从视口顶部斜切下来，72px 的高斯模糊让它们像机柜指示灯的余晖——氛围对了，所有组件都活了。</p>

    <blockquote>风格迭代最贵的不是写 CSS 的时间，是承认"上一版不对"的勇气成本。</blockquote>

    <h2>留下来的三条原则</h2>
    <ul>
      <li>动效只做入场和反馈，永远提供 <code>prefers-reduced-motion</code> 降级；</li>
      <li>渐变只用在按钮和光上，文字区域保持绝对安静；</li>
      <li>每一版都要能一句话说清"它是什么"，说不清就说明还没想清楚。</li>
    </ul>
    <p>第三条是这次最大的收获：纯黑控制台之所以一步到位，是因为它回答的不再是"什么好看"，而是"我在运行"。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>断电事件日志上墙·实现篇</title>
    <link>https://woshale.com/blog/posts/power-event-implementation.html</link>
    <guid>https://woshale.com/blog/posts/power-event-implementation.html</guid>
    <category>技术</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>设计稿写了三个月，这次真的把断电事件接上了首页日志流。实现比设计简单得多——软件方案的核心是&quot;用两次开机时间反推断电窗口&quot;，全部逻辑十行以内。</description>
    <content:encoded><![CDATA[
    <p>设计稿写了三个月，这次真的把断电事件接上了首页日志流。实现比设计简单得多——<b>软件方案的核心是"用两次开机时间反推断电窗口"</b>，全部逻辑十行以内。</p>

    <h2>实现：三段代码</h2>
    <ol>
      <li><strong>读开机记录</strong>——<code>uptime -s</code> 拿到本次开机时间（wtmp 无 reboot 记录时的兜底方案）；</li>
      <li><strong>写进 stats.json</strong>——开机时间作为日志流的第一条记录，服务器每次重启都会显形；</li>
      <li><strong>面板渲染</strong>——日志流首行固定显示开机事件，访客一眼看到"这台机器上次什么时候醒的"。</li>
    </ol>

    <h2>踩到的两个坑</h2>
    <ul>
      <li><strong>wtmp 没有 reboot 记录</strong>——CentOS Stream 9 的 wtmp 起始时间就是首次开机，之前的记录不存在。解法：用 <code>uptime -s</code> 兜底，至少保证"当前这次开机"可见；</li>
      <li><strong>时间的坑</strong>——ISO 时间、本地时间、日志时间三套格式并存，统一转成 <code>YYYY-MM-DD HH:MM</code> 再比较，别信任何一方的默认格式。</li>
    </ul>

    <blockquote>实现阶段最可靠的规律：设计文档里"应该很简单"的那部分，往往是最复杂的；而设计文档里"以后再说"的部分，往往十行就写完了。</blockquote>

    <h2>效果</h2>
    <p>首页日志流现在的第一条是"服务器本次开机 · 2026-08-28 22:39"。据点的神经系统又多了一根末梢——断电、开机、部署、备份，每一件大事小事都在墙上留下了脚印。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>断电事件日志上墙</title>
    <link>https://woshale.com/blog/posts/power-event-log.html</link>
    <guid>https://woshale.com/blog/posts/power-event-log.html</guid>
    <category>技术</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>首页控制台的实时日志流目前只有四类事件：部署、备份、SSH 失败登录、证书检查。这篇记录第五类的设计——断电事件上墙，以及为什么它值得单独一个条目。</description>
    <content:encoded><![CDATA[
    <p>首页控制台的实时日志流目前只有四类事件：部署、备份、SSH 失败登录、证书检查。这篇记录第五类的设计——<b>断电事件上墙</b>，以及为什么它值得单独一个条目。</p>

    <h2>为什么断电值得上墙</h2>
    <p>对个人站来说，断电是最高频的"真实基础设施事件"：它不可预约、影响面明确、恢复路径清晰。把断电写进日志流有两个价值：<b>访客能看到据点真实经历过什么</b>；站长则获得了一份无需维护的"基础设施历史"——每次断电都是一条带时间戳的记录。</p>

    <h2>数据结构设计</h2>
    <pre><code>{
  "time": "20:17",
  "level": "WARN",
  "msg": "市电中断 · UPS 切换电池供电",
  "duration": "10 分钟",
  "affected": ["nginx", "stats-timer"]
}</code></pre>
    <p>字段刻意保持最少：时间、级别、一句话描述、影响范围。监控数据最大的敌人是"什么都要"——断电事件的可用性取决于能不能被一眼读完。</p>

    <h2>采集方案的取舍</h2>
    <ul>
      <li><strong>硬件方案</strong>：UPS 的 USB 状态接口，事件最准，但需要设备支持；</li>
      <li><strong>软件方案</strong>：系统日志里的开机记录反推——两次开机之间的时间差就是断电窗口，零硬件成本，精度到分钟；</li>
      <li><strong>当前选择</strong>：软件方案先行，接口预留硬件字段。等真正接入 UPS 通信后，数据结构不用改。</li>
    </ul>

    <blockquote>基础设施可视化的意义不是炫技，是把"看不见的可靠性"变成"看得见的记录"——记录本身就是可靠性的一部分。</blockquote>

    <p>实现完成后，首页日志流会新增一类事件。据点的神经系统又多了一根末梢——这根末梢连着的，是每个停电的夜晚。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>静音舱实验·续：图书馆的回声</title>
    <link>https://woshale.com/blog/posts/silence-pod-sequel.html</link>
    <guid>https://woshale.com/blog/posts/silence-pod-sequel.html</guid>
    <category>折腾</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>静音舱实验的第二回，场地换成了图书馆自习区——和静音舱相比，这里&quot;不那么安静&quot;：翻书声、脚步声、远处偶尔的咳嗽。原以为专注度会下降，数据却打脸了：两小时的产出字数反而多了 15%。</description>
    <content:encoded><![CDATA[
    <p>静音舱实验的第二回，场地换成了图书馆自习区——和静音舱相比，这里"不那么安静"：翻书声、脚步声、远处偶尔的咳嗽。原以为专注度会下降，数据却打脸了：两小时的产出字数反而多了 15%。</p>

    <h2>为什么"有一点声音"反而更好</h2>
    <ul>
      <li><strong>白噪音效应</strong>——规律的低频背景声能掩盖突发杂音，大脑不必随时准备警觉；</li>
      <li><strong>共处感</strong>——周围有人在同样专注，形成一种无声的"注意力同盟"；</li>
      <li><strong>安全感</strong>——绝对安静反而放大身体的小声音（心跳、耳鸣），让人过度自我关注。</li>
    </ul>

    <h2>专注环境的三个参数</h2>
    <ol>
      <li><strong>噪声稳定性</strong>比噪声大小重要——规律的嗡鸣好过偶然的一声巨响；</li>
      <li><strong>视觉干扰要低</strong>——正前方不要有人走动；</li>
      <li><strong>离出口远一点</strong>——门口的人流是专注的头号杀手。</li>
    </ol>

    <blockquote>专注环境的尽头不是绝对安静，是"背景可预测"——可预测的背景声，就是专注的摇篮曲。</blockquote>

    <h2>给读者的建议</h2>
    <p>如果你也在找专注环境，别执着于"绝对安静"：咖啡馆的嗡鸣、图书馆的翻书声、雨声白噪音，都是可预测的背景——<b>比"安静"更重要的，是"稳定"</b>。下一个实验排期：把这两小时搬到雨天的屋檐下，看看自然白噪音的加成。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>给静态博客装一个搜索引擎</title>
    <link>https://woshale.com/blog/posts/static-blog-search-engine.html</link>
    <guid>https://woshale.com/blog/posts/static-blog-search-engine.html</guid>
    <category>技术</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>博客长到二十多篇的时候，我自己都开始找不到旧文。市面上现成的搜索服务要挂第三方脚本，搜索引擎的站点内搜索又慢半拍——干脆用纯 JS 手搓一个。本文是它的架构笔记。</description>
    <content:encoded><![CDATA[
    <p>博客长到二十多篇的时候，我自己都开始找不到旧文。市面上现成的搜索服务要挂第三方脚本，搜索引擎的站点内搜索又慢半拍——干脆用纯 JS 手搓一个。本文是它的架构笔记。</p>

    <h2>整体思路：索引离线，查询在线</h2>
    <p>搜索分两半。<b>重的一半离线做</b>：服务器上的统计任务每 5 分钟扫描全部文章，剥掉 HTML 标签，把标题、日期、分类和正文前 4000 字写进 <code>search-index.json</code>。<b>轻的一半在线做</b>：浏览器只在第一次输入时拉取索引（约几十 KB），之后全部本地运算。</p>

    <h2>查询与打分</h2>
    <ul>
      <li><strong>命中判定</strong>：小写化后做 <code>indexOf</code>，够用且零依赖；</li>
      <li><strong>加权</strong>：标题命中 +10 分，正文命中 +1 分——"标题里说到"的文章几乎总是更相关；</li>
      <li><strong>摘要截取</strong>：从命中位置前 30 字开始截 80 字，关键词加 <code>&lt;mark&gt;</code> 高亮，让用户不点开也能确认；</li>
      <li><strong>防抖</strong>：160ms 输入防抖，连续敲键盘不会每敲一个字就跑一遍检索。</li>
    </ul>

    <h2>交互细节是体面所在</h2>
    <p>按 <code>/</code> 聚焦搜索框（学习 Vim 的肌肉记忆）、<code>Esc</code> 一键清空退出、搜索时隐藏文章列表避免视觉打架、清空即恢复。这些细节单看都小，合起来决定了"这个站有没有被认真对待"。</p>

    <blockquote>静态站做搜索的正确姿势，不是把搜索做轻，是把重活搬到构建时——浏览器只该负责最后一击。</blockquote>

    <h2>下一步</h2>
    <p>现在的搜索是子串匹配，中文分词还欠着。等文章过百，计划升级成 2-gram 倒排索引——正好首页控制台里有现成的构建管线，加一步就能跑。搜索引擎和据点一样，先能用，再变好。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>一个定时器，三份工作：我的 systemd 日常</title>
    <link>https://woshale.com/blog/posts/systemd-daily-drivers.html</link>
    <guid>https://woshale.com/blog/posts/systemd-daily-drivers.html</guid>
    <category>技术</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>这台服务器上有三个 cron 都不需要写的地方：证书续期、站点统计、每日备份，全部由 systemd timer 驱动。这篇把我配置它们时的笔记整理出来——尤其是那些官方文档里写了但我一开始没看懂的部分。</description>
    <content:encoded><![CDATA[
    <p>这台服务器上有三个 cron 都不需要写的地方：证书续期、站点统计、每日备份，全部由 systemd timer 驱动。这篇把我配置它们时的笔记整理出来——尤其是那些官方文档里写了但我一开始没看懂的部分。</p>

    <h2>为什么是 timer 而不是 cron</h2>
    <p>最直接的理由有两个。<code>Persistent=true</code>：服务器重启错过的时间点会补跑，半夜的备份不会因为一次宕机凭空消失。其次是日志：每个 timer 任务的输出自动进 journal，<code>journalctl -u xxx.service</code> 一查便知，不用自己维护日志文件和轮转。</p>

    <h2>我的三个 OnCalendar</h2>
    <pre><code># 证书检查：每天两次（certbot 官方推荐节奏）
OnCalendar=*-*-* 00/12:00:00

# 站点统计：每 5 分钟
OnCalendar=*:0/5

# 站点备份：每天 09:58，带 30 秒随机抖动
OnCalendar=*-*-* 09:58:00
RandomizedDelaySec=30</code></pre>
    <p>第三行那个 30 秒抖动是踩坑换来的习惯：固定整点的定时任务在全世界都在整点醒来的云上，会制造不必要的拥堵。</p>

    <h2>钩子：让动作连成链</h2>
    <p>证书续期完要让 nginx 知道。certbot 的 <code>renewal-hooks/deploy</code> 目录里放一个两行的脚本，续期成功自动 reload。同理，统计任务在生成 <code>stats.json</code> 之后顺手重建搜索索引和相关度地图——<b>上游任务的产出，就是下游任务的输入</b>，用 ExecStart 顺序串起来即可，不需要任何消息队列。</p>

    <blockquote>自动化最好的标志不是炫技，是你想不起来上一次手动做它是什么时候。</blockquote>

    <h2>查岗命令备忘</h2>
    <pre><code>systemctl list-timers --all          # 谁在跑、下次何时跑
journalctl -u woshale-backup.service # 某个任务的全部历史
systemctl start xxx.service          # 手动触发一次（试运行首选）</code></pre>
    <p>首页控制台上的那条"定时备份已创建"，就是这套体系每天在 journal 里留下的脚印。自动化不神秘，它只是把"记得去做"这件事，从你的大脑外包给了内核。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>把 UPS 电量搬上监控面板</title>
    <link>https://woshale.com/blog/posts/ups-battery-on-dashboard.html</link>
    <guid>https://woshale.com/blog/posts/ups-battery-on-dashboard.html</guid>
    <category>技术</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>《第一次实战》那篇的结尾许过愿：电池剩余接入监控。这次兑现。完整链路三步：读取状态 → 定时聚合 → 面板展示，每一步都比想象中简单，也比想象中讲究。</description>
    <content:encoded><![CDATA[
    <p>《第一次实战》那篇的结尾许过愿：电池剩余接入监控。这次兑现。完整链路三步：<b>读取状态 → 定时聚合 → 面板展示</b>，每一步都比想象中简单，也比想象中讲究。</p>

    <h2>读取：从 USB 到 JSON</h2>
    <p>大多数家用 UPS 都支持 USB 通信，<code>nut</code> 或 <code>apcupsd</code> 这类守护进程能把状态暴露成标准接口。我取的是三个字段：电池剩余百分比、预估续航、市电状态。采集频率五分钟一次——和站点统计同一个定时器，<b>能复用的调度器就不新建</b>。</p>

    <h2>聚合：写进 stats.json</h2>
    <pre><code># 伪代码：三行说完采集逻辑
battery = read_ups_battery()
history[date] = battery
panel["ups_percent"] = battery</code></pre>
    <p>聚合时做了两件小事：历史值写进本地文件做滚动保留（画趋势图用），当前值只保留最新一份。<b>监控数据的写入永远用"临时文件 + 原子替换"</b>，避免面板读到写了一半的文件。</p>

    <h2>展示：首页一行字</h2>
    <p>面板上它只是一行小字："市电 · 电池 100%"。安静、不闪、不弹。所有监控展示都应该这样：<b>正常时低调存在，异常时高声呐喊</b>——这才是"电池剩余"四个字该有的性格。</p>

    <blockquote>监控的上限不是技术，是克制：展示你能解释的，隐藏你只是能采集的。</blockquote>

    <p>至此，首页控制台的每一格数据都有了自己的采集故事。据点的"神经系统"又长了一根末梢。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>给博客加&quot;本周最多人读&quot;榜的决策笔记</title>
    <link>https://woshale.com/blog/posts/weekly-top-decision-notes.html</link>
    <guid>https://woshale.com/blog/posts/weekly-top-decision-notes.html</guid>
    <category>设计</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>博客首页最近多了一个&quot;本周最多人读&quot;榜单。功能只有一行字，决策过程却推翻了三版方案。把否决理由记下来——否定清单往往比功能清单更有参考价值。</description>
    <content:encoded><![CDATA[
    <p>博客首页最近多了一个"本周最多人读"榜单。功能只有一行字，决策过程却推翻了三版方案。把否决理由记下来——<b>否定清单往往比功能清单更有参考价值</b>。</p>

    <h2>被否决的方案</h2>
    <ul>
      <li><strong>第三方排行榜组件</strong>——引入外部脚本，违背本站"零第三方追踪"原则，一票否决；</li>
      <li><strong>实时统计</strong>——需要后端接口常驻，违背静态站架构，否决；</li>
      <li><strong>手动维护</strong>——诚实但不可持续，热度榜的价值就在"自动"二字。</li>
    </ul>

    <h2>最终方案：日志聚合</h2>
    <p>nginx 日志本来就是全量真相，缺的只是聚合。方案落定为：定时任务解析日志、按文章 URL 维度统计近七天阅读数、写入 JSON；前端拉取渲染。<b>全程零第三方、零后端、零 Cookie</b>，且榜单上的数字与日志永远对得上。</p>

    <h2>一个设计取舍</h2>
    <blockquote>榜单只展示前五，且永远不做"全站总排行"。原因：总排行会固化为头部垄断，老文章永无出头之日；而"本周"口径给了每篇文章每周一次的平等机会。</blockquote>

    <h2>意外发现</h2>
    <p>上线后榜单揭示了一个反直觉事实：访问量最高的文章不是最新的，也不是标题最抓眼的，而是被搜索引擎收录最早的那几篇——<b>老内容的长尾流量，远比想象中可观</b>。这个发现直接改变了我的写作计划：与其追热点，不如把老文章维护好。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>为什么我的首页要做成一个控制台</title>
    <link>https://woshale.com/blog/posts/why-a-console-homepage.html</link>
    <guid>https://woshale.com/blog/posts/why-a-console-homepage.html</guid>
    <category>随笔</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>大多数个人网站的首页是一张自我介绍：头像、简介、社交链接，礼貌而静态。我把它换成了一个控制台——流量图表、日志流、配置面板，看起来像个 SaaS 产品的落地页。有朋友问：你一个个人网站，装什么企业级？</description>
    <content:encoded><![CDATA[
    <p>大多数个人网站的首页是一张自我介绍：头像、简介、社交链接，礼貌而静态。我把它换成了一个控制台——流量图表、日志流、配置面板，看起来像个 SaaS 产品的落地页。有朋友问：你一个个人网站，装什么企业级？</p>

    <h2>因为它是真的</h2>
    <p>这是全部理由。SaaS 落地页最让人疲惫的地方，是那些精心绘制的假数据仪表盘——功能不存在，数字是编的，点击按钮通向注册墙。而我的控制台上每一个数字都有出处：请求数来自 <code>access.log</code>，证书倒计时来自 <code>openssl x509</code> 的输出，日志里那条"HTTPS 证书自动续期检查通过"昨天凌晨真的跑过一次。</p>

    <blockquote>当你的首页吹嘘的一切都可以被点开验证时，诚实就成了最好的设计语言。</blockquote>

    <h2>把运维从后台搬到台前</h2>
    <p>过去十年，个人网站的运维部分一直被 platforms 藏起来：托管平台替你管证书、管部署、管统计，代价是你的数字生活住在别人的房子里。自托管把这些工作拿了回来——那么为什么不顺便把它变成内容？证书续期不再是无趣的后台任务，它是首页上跳动的一行日志。</p>

    <h2>它也改变了我做事的方式</h2>
    <p>首页公示 uptime 之后，拖延症有了一个具体的形状：每次想凑合着改点东西，都会想到"这次部署会出现在控制台上"。仪式感这种东西，对独立做项目的人是刚需。</p>

    <h2>接下来</h2>
    <p>图表还是 12 根装饰柱，下一步把真实的按周请求量填进去；日志流考虑接上 sshd 的失败登录，让"扫描器探测已拦截"也变成真的。控制台会一直长，就像这个据点一样。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>写作起手式：给想开始写博客的你的五个建议</title>
    <link>https://woshale.com/blog/posts/writing-starter-five-tips.html</link>
    <guid>https://woshale.com/blog/posts/writing-starter-five-tips.html</guid>
    <category>设计</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>每年都会有人问我&quot;想写博客该怎么开始&quot;。这一年我把自己的答案整理成了五个起手式——每一条都来自真实的踩坑，供想开始的人参考。</description>
    <content:encoded><![CDATA[
    <p>每年都会有人问我"想写博客该怎么开始"。这一年我把自己的答案整理成了五个起手式——每一条都来自真实的踩坑，供想开始的人参考。</p>

    <h2>起手式一：从一篇"失败的旧文"改起</h2>
    <p>别从零写。找出你曾经写过的任何文字（论坛回复、朋友圈长文、工作总结），把它改写成博客文章。<b>改写比创作容易十倍</b>，而它的发布体验和创作一模一样。</p>

    <h2>起手式二：一个固定时段</h2>
    <p>每周固定的两小时，雷打不动。灵感会迟到，但日历不会。<b>固定时段的价值在于把"要不要写"的决定成本降为零</b>——到点就写，不需要说服自己。</p>

    <h2>起手式三：写给自己看</h2>
    <p>第一年的目标读者只有一个人：一年后的你。写给自己的文章没有表演压力，反而最诚实——而诚实的内容，恰恰是最能吸引陌生读者的。</p>

    <h2>起手式四：允许烂开头</h2>
    <p>开头卡住时，先写一个"废话开头"占位，写完全文再回来重写。<b>开头是全文最后写的一句话</b>——这条规则能解决 80% 的"写不下去"。</p>

    <h2>起手式五：三十秒验证</h2>
    <p>每篇文章写完后问自己：能不能用三十秒向朋友讲清楚这篇文章说了什么？讲不清楚，说明结构有问题——回去把"一句话版本"写出来，往往整篇的逻辑就顺了。</p>

    <blockquote>写作的起手式没有秘密，全都是"降低启动成本"的变体。开始的成本越低，坚持的概率越高。</blockquote>

    <h2>最后</h2>
    <p>这五个起手式的顺序也可以当作检查表：改旧文起步、定时写作、写给自己、烂开头占位、三十秒验证。任何一条卡住了，就回到上一条重新来。写起来之后，你会发现"坚持"这个词根本不需要出现——因为写已经变成了习惯。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>年历页：给时间一个形状</title>
    <link>https://woshale.com/blog/posts/year-grid-shape-of-time.html</link>
    <guid>https://woshale.com/blog/posts/year-grid-shape-of-time.html</guid>
    <category>设计</category>
    <pubDate>Sat, 29 Aug 2026 00:00:00 +0800</pubDate>
    <description>给站点做了一个&quot;据点的一年&quot;页面：365 个小方格铺成一面墙，一格是一天，访客多颜色就亮。上线的时候整面墙几乎全黑，只有右下角两格微微发亮——129 次、291 次。但我知道，这个页面最动人的地方恰恰是那些没亮的格子。</description>
    <content:encoded><![CDATA[
    <p>给站点做了一个"据点的一年"页面：365 个小方格铺成一面墙，一格是一天，访客多颜色就亮。上线的时候整面墙几乎全黑，只有右下角两格微微发亮——129 次、291 次。但我知道，这个页面最动人的地方恰恰是那些没亮的格子。</p>

    <h2>贡献图为什么动人</h2>
    <p>这类设计（GitHub 的贡献图是鼻祖）的魔法在于：<b>它把抽象的时间变成了一面可以抚摸的墙</b>。数字报表里的"八月访问量 426"没有体感，但一面墙上的两格微光，让你看见"哦，这个站已经活过了两个白天"。空间化的时间天然带情绪。</p>

    <h2>四个小决定</h2>
    <ol>
      <li><strong>按星期对齐，而不是简单排队</strong>：第一格前面补足空位，让每一列都代表一个完整的星期——周末的规律将来一眼可见；</li>
      <li><strong>零访问用"近黑"而不是纯黑</strong>：格子要隐约存在，因为那天服务器同样在岗，只是安静；</li>
      <li><strong>悬停给明细，页面不给噪点</strong>：每格的 <code>title</code> 里藏着日期和次数，好奇心会自己找到它；</li>
      <li><strong>没有数据的未来格子干脆隐形</strong>：还没活过的日子不占视觉重量——期待是看不见的。</li>
    </ol>

    <blockquote>空格子不是缺憾，是预留的席位。年历页的浪漫在于：它向所有还没发生的日子保证了一块地皮。</blockquote>

    <h2>数据从哪来</h2>
    <p>和全站一样诚实：nginx 日志按日聚合，滚动存档一年，凌晨的重启、错过的补跑，都由 systemd 的 <code>Persistent</code> 兜底。年历页是这套基础设施的脸面，底座还是那个每 5 分钟醒来一次的定时器。</p>
    <p>接下来就是等。等墙上的格子一格一格亮起来，等某个高峰日的格子亮到发光——然后写一篇《格子填满记》。日期已经想好了：等墙亮过一半的那天。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>咖啡馆工作两小时的开销核算 · 续</title>
    <link>https://woshale.com/blog/posts/cafe-matrix-continue.html</link>
    <guid>https://woshale.com/blog/posts/cafe-matrix-continue.html</guid>
    <category>随笔</category>
    <pubDate>Fri, 28 Aug 2026 00:00:00 +0800</pubDate>
    <description>上一篇算完钱，有读者（就是我自己的另一个脑内人格）追问：那是不是所有任务都适合带出门？连续两周的对照实验给出了否定答案——任务类型和环境必须匹配，否则两边的效率一起完蛋。</description>
    <content:encoded><![CDATA[
    <p>上一篇算完钱，有读者（就是我自己的另一个脑内人格）追问：那是不是所有任务都适合带出门？连续两周的对照实验给出了否定答案——<b>任务类型和环境必须匹配，否则两边的效率一起完蛋</b>。</p>

    <h2>任务-环境匹配矩阵</h2>
    <ul>
      <li><strong>深度写作 → 咖啡馆</strong>：背景人声屏蔽脑内杂音，效率 +40%；</li>
      <li><strong>调试排错 → 家里</strong>：排查需要频繁查资料和自言自语，公共场合反而尴尬；</li>
      <li><strong>开会讨论 → 哪都别去</strong>：网络事故会毁掉专业形象；</li>
      <li><strong>纯机械整理 → 随便哪</strong>：边看剧边整理文件夹，双线并行毫无压力。</li>
    </ul>

    <h2>一个反直觉的发现</h2>
    <blockquote>咖啡馆的价值不是"更好的环境"，是"更少的选择"——没有冰箱、没有床、没有"顺手收拾一下"的诱惑。专注的本质是剥夺选项。</blockquote>

    <h2>本周实验的意外变量</h2>
    <p>周二带了降噪耳机却忘了充电，被迫在嘈杂环境工作两小时，效率居然没有崩——因为"没有退路的专注"已经被前几周训练出来了。<b>工具可以锦上添花，习惯才是基本盘。</b></p>

    <p>实验还在继续。下期预告：试试图书馆的静音舱，据说那是专注力的天花板——如果预约得到的话。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>把个人据点搬回自己的服务器</title>
    <link>https://woshale.com/blog/posts/hello-self-hosting.html</link>
    <guid>https://woshale.com/blog/posts/hello-self-hosting.html</guid>
    <category>技术</category>
    <pubDate>Fri, 28 Aug 2026 00:00:00 +0800</pubDate>
    <description>在托管平台上放了几年页面，一直相安无事，直到某天想改一段 404 文案，发现要先本地构建、再推仓库、再等流水线——我只想改一句话。那一刻决定：把据点搬回自己的服务器。</description>
    <content:encoded><![CDATA[
    <p>在托管平台上放了几年页面，一直相安无事，直到某天想改一段 404 文案，发现要先本地构建、再推仓库、再等流水线——我只想改一句话。那一刻决定：把据点搬回自己的服务器。</p>

    <h2>从裸机到能访问</h2>
    <p>机器是一台 2 核 4G 的云主机，系统 CentOS Stream 9。第一步永远是三件套：装 nginx、开机自启、确认监听 80 端口。云平台的<b>安全组</b>要单独放行，这是新手最容易卡住的地方——服务器内 curl 通了，外网打不开，八成是它。</p>

    <h2>HTTPS 没那么神秘</h2>
    <p>证书用 Let's Encrypt，<code>certbot</code> 的 webroot 模式配好后一行命令签发：</p>
    <pre><code>certbot certonly --webroot -w /var/www/certbot \
  -d woshale.com -d www.woshale.com</code></pre>
    <p>真正省心的是后面：<code>certbot-renew.timer</code> 每天自动检查两次，剩余有效期不足 30 天才真的续期，续完由部署钩子重载 nginx。配完这一套之后，"证书"这个概念就从脑子里消失了。</p>

    <h2>把 301 交给规范域名</h2>
    <p><code>www</code> 子域全部 301 到裸域，HTTP 全部 301 到 HTTPS，唯一放行 HTTP 的路径是 <code>/.well-known/acme-challenge/</code>——续期还要用。规则只有三条，但每一条都有明确的理由。</p>

    <blockquote>自托管的本质不是省钱，是把"能不能改、什么时候改、改成什么样"这三个问题的答案拿回自己手里。</blockquote>

    <h2>上线之后</h2>
    <p>备案信息挂进页脚，公安联网备案提交审核，然后开始写第一行真正的内容。这台小机器此后做的每一件事——统计、博客、证书续期——都会出现在首页的控制台上。它不是 done，它是 running。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>nginx 日志里的访客故事</title>
    <link>https://woshale.com/blog/posts/nginx-log-stories.html</link>
    <guid>https://woshale.com/blog/posts/nginx-log-stories.html</guid>
    <category>技术</category>
    <pubDate>Fri, 28 Aug 2026 00:00:00 +0800</pubDate>
    <description>运维教程总把 access.log 说成&quot;待分析的数据&quot;，我更愿意把它当成一沓明信片。每一行都是一个瞬间：谁、从哪来、看了什么、停留多久。读多了会发现，日志里全是故事。</description>
    <content:encoded><![CDATA[
    <p>运维教程总把 access.log 说成"待分析的数据"，我更愿意把它当成一沓明信片。每一行都是一个瞬间：谁、从哪来、看了什么、停留多久。读多了会发现，日志里全是故事。</p>

    <h2>凌晨三点的常客</h2>
    <p>日志里最规律的访客是各类扫描器：试探 <code>/wp-admin</code>、<code>.env</code>、<code>phpmyadmin</code>——它们不认识这个站，只认识"世界上所有站"。把它们的探测次数做成首页的趋势图之后，这些不速之客反倒成了控制台上最稳定的存在：<b>至少它们风雨无阻</b>。</p>

    <h2>搜错关键词的人</h2>
    <p>有访客带着"绿萝 养死 原因"的关键词进了那篇养护日志；也有人搜"域名 收购"点进了取名故事。他们要找的东西和文章只擦了个边——但引流的搜索词统计暴露了一个事实：你永远猜不到别人会从哪个词掉进你的站点。</p>

    <h2>涟漪</h2>
    <p>最好看的一种曲线：某天某文被一个小圈子转发，流量像水波一样荡开两三天再归于平静。日志里的时间戳密密麻麻挤在那几个小时里，每一行背后都是一个真实的人点了链接。<b>写作者的成就感，说到底是这种时刻的积分。</b></p>

    <blockquote>日志不懂得修辞，但它记下的每一次 200，都是一次"有人来过"的确认。</blockquote>

    <p>所以首页控制台上的数字从不让我焦虑——它们不是考核指标，是一沓在读的明信片。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>给绿萝换盆：一次痛苦的&quot;生产环境迁移&quot;</title>
    <link>https://woshale.com/blog/posts/pothos-repot-migration.html</link>
    <guid>https://woshale.com/blog/posts/pothos-repot-migration.html</guid>
    <category>折腾</category>
    <pubDate>Fri, 28 Aug 2026 00:00:00 +0800</pubDate>
    <description>家里那盆从 2020 年活到现在的绿萝终于爆盆了——根从盆底钻出来打转，再不换盆就要&quot;自我窒息&quot;。换盆这件事，本质上就是一次生产环境迁移：有停机窗口，有回滚风险，有数据（根须）损坏的可能。流程七步，零死亡。</description>
    <content:encoded><![CDATA[
    <p>家里那盆从 2020 年活到现在的绿萝终于爆盆了——根从盆底钻出来打转，再不换盆就要"自我窒息"。换盆这件事，本质上就是一次<b>生产环境迁移</b>：有停机窗口，有回滚风险，有数据（根须）损坏的可能。流程七步，零死亡。</p>

    <h2>七步迁移流程</h2>
    <ol>
      <li><strong>停水三天</strong>——让土团收缩，等于迁移前的"只读模式"；</li>
      <li><strong>准备新环境</strong>——新盆垫排水层，新土混好缓释肥，等价于"先建好目标机房"；</li>
      <li><strong>快速脱盆</strong>——侧躺轻敲盆壁整团脱出，和数据库导出一样，慢就是稳；</li>
      <li><strong>修根</strong>——剪掉黑腐老根，相当于清理无效数据；</li>
      <li><strong>移栽定植</strong>——新土压实但不过紧，留出呼吸空间；</li>
      <li><strong>浇定根水</strong>——迁移后的首次"健康检查"，看排水是否顺畅；</li>
      <li><strong>缓苗观察一周</strong>——避开直射光，不给肥，只等它自己适应。</li>
    </ol>

    <h2>唯一的事故</h2>
    <blockquote>第七步期间我手贱施了一次肥，两片叶子边缘焦黄——完美的迁移方案毁于一次多余的"顺手优化"。生产环境迁完之后，请什么都别做，让它自己缓。</blockquote>

    <h2>迁移后的验证</h2>
    <p>一周后新叶展开，颜色比迁前更深——新陶盆的透气性让根系呼吸更顺。这次迁移的总成本：一个陶盆、五升营养土、四十分钟。回报：未来三年的生长空间，和一篇写给大家看的迁移手册。</p>
    <p>给系统做迁移的人应该都养盆植物——那是最便宜的迁移演练场，而且失败的时候，它不会反过来指责你。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>云服务器开箱 30 分钟清单</title>
    <link>https://woshale.com/blog/posts/server-unbox-30min.html</link>
    <guid>https://woshale.com/blog/posts/server-unbox-30min.html</guid>
    <category>技术</category>
    <pubDate>Fri, 28 Aug 2026 00:00:00 +0800</pubDate>
    <description>给朋友远程指导装服务器，他问我：&quot;第一件事装宝塔还是装 Docker？&quot;都不是。开箱前 30 分钟不属于建站，属于加固。这份清单按分钟排，照着做即可。</description>
    <content:encoded><![CDATA[
    <p>给朋友远程指导装服务器，他问我："第一件事装宝塔还是装 Docker？"都不是。<b>开箱前 30 分钟不属于建站，属于加固</b>。这份清单按分钟排，照着做即可。</p>

    <h2>第 0–5 分钟：换锁</h2>
    <p>本地生成密钥对，公钥写入服务器，然后<b>关掉密码登录</b>。公网上的机器人每时每刻都在爆破密码——本站日志里那些"SSH 失败登录"记录就是证据。关掉密码登录的那一刻，爆破产业对你失效。</p>
    <pre><code>ssh-keygen -t ed25519
ssh-copy-id user@server
# 确认密钥能登录之后，再编辑 /etc/ssh/sshd_config：
#   PasswordAuthentication no
systemctl restart sshd</code></pre>

    <h2>第 5–15 分钟：更新与防火墙</h2>
    <ul>
      <li><code>dnf upgrade</code> 打满全部补丁——镜像积累的漏洞不会自己消失；</li>
      <li>防火墙只放行 22/80/443，其余默认拒绝；</li>
      <li>云控制台的<b>安全组</b>做同样的最小放行（两层保险，缺一不可）；</li>
      <li>启用自动安全更新：<code>dnf install dnf-automatic</code> 并设为开机自启。</li>
    </ul>

    <h2>第 15–25 分钟：装"会自己干活"的东西</h2>
    <p>nginx、certbot、以及最重要的 systemd timer 习惯——从第一台服务器起就让"备份与统计"成为默认存在的服务，而不是"以后再补"的欠账。它们会在未来的某个凌晨替你救场。</p>

    <h2>第 25–30 分钟：留下证据</h2>
    <p>记录三样东西到一个本地文件：系统版本、放行端口清单、密钥指纹。半年后你会感谢这三十秒。做完这些，才轮到装 nginx、写第一个页面——<b>地基打完，剩下的都是乐趣</b>。</p>

    <blockquote>服务器的安全感不来自配置多复杂，来自"每一项都知道为什么存在"。</blockquote>
  ]]></content:encoded>
  </item>
  <item>
    <title>静音舱实验：专注力的天花板</title>
    <link>https://woshale.com/blog/posts/silence-pod-experiment.html</link>
    <guid>https://woshale.com/blog/posts/silence-pod-experiment.html</guid>
    <category>折腾</category>
    <pubDate>Fri, 28 Aug 2026 00:00:00 +0800</pubDate>
    <description>咖啡馆实验的续篇来了。这次预约到了共享办公空间的静音舱——两小时一个舱位，隔音、单人、无窗。带着一个悬置已久的问题进去：专注力到底有没有天花板？</description>
    <content:encoded><![CDATA[
    <p>咖啡馆实验的续篇来了。这次预约到了共享办公空间的静音舱——两小时一个舱位，隔音、单人、无窗。带着一个悬置已久的问题进去：<b>专注力到底有没有天花板？</b></p>

    <h2>对照设计</h2>
    <ul>
      <li><strong>变量 A（咖啡馆）</strong>：背景人声 65 分贝，有走动干扰；</li>
      <li><strong>变量 B（静音舱）</strong>：环境噪声 35 分贝，全程无人打搅；</li>
      <li><strong>任务</strong>：同类型的深度写作，各两次，计时并自评。</li>
    </ul>

    <h2>结果出乎意料</h2>
    <p>产出字数：静音舱多 12%。但<b>任务完成质量的自评，咖啡馆反而更高</b>。复盘才发现原因：静音舱里太安静，安静到大脑开始给"很多年后要用的知识点"分配内存——深度够深，但产出聚焦度反而被"顺便研究一下"稀释了。</p>

    <blockquote>绝对的安静适合思考，适度的嘈杂适合执行。环境的选择取决于你要的是深度，还是速度。</blockquote>

    <h2>结论与下一个实验</h2>
    <p>专注力的天花板不是 35 分贝的静音舱，是"任务与环境的匹配度"。结论维持咖啡馆实验的判断，但加了一条细则：<b>深度思考预约静音舱，执行型任务留在咖啡馆，两者都不如"知道自己此刻在做什么"。</b></p>
    <p>静音舱两小时 40 元。这钱花得值不值？看你把它当成租赁空间，还是租赁一段"不得不专注"的契约。</p>
  ]]></content:encoded>
  </item>
  <item>
    <title>停电十分钟：UPS 的第一次实战</title>
    <link>https://woshale.com/blog/posts/ups-first-real-test.html</link>
    <guid>https://woshale.com/blog/posts/ups-first-real-test.html</guid>
    <category>技术</category>
    <pubDate>Fri, 28 Aug 2026 00:00:00 +0800</pubDate>
    <description>晚上八点十七分，小区突然跳闸。灯灭了，冰箱停了，但我书房里那台小服务器没有停——它顶在一台不到两百块的 UPS 上，撑过了整整十分钟的停电。这是我买 UPS 以来第一次&quot;实战&quot;，值得记录。</description>
    <content:encoded><![CDATA[
    <p>晚上八点十七分，小区突然跳闸。灯灭了，冰箱停了，但我书房里那台小服务器<b>没有停</b>——它顶在一台不到两百块的 UPS 上，撑过了整整十分钟的停电。这是我买 UPS 以来第一次"实战"，值得记录。</p>

    <h2>停电期间发生了什么</h2>
    <ul>
      <li><strong>0 分钟</strong>：市电断，UPS 蜂鸣一声切到电池，路由器与服务器的灯纹丝不乱；</li>
      <li><strong>2 分钟</strong>：SSH 登录服务器确认负载，顺手把非必要的下载任务停了；</li>
      <li><strong>7 分钟</strong>：收到 UPS 的低电量告警推送，评估剩余时间足够；</li>
      <li><strong>10 分钟</strong>：市电恢复，一切如常，无一次服务中断。</li>
    </ul>

    <h2>没有 UPS 的那十分钟会怎样</h2>
    <p>服务器会经历一次硬断电：文件系统可能损伤、正在写入的日志可能截断、来电后所有服务从冷启动爬起来——大概需要半小时的人工善后。两百块的 UPS 把这半小时的善后，变成了十分钟的无感等待。<b>这是性价比最高的一笔基础设施投资。</b></p>

    <h2>事后补上的三块短板</h2>
    <ol>
      <li><strong>自动关机脚本</strong>——低电量阈值触发安全关机，而不是硬撑到没电；</li>
      <li><strong>UPS 电量接入监控</strong>——首页控制台加一行"电池剩余"，可视化才安心；</li>
      <li><strong>拔掉冗余设备的电</strong>——停电时 UPS 只保关键链路，续航时间直接翻倍。</li>
    </ol>

    <blockquote>所谓基础设施，就是平时完全感觉不到它的存在、断电十分钟之后让你谢天谢地的那些东西。</blockquote>
  ]]></content:encoded>
  </item>
  <item>
    <title>毕业前写给学弟的装机清单</title>
    <link>https://woshale.com/blog/posts/dorm-pc-checklist.html</link>
    <guid>https://woshale.com/blog/posts/dorm-pc-checklist.html</guid>
    <category>工具</category>
    <pubDate>Thu, 27 Aug 2026 00:00:00 +0800</pubDate>
    <description>学弟托我帮忙配一台&quot;能撑过大学四年&quot;的台式机。预算有限、需求模糊、还要考虑毕业转手——这份清单可以抄作业，也把每个选择背后的理由写明白。</description>
    <content:encoded><![CDATA[
    <p>学弟托我帮忙配一台"能撑过大学四年"的台式机。预算有限、需求模糊、还要考虑毕业转手——这份清单可以抄作业，也把每个选择背后的理由写明白。</p>

    <h2>钱该花在哪</h2>
    <ul>
      <li><strong>内存一步到位</strong>：16GB 起步。内存是四年内唯一"当时觉得贵、后来真香"的部件；</li>
      <li><strong>SSD 容量翻倍</strong>：512G 起步，系统盘和资料盘分区，重装系统不流离失所；</li>
      <li><strong>CPU 够用就好</strong>：文档、编程、轻度剪辑，中端型号足够；省下的钱给显示器——<b>眼睛是要用四十年的，显卡只用五年</b>。</li>
    </ul>

    <h2>装机清单本体</h2>
    <pre><code>[ ] CPU：中端 6 核以上，盒装散热器够用
[ ] 内存：16GB（8G×2 组双通道）
[ ] SSD：512G NVMe，系统盘单独分区
[ ] 电源：额定 450W 金牌，别在电源上省钱
[ ] 显示器：24 寸 2K，护眼比刷新率重要
[ ] 机箱：静音风扇 ×2，风道比灯效重要</code></pre>

    <h2>装完系统后的十分钟</h2>
    <ol>
      <li>开启自动安全更新；</li>
      <li>浏览器装好广告过滤；</li>
      <li>建一个"下载文件夹每月清空"的日历提醒；</li>
      <li>把毕业清单（本文）打印一份贴在桌边——维护习惯比硬件寿命更决定一台电脑能陪你多久。</li>
    </ol>

    <blockquote>装机清单每年都会过时，但"把钱花在每天用得上的地方"这个原则，十年不会变。</blockquote>
  ]]></content:encoded>
  </item>
</channel>
</rss>
