<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>技术 on 睡醒了再写</title><link>https://lingzuian.top/categories/%E6%8A%80%E6%9C%AF/</link><description>Recent content in 技术 on 睡醒了再写</description><generator>Hugo -- 0.146.0</generator><language>zh-cn</language><copyright>2026 睡醒了再写 | 备案号：湘ICP备2026005470号</copyright><lastBuildDate>Fri, 27 Feb 2026 18:33:54 +0800</lastBuildDate><atom:link href="https://lingzuian.top/categories/%E6%8A%80%E6%9C%AF/index.xml" rel="self" type="application/rss+xml"/><item><title>基于腾讯云 COS 的 Obsidian 三端同步方案：从 WebDAV 困境到 S 3 协议实践</title><link>https://lingzuian.top/posts/based_on_tencent_cloud_cos_obsidian_three_way_sync_solution/</link><pubDate>Fri, 27 Feb 2026 18:33:54 +0800</pubDate><guid>https://lingzuian.top/posts/based_on_tencent_cloud_cos_obsidian_three_way_sync_solution/</guid><description>&lt;h2 id="引言">引言&lt;/h2>
&lt;p>Obsidian 是一款优秀的本地知识库工具，但是其没有免费的多端同步服务，其他人我不知道，这个问题反正很困扰本人。我主要是在教室主要使用平板编辑，在寝室就换为电脑了，所以有频繁的多端同步需求。&lt;/p>
&lt;p>奈何官方同步服务收费较高，而第三方网盘（iCloud、百度云、OneDrive 等）存在隐私顾虑和速度限制。所以我选择自建同步方案，但这么搞往往需要处理协议兼容性、权限配置等等细节。于是在寒假折腾一天，这里就总结一下，旨在为有类似需求的读者提供一份兼顾专业性与可操作性的参考。&lt;/p>
&lt;p>本文记录的是我从最初尝试 Nextcloud+WebDAV 到最终采用腾讯云 COS（对象存储）实现电脑、手机、平板三端稳定同步的全过程，尝试深入剖析各阶段遇到的技术问题及其原理。&lt;/p>
&lt;p>本文部分使用 AI 辅助编写。&lt;/p>
&lt;hr>
&lt;h2 id="webdav-方案的尝试与失败">WebDAV 方案的尝试与失败&lt;/h2>
&lt;h3 id="初始架构nextcloud--webdav">初始架构：Nextcloud + WebDAV&lt;/h3>
&lt;p>我最初利用服务器，通过 Docker （服务器还有其他东西，求放心搞了一个隔离）部署了 Nextcloud（版本 23），并启用其 WebDAV 服务。在电脑端 Obsidian 中安装 Remotely Save 插件，配置 WebDAV 连接后，同步功能正常，文件可双向传输。这就验证了自建同步的可行性。&lt;/p>
&lt;h3 id="安卓端的异常现象">安卓端的异常现象&lt;/h3>
&lt;p>但是，当在安卓手机和平板上进行同样配置时，问题出现了：同步状态极不稳定，频繁返回 401 Unauthorized 错误，连接测试时而成功，时而失败，无固定规律。偶尔成功同步一次后，再次尝试即失败。设备重启后短暂恢复，随后再次报错。不同安卓设备表现一致，排除了个别设备故障。&lt;/p>
&lt;h3 id="排查过程">排查过程：&lt;/h3>
&lt;p>针对上述现象，我和 AI 聊了聊，做了排查：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>凭证验证&lt;/strong>：重置 Nextcloud 账户密码，重新输入插件配置，问题依旧。&lt;/li>
&lt;li>&lt;strong>域名与信任&lt;/strong>：在 Nextcloud 的 &lt;code>config.php&lt;/code> 中添加了手机访问的 IP 和域名，避免请求被拒绝。&lt;/li>
&lt;li>&lt;strong>网络环境&lt;/strong>：切换 Wi-Fi、4 G/5 G，甚至使用手机热点连接，未能改善。&lt;/li>
&lt;li>&lt;strong>服务&lt;/strong>：使用手机浏览器直接访问 Nextcloud 的 WebDAV 地址，输入凭证后可以正常浏览目录，说明服务本身是正常的，且网络无阻断。&lt;/li>
&lt;/ol>
&lt;h3 id="根本原因分析">根本原因分析&lt;/h3>
&lt;p>走投无路，于是求助伟大的 deepseek ，他查阅 Remotely Save 插件开发者文档及相关技术讨论后，发现了问题根源：&lt;strong>安卓系统底层对 WebDAV 协议的非标准 HTTP 方法支持存在缺陷&lt;/strong>。&lt;/p></description></item><item><title>记一次 Minecraft 服务器运维：脚本编写漏洞导致的日报数据不全</title><link>https://lingzuian.top/posts/daily_report_data_incomplete_due_to_a_script_writing_bug/</link><pubDate>Thu, 26 Feb 2026 22:45:00 +0800</pubDate><guid>https://lingzuian.top/posts/daily_report_data_incomplete_due_to_a_script_writing_bug/</guid><description>&lt;h1 id="记一次-minecraft-服务器运维脚本编写漏洞导致的日报数据不全">记一次 Minecraft 服务器运维：脚本编写漏洞导致的日报数据不全&lt;/h1>
&lt;h2 id="问题现象日报只记录了半天的活动">问题现象：日报只记录了“半天”的活动&lt;/h2>
&lt;p>我搭建的 Minecraft Fabric 1.20.1 服务器每天重启四次（0、6、12、18 点），并在 23:55 生成一份 Markdown 日报。运行一段时间后，我不幸的发现：&lt;strong>日报里的“最近聊天记录”只显示最后几小时的消息，而“活跃玩家列表”中的“最后活动”时间其实是玩家最后一次上线时间，根本不是真正的退出时间&lt;/strong>。简单来说，日报数据严重不全，几乎失去了参考价值。这令人沮丧，本来我就被脚本妙妙小 bug 折磨，现在又要来修了，于是在精心编写了提示词后与 AI 好好学习了一下，现在总结问题发出来。&lt;/p>
&lt;h2 id="为什么会出现数据不全">为什么会出现数据不全？&lt;/h2>
&lt;p>要搞清原因，得先了解 Minecraft 服务器的日志机制。&lt;/p>
&lt;h3 id="1-服务器重启会覆盖-latestlog">1. 服务器重启会覆盖 &lt;code>latest.log&lt;/code>&lt;/h3>
&lt;p>Minecraft 服务端（包括 Fabric）运行时，会把所有日志实时写入 &lt;code>logs/latest.log&lt;/code>。但当服务器重启（无论是正常关闭还是崩溃重启），&lt;code>latest.log&lt;/code> 通常会被清空或覆盖。新启动的服务器会创建一个全新的 &lt;code>latest.log&lt;/code>，只记录本次启动后的日志。&lt;/p>
&lt;p>我之前是打算每天 23:55 生成报告，服务器这之前不重启。但后来为了保证服务器稳定（对钱包的妥协），设置了每天四次定时重启（通过维护脚本）。这就导致：&lt;strong>23:55 生成日报时，&lt;code>latest.log&lt;/code> 里只保存了最后一次重启（18 点）之后到现在的日志&lt;/strong>，而 0 点到 18 点之间的所有日志都丢失了。&lt;/p>
&lt;h3 id="2-旧脚本只盯着-latestlog">2. 旧脚本只盯着 &lt;code>latest.log&lt;/code>&lt;/h3>
&lt;p>看看旧的日报脚本是怎么获取日志的（简化版）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>LOG_FILE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$SERVER_DIR&lt;span style="color:#e6db74">/logs/latest.log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>TODAY_LOG&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>grep &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$TODAY&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$LOG_FILE&lt;span style="color:#e6db74">&amp;#34;&lt;/span> 2&amp;gt;/dev/null&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -z &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$TODAY_LOG&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> TODAY_LOG&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>tail -1000 &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$LOG_FILE&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这段代码试图从 &lt;code>latest.log&lt;/code> 中提取当天的日志行（按日期字符串过滤），如果找不到（比如日志里没有日期前缀，或者重启后日期已变），就退而取最后 1000 行（至少想到了这个备案）。但是显然，无论哪种方式，都只能得到部分日志。&lt;/p>
&lt;h3 id="3-三步之内必有解药日志归档目录-logs">3. 三步之内必有解药：日志归档目录 &lt;code>logs/&lt;/code>&lt;/h3>
&lt;p>实际上，Minecraft 服务端在日志轮转方面做得挺周到（屎山代码居然还有小巧思）——它会将旧的日志自动压缩并存放到 &lt;code>logs/&lt;/code> 目录下（缺点就是积压一堆不大但是碍眼的压缩包），文件名通常像这样：&lt;/p>
&lt;div class="goat svg-container ">
&lt;svg
xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 200 73"
>
&lt;g transform='translate(8,16)'>
&lt;text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'>l&lt;/text>
&lt;text text-anchor='middle' x='0' y='20' fill='currentColor' style='font-size:1em'>l&lt;/text>
&lt;text text-anchor='middle' x='0' y='36' fill='currentColor' style='font-size:1em'>l&lt;/text>
&lt;text text-anchor='middle' x='8' y='4' fill='currentColor' style='font-size:1em'>o&lt;/text>
&lt;text text-anchor='middle' x='8' y='20' fill='currentColor' style='font-size:1em'>o&lt;/text>
&lt;text text-anchor='middle' x='8' y='36' fill='currentColor' style='font-size:1em'>o&lt;/text>
&lt;text text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'>s&lt;/text>
&lt;text text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'>s&lt;/text>
&lt;text text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'>s&lt;/text>
&lt;text text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'>/&lt;/text>
&lt;text text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'>/&lt;/text>
&lt;text text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'>/&lt;/text>
&lt;text text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'>0&lt;/text>
&lt;text text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'>0&lt;/text>
&lt;text text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'>0&lt;/text>
&lt;text text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'>5&lt;/text>
&lt;text text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'>5&lt;/text>
&lt;text text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'>5&lt;/text>
&lt;text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'>0&lt;/text>
&lt;text text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'>0&lt;/text>
&lt;text text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'>0&lt;/text>
&lt;text text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='104' y='36' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'>3&lt;/text>
&lt;text text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'>3&lt;/text>
&lt;text text-anchor='middle' x='112' y='36' fill='currentColor' style='font-size:1em'>4&lt;/text>
&lt;text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='120' y='20' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='120' y='36' fill='currentColor' style='font-size:1em'>-&lt;/text>
&lt;text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'>1&lt;/text>
&lt;text text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'>2&lt;/text>
&lt;text text-anchor='middle' x='128' y='36' fill='currentColor' style='font-size:1em'>1&lt;/text>
&lt;text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'>.&lt;/text>
&lt;text text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'>.&lt;/text>
&lt;text text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'>.&lt;/text>
&lt;text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'>l&lt;/text>
&lt;text text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'>l&lt;/text>
&lt;text text-anchor='middle' x='144' y='36' fill='currentColor' style='font-size:1em'>l&lt;/text>
&lt;text text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'>o&lt;/text>
&lt;text text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'>o&lt;/text>
&lt;text text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'>o&lt;/text>
&lt;text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'>.&lt;/text>
&lt;text text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'>.&lt;/text>
&lt;text text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'>.&lt;/text>
&lt;text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'>g&lt;/text>
&lt;text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'>z&lt;/text>
&lt;text text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'>z&lt;/text>
&lt;text text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'>z&lt;/text>
&lt;/g>
&lt;/svg>
&lt;/div>
&lt;p>这些压缩文件里保存着全天的日志，按时间分段。如果日报脚本能读取这些文件，就能拼凑出完整的日志历史。&lt;/p></description></item><item><title>博客项目技术文档</title><link>https://lingzuian.top/posts/blog_project_technical_documentation/</link><pubDate>Thu, 26 Feb 2026 21:28:17 +0800</pubDate><guid>https://lingzuian.top/posts/blog_project_technical_documentation/</guid><description>&lt;h1 id="博客项目概述">博客项目概述&lt;/h1>
&lt;h2 id="一项目简介">一、项目简介&lt;/h2>
&lt;p>这是一个基于 &lt;strong>Hugo&lt;/strong> 静态网站生成器 + &lt;strong>PaperMod&lt;/strong> 主题的个人博客系统。代码托管在 &lt;strong>Gitee&lt;/strong> 私有仓库，通过 &lt;strong>Caddy&lt;/strong> 作为 Web 服务器自动提供 HTTPS 服务，并利用服务器定时任务（crontab）实现自动拉取更新、构建和部署。整个系统部署在腾讯云服务器（Ubuntu 24.04）上，同时服务器还运行着 Nextcloud 私有云盘和 Jupyter 科学计算环境（均通过 Docker 容器管理）。&lt;/p>
&lt;h2 id="二技术栈">二、技术栈&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>静态生成器&lt;/strong>：Hugo（v 0.146.0+extended）&lt;/li>
&lt;li>&lt;strong>主题&lt;/strong>：PaperMod（手动下载，非 Git 子模块）&lt;/li>
&lt;li>&lt;strong>版本控制&lt;/strong>：Git + Gitee（国内镜像，私有仓库）&lt;/li>
&lt;li>&lt;strong>Web 服务器&lt;/strong>：Caddy（Docker 容器），自动申请/续期 SSL 证书&lt;/li>
&lt;li>&lt;strong>部署方式&lt;/strong>：本地推送 → Gitee → 服务器定时拉取 → Hugo 构建 → Caddy 服务&lt;/li>
&lt;li>&lt;strong>服务器 OS&lt;/strong>：Ubuntu 24.04 LTS&lt;/li>
&lt;li>&lt;strong>容器管理&lt;/strong>：Docker + Docker Compose（管理 Caddy、Nextcloud、Jupyter 等）&lt;/li>
&lt;li>&lt;strong>自动部署&lt;/strong>：crontab 每分钟执行自定义脚本 &lt;code>/home/your-username/auto-deploy.sh&lt;/code>&lt;/li>
&lt;/ul>
&lt;h2 id="三系统架构">三、系统架构&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>本地电脑
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ 写文章 (Markdown)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ hugo new posts/xxx.md
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ 编辑后 git add/commit/push
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ▼
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Gitee 仓库 (私有)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ▼
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>腾讯云服务器
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ├─ crontab (每分钟)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ └─ 运行 /home/your-username/auto-deploy.sh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ ├─ git pull 拉取最新源码
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ ├─ hugo --minify 生成静态文件到临时目录
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ ├─ 替换 /home/your-username/blog/public
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ ├─ 修复权限为 www-data
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> │ └─ docker restart caddy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> └─ Caddy 容器 (监听 80/443)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> └─ 托管 /home/your-username/blog/public
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="四关键配置与路径">四、关键配置与路径&lt;/h2>
&lt;h3 id="41-本地博客源码">4.1 本地博客源码&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>路径&lt;/strong>：&lt;code>本地博客路径&lt;/code>&lt;/li>
&lt;li>&lt;strong>配置文件&lt;/strong>：&lt;code>hugo.toml&lt;/code>（或 &lt;code>config.toml&lt;/code>），内容示例：
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-toml" data-lang="toml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">baseURL&lt;/span> = &lt;span style="color:#e6db74">&amp;#39;https://lingzuian.top/&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">languageCode&lt;/span> = &lt;span style="color:#e6db74">&amp;#39;zh-cn&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">title&lt;/span> = &lt;span style="color:#e6db74">&amp;#39;静影沉璧到此一游&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">theme&lt;/span> = &lt;span style="color:#e6db74">&amp;#39;PaperMod&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">copyright&lt;/span> = &lt;span style="color:#e6db74">&amp;#39;© 2026 静影沉璧到此一游 | 备案号：&amp;lt;a href=&amp;#34;https://beian.miit.gov.cn/&amp;#34; target=&amp;#34;_blank&amp;#34;&amp;gt;湘ICP备2026005470号&amp;lt;/a&amp;gt;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[&lt;span style="color:#a6e22e">params&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">math&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span> &lt;span style="color:#75715e"># 开启 KaTeX 数学公式&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>[&lt;span style="color:#a6e22e">menu&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [[&lt;span style="color:#a6e22e">menu&lt;/span>.&lt;span style="color:#a6e22e">main&lt;/span>]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">name&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;文章&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">url&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;/posts/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">weight&lt;/span> = &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> [[&lt;span style="color:#a6e22e">menu&lt;/span>.&lt;span style="color:#a6e22e">main&lt;/span>]]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">name&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;关于&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">url&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;/about/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">weight&lt;/span> = &lt;span style="color:#ae81ff">20&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>&lt;strong>文章存放&lt;/strong>：&lt;code>content/posts/&lt;/code>&lt;/li>
&lt;li>&lt;strong>页面存放&lt;/strong>：&lt;code>content/&lt;/code>，如 &lt;code>about.md&lt;/code>&lt;/li>
&lt;li>&lt;strong>自定义模板&lt;/strong>：&lt;code>layouts/partials/&lt;/code>，如 &lt;code>math.html&lt;/code>（加载 KaTeX）&lt;/li>
&lt;/ul>
&lt;h3 id="42-服务器关键目录">4.2 服务器关键目录&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>博客源码&lt;/strong>：&lt;code>/home/your-username/blog-source&lt;/code>（从 Gitee 克隆）&lt;/li>
&lt;li>&lt;strong>静态文件目录&lt;/strong>：&lt;code>/home/your-username/blog/public&lt;/code>（Caddy 挂载的根目录）&lt;/li>
&lt;li>&lt;strong>自动部署脚本&lt;/strong>：&lt;code>/home/your-username/auto-deploy.sh&lt;/code>&lt;/li>
&lt;li>&lt;strong>部署日志&lt;/strong>：&lt;code>/home/your-username/auto-deploy.log&lt;/code>&lt;/li>
&lt;li>&lt;strong>Caddy 配置&lt;/strong>：&lt;code>/home/your-username/caddy/Caddyfile&lt;/code>&lt;/li>
&lt;li>&lt;strong>Caddy Compose 文件&lt;/strong>：&lt;code>/home/your-username/caddy/docker-compose.yml&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="43-自动部署脚本当前稳定版">4.3 自动部署脚本（当前稳定版）&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>SOURCE_DIR&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/home/your-username/blog-source&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PUBLIC_DIR&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/home/your-username/blog/public&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>TEMP_DIR&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/home/your-username/blog/temp&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$SOURCE_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">||&lt;/span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git fetch origin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LOCAL&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>git rev-parse HEAD&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>REMOTE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>git rev-parse origin/main&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$LOCAL&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$REMOTE&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;No updates, exiting.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;Updates found, pulling changes...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> ! git pull; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Git pull failed. Aborting deployment.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>mkdir -p &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$TEMP_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo chown your-username:your-username &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$TEMP_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> ! hugo --minify --destination &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$TEMP_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Hugo build failed, aborting deployment. Keeping old site.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rm -rf &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$TEMP_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo rm -rf &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$PUBLIC_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo mv &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$TEMP_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$PUBLIC_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo chown -R 33:33 &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$PUBLIC_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo chmod -R &lt;span style="color:#ae81ff">755&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$PUBLIC_DIR&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker restart caddy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;Deployment complete.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="44-caddy-配置-caddyfile">4.4 Caddy 配置 (&lt;code>Caddyfile&lt;/code>)&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>lingzuian.top {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> root * /var/www/blog
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> file_server
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cloud.internal.example.com {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverse_proxy nextcloud_app:80
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>jupyter.internal.example.com {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> reverse_proxy math_jupyter:8888
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="45-caddy-docker-compose-docker-composeyml">4.5 Caddy Docker Compose (&lt;code>docker-compose.yml&lt;/code>)&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">caddy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">caddy:latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">caddy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;80:80&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;443:443&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./Caddyfile:/etc/caddy/Caddyfile&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/home/your-username/blog/public:/var/www/blog&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">caddy_data:/data&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">caddy_config:/config&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">networks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">web&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">caddy_data&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">caddy_config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">networks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">web&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">external&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="五自动部署流程详解">五、自动部署流程详解&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>crontab&lt;/strong> 每分钟执行 &lt;code>/home/your-username/auto-deploy.sh&lt;/code>。&lt;/li>
&lt;li>脚本先 &lt;code>git fetch origin&lt;/code> 比较本地与远程 commit hash：
&lt;ul>
&lt;li>若相同 → 退出（无更新）。&lt;/li>
&lt;li>若不同 → 执行 &lt;code>git pull&lt;/code> 拉取最新代码。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>拉取成功后，创建临时目录 &lt;code>/home/your-username/blog/temp&lt;/code>，确保所有者是 &lt;code>your-username&lt;/code>。&lt;/li>
&lt;li>运行 &lt;code>hugo --minify --destination&lt;/code> 生成静态文件到临时目录。&lt;/li>
&lt;li>&lt;strong>构建成功&lt;/strong>：删除旧 &lt;code>public&lt;/code> 目录，将 &lt;code>temp&lt;/code> 原子移动为 &lt;code>public&lt;/code>，然后修复所有者为 &lt;code>www-data&lt;/code>（UID 33）并设置权限 755，最后重启 Caddy。&lt;/li>
&lt;li>&lt;strong>构建失败&lt;/strong>：保留旧 &lt;code>public&lt;/code> 目录，删除临时目录，退出（网站不变）。&lt;/li>
&lt;/ol>
&lt;h2 id="六常见问题与解决方案历史坑点">六、常见问题与解决方案（历史坑点）&lt;/h2>
&lt;h3 id="61-权限问题permission-denied">6.1 权限问题（Permission denied）&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>现象&lt;/strong>：Hugo 构建时无法写入 &lt;code>public&lt;/code> 目录，或 Caddy 无法读取文件。&lt;/li>
&lt;li>&lt;strong>原因&lt;/strong>：&lt;code>public&lt;/code> 目录所有者不是运行 Hugo 的用户（your-username）或不是容器内的用户（www-data）。&lt;/li>
&lt;li>&lt;strong>解决方案&lt;/strong>：
&lt;ul>
&lt;li>在脚本中，生成前确保 &lt;code>temp&lt;/code> 目录归 &lt;code>your-username&lt;/code>，生成后 &lt;code>public&lt;/code> 归 &lt;code>www-data&lt;/code>。&lt;/li>
&lt;li>手动修复：&lt;code>sudo chown -R 33:33 /home/your-username/blog/public&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>当前状态&lt;/strong>：脚本已正确处理，若手动操作后需检查权限。&lt;/li>
&lt;/ul>
&lt;h3 id="62-git-冲突或无法推送">6.2 Git 冲突或无法推送&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>现象&lt;/strong>：&lt;code>git push&lt;/code> 被拒，提示 &lt;code>non-fast-forward&lt;/code> 或 &lt;code>divergent branches&lt;/code>。&lt;/li>
&lt;li>&lt;strong>原因&lt;/strong>：在服务器上直接提交了代码，导致本地与远程分叉。&lt;/li>
&lt;li>&lt;strong>解决方案&lt;/strong>：
&lt;ul>
&lt;li>永远不要在服务器上执行 &lt;code>git commit&lt;/code>。所有修改必须在本地进行。&lt;/li>
&lt;li>若已发生，需在服务器上 &lt;code>git pull&lt;/code> 合并（可能冲突），再 &lt;code>git push&lt;/code> 解决。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>预防&lt;/strong>：遵守“只从本地推送”原则。&lt;/li>
&lt;/ul>
&lt;h3 id="63-hugo-构建失败front-matter-格式错误">6.3 Hugo 构建失败（Front Matter 格式错误）&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>现象&lt;/strong>：构建时报错 &lt;code>unmarshal failed: toml: expected character =&lt;/code>，导致网站无法更新。&lt;/li>
&lt;li>&lt;strong>原因&lt;/strong>：新建或修改的 Markdown 文件开头元数据格式有误（如误用 &lt;code>---&lt;/code> 代替 &lt;code>+++&lt;/code>，或缺少等号）。&lt;/li>
&lt;li>&lt;strong>解决方案&lt;/strong>：
&lt;ul>
&lt;li>确保文件开头是 &lt;code>+++&lt;/code>，每行格式如 &lt;code>key = &amp;quot;value&amp;quot;&lt;/code>。&lt;/li>
&lt;li>推送前用 &lt;code>hugo server -D&lt;/code> 本地预览，可提前发现错误。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>脚本保护&lt;/strong>：脚本在构建失败时会保留旧网站，避免 404。&lt;/li>
&lt;/ul>
&lt;h3 id="64-caddy-挂载失效目录-inode-变化">6.4 Caddy 挂载失效（目录 inode 变化）&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>现象&lt;/strong>：网站 404，但服务器上 &lt;code>public&lt;/code> 目录有文件，容器内 &lt;code>/var/www/blog&lt;/code> 为空。&lt;/li>
&lt;li>&lt;strong>原因&lt;/strong>：脚本用 &lt;code>sudo rm -rf&lt;/code> 删除旧目录再重建，导致目录 inode 变化，Docker 挂载指向了已删除的 inode。&lt;/li>
&lt;li>&lt;strong>解决方案&lt;/strong>：
&lt;ul>
&lt;li>改用 &lt;code>sudo rm -rf &amp;quot;$PUBLIC_DIR&amp;quot;/*&lt;/code> 清空内容而不删除目录本身（保留 inode）。&lt;/li>
&lt;li>或采用临时目录原子替换（当前脚本已使用 &lt;code>mv&lt;/code> 替换整个目录，但 &lt;code>mv&lt;/code> 后 inode 改变，仍需重启 Caddy）。因此脚本最后重启 Caddy 确保重新挂载。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>当前状态&lt;/strong>：脚本通过重启 Caddy 解决此问题，且只在有更新时重启，无更新时不重启。&lt;/li>
&lt;/ul>
&lt;h3 id="65-自动部署脚本误判更新">6.5 自动部署脚本误判更新&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>现象&lt;/strong>：即使无更新，脚本也执行构建和重启。&lt;/li>
&lt;li>&lt;strong>原因&lt;/strong>：早期脚本通过 &lt;code>git pull&lt;/code> 的输出判断更新，不够准确。&lt;/li>
&lt;li>&lt;strong>解决方案&lt;/strong>：改用 &lt;code>git fetch&lt;/code> 比较 commit hash（当前脚本已修复）。&lt;/li>
&lt;/ul>
&lt;h3 id="66-katex-公式不渲染">6.6 KaTeX 公式不渲染&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>现象&lt;/strong>：文章中的 &lt;code>$...$&lt;/code> 或 &lt;code>$$...$$&lt;/code> 未渲染为数学公式。&lt;/li>
&lt;li>&lt;strong>原因&lt;/strong>：KaTeX 脚本未正确加载或定界符未配置。&lt;/li>
&lt;li>&lt;strong>解决方案&lt;/strong>：
&lt;ul>
&lt;li>在 &lt;code>layouts/partials/math.html&lt;/code> 中添加 KaTeX 脚本和 &lt;code>renderMathInElement&lt;/code> 调用（已配置）。&lt;/li>
&lt;li>确保文章或全局开启了 &lt;code>math = true&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="七注意事项与最佳实践">七、注意事项与最佳实践&lt;/h2>
&lt;ol>
&lt;li>&lt;strong>绝对不要在服务器上直接修改文件&lt;/strong>（包括 &lt;code>nano&lt;/code> 编辑），所有更改都应在本地完成并推送。&lt;/li>
&lt;li>&lt;strong>绝对不要在 Gitee 网页上直接编辑文件&lt;/strong>，以免造成版本混乱。&lt;/li>
&lt;li>&lt;strong>推送前务必本地预览&lt;/strong>：&lt;code>hugo server -D&lt;/code> 检查格式和渲染。&lt;/li>
&lt;li>&lt;strong>新文章必须 &lt;code>git add&lt;/code>&lt;/strong>：新建文件后，先用 &lt;code>git status&lt;/code> 确认已加入版本控制。&lt;/li>
&lt;li>&lt;strong>定期查看服务器日志&lt;/strong>：&lt;code>tail -f /home/your-username/auto-deploy.log&lt;/code> 确保脚本正常运行。&lt;/li>
&lt;li>&lt;strong>如果需紧急修改服务器文件&lt;/strong>（不推荐），改完后必须立即 &lt;code>git commit&lt;/code> 并 &lt;code>git push&lt;/code>，然后在本地 &lt;code>git pull&lt;/code> 同步。&lt;/li>
&lt;/ol>
&lt;h2 id="八日常维护与更新指南">八、日常维护与更新指南&lt;/h2>
&lt;h3 id="81-写一篇新文章">8.1 写一篇新文章&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 本地&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd 本地博客路径
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>hugo new posts/文章名.md
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 编辑文章（修改 draft = false）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>hugo server -D &lt;span style="color:#75715e"># 预览&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 满意后&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git add .
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git commit -m &lt;span style="color:#e6db74">&amp;#34;新增文章：文章名&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git push
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="82-修改已有文章">8.2 修改已有文章&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 编辑文件后&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git commit -am &lt;span style="color:#e6db74">&amp;#34;更新文章：xxx&amp;#34;&lt;/span> &lt;span style="color:#75715e"># 针对已追踪文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git push
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="83-修改主题或配置">8.3 修改主题或配置&lt;/h3>
&lt;ul>
&lt;li>所有修改在本地进行，然后 &lt;code>git add/commit/push&lt;/code>。&lt;/li>
&lt;li>主题文件位于 &lt;code>themes/PaperMod/&lt;/code>，若有自定义覆盖，放在 &lt;code>layouts/&lt;/code> 或 &lt;code>assets/css/extended/&lt;/code>。&lt;/li>
&lt;/ul>
&lt;h3 id="84-升级-hugo-版本">8.4 升级 Hugo 版本&lt;/h3>
&lt;ul>
&lt;li>服务器上需手动下载新版 &lt;code>hugo&lt;/code> 二进制并替换 &lt;code>/usr/local/bin/hugo&lt;/code>。&lt;/li>
&lt;li>本地也需要同步升级，避免版本差异导致的构建问题。&lt;/li>
&lt;/ul>
&lt;h3 id="85-处理服务器故障">8.5 处理服务器故障&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Caddy 挂了&lt;/strong>：&lt;code>docker restart caddy&lt;/code> 或 &lt;code>cd ~/caddy &amp;amp;&amp;amp; docker-compose down &amp;amp;&amp;amp; docker-compose up -d&lt;/code>&lt;/li>
&lt;li>&lt;strong>磁盘空间满&lt;/strong>：检查日志大小，清理旧日志或无用的 Docker 镜像。&lt;/li>
&lt;li>&lt;strong>域名证书问题&lt;/strong>：Caddy 会自动续期，无需干预。&lt;/li>
&lt;/ul>
&lt;h2 id="九联系与备份">九、联系与备份&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>博客域名&lt;/strong>：&lt;code>https://lingzuian.top&lt;/code>（备案号：湘 ICP 备 2026005470 号）&lt;/li>
&lt;li>&lt;strong>Gitee 仓库&lt;/strong>：私有仓库，地址不公开&lt;/li>
&lt;li>&lt;strong>服务器&lt;/strong>：仅管理员 SSH 登录&lt;/li>
&lt;li>&lt;strong>数据备份&lt;/strong>：建议定期将 &lt;code>/home/your-username/blog/public&lt;/code> 和 &lt;code>/home/your-username/blog-source&lt;/code> 备份到 COS 或 Nextcloud。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;p>本概述涵盖了项目架构、配置、历史问题和维护要点。希望未来无论由谁（或哪个 AI）接手，都能快速理解并有效协助。&lt;/p></description></item></channel></rss>