<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>RGC Blog</title><description>代码、笔记与一些正在发生的想法</description><link>https://r-gc.github.io/</link><language>zh_CN</language><item><title>博客开始了</title><link>https://r-gc.github.io/posts/hello-blog/</link><guid isPermaLink="true">https://r-gc.github.io/posts/hello-blog/</guid><description>这个博客的第一篇记录，也算是给这个站点定一个方向。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这是这个博客的第一篇文章，也算是给它留一个起点。&lt;/p&gt;
&lt;p&gt;我不太想把它做成一个只摆成品的地方。更想让它像一个可以慢慢堆东西的工作台：项目做到一半的想法、某次配置踩过的坑、一个后来终于跑通的接口、或者某个突然想试试的页面效果，都可以先放进来。&lt;/p&gt;
&lt;p&gt;大概会先写这些内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;项目里真正值得回看的设计和问题&lt;/li&gt;
&lt;li&gt;平时用到的配置、命令和代码片段&lt;/li&gt;
&lt;li&gt;学习过程中还没完全吃透、但值得记录的东西&lt;/li&gt;
&lt;li&gt;一些带动画、音乐、视频或交互效果的小实验&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第一版先用 Astro 和 Fuwari 搭起来。它现在还很朴素，但这也挺好：先让内容有地方落脚，再一点点把样子和结构调成自己喜欢的状态。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const blog = {
  stack: [&quot;Astro&quot;, &quot;Fuwari&quot;, &quot;Markdown&quot;],
  purpose: &quot;write first, polish later&quot;,
};
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>在 Frappe / ERPNext 上折腾一个业务网关</title><link>https://r-gc.github.io/posts/project-frappe-erpnext-myapp/</link><guid isPermaLink="true">https://r-gc.github.io/posts/project-frappe-erpnext-myapp/</guid><description>记录 myapp 在 Frappe / ERPNext Docker 环境里的接口、前端、移动端和测试整理。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;一开始只是想把 Frappe / ERPNext 的 Docker 环境跑顺。跑起来之后，问题就变成了另一个：如果真的要围绕 ERPNext 做一个自己的业务系统，代码应该怎么组织才不至于越写越散？&lt;/p&gt;
&lt;p&gt;于是有了这个 &lt;code&gt;myapp&lt;/code&gt;。它现在更像一组持续整理中的实践：后端有自定义 App 和业务网关，前端有 Web 和移动端方向，旁边还放着接口集合、HTTP 测试和一些性能记录。&lt;/p&gt;
&lt;h2&gt;为什么要加一层网关&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;myapp&lt;/code&gt; 是一个基于 Frappe / ERPNext 的业务系统扩展。它没有直接让前端散落调用 ERPNext 原生接口，而是用 &lt;code&gt;myapp.api.gateway.*&lt;/code&gt; 组织出一层更稳定的业务网关。&lt;/p&gt;
&lt;p&gt;这层网关覆盖了商品、客户、销售、采购、供应商、结算、报表、媒体上传和移动端版本信息等能力。&lt;/p&gt;
&lt;p&gt;这样做的价值在于，前端看到的是业务动作，而不是 ERPNext 里面更底层的 DocType 细节：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;前端面对的是业务语义，而不是 ERPNext 的底层 DocType 细节&lt;/li&gt;
&lt;li&gt;错误码、响应格式和权限处理可以统一&lt;/li&gt;
&lt;li&gt;销售、采购等主链路可以围绕幂等和真实 HTTP 测试做回归&lt;/li&gt;
&lt;li&gt;后续替换图片存储、打印服务或移动端能力时，接口契约更稳定&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;现在的结构&lt;/h2&gt;
&lt;p&gt;从目录和文档看，项目大概分成三块：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;apps/myapp&lt;/code&gt;：自定义 Frappe App，放业务接口和测试&lt;/li&gt;
&lt;li&gt;&lt;code&gt;frontend/myapp-web&lt;/code&gt;：Web 管理端，基于 React、Umi Max、Ant Design Pro&lt;/li&gt;
&lt;li&gt;&lt;code&gt;frontend/myapp-mobile&lt;/code&gt;：移动端，基于 Expo、React Native、expo-router&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这让我比较在意的一点是：它不是只停留在后台配置页面，而是开始往“业务现场怎么用”这个方向走。比如移动端依赖里已经出现了相机、图片、打印、PDF、图表这些能力，这些都更接近收货、上传、查看和现场处理。&lt;/p&gt;
&lt;h2&gt;接口怎么组织&lt;/h2&gt;
&lt;p&gt;文档里把接口按业务域组织，而不是按“原生接口 / 自定义接口”划分。这一点很重要，因为调用方真正关心的是“销售要调哪些接口”“采购要调哪些接口”“报表要调哪些接口”。&lt;/p&gt;
&lt;p&gt;当前网关包含这些方向：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;商品搜索、商品创建、商品详情、图片上传&lt;/li&gt;
&lt;li&gt;客户与供应商主数据&lt;/li&gt;
&lt;li&gt;销售订单、发货、开票、收款、退货&lt;/li&gt;
&lt;li&gt;采购订单、收货、采购发票、供应商付款、采购退货&lt;/li&gt;
&lt;li&gt;经营总览、销售分析、采购分析、应收应付、资金流水&lt;/li&gt;
&lt;li&gt;移动端版本信息与认证&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接口返回也统一成类似这样的包络：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;ok&quot;: true,
  &quot;status&quot;: &quot;success&quot;,
  &quot;code&quot;: &quot;ORDER_CREATED&quot;,
  &quot;message&quot;: &quot;业务提示信息&quot;,
  &quot;data&quot;: {},
  &quot;meta&quot;: {}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;错误响应也做了统一错误码，例如认证、权限、资源不存在、库存不足、参数校验失败等。这个细节很容易被忽略，但对前端开发很友好：不用在每个页面里猜后端到底抛了什么异常。&lt;/p&gt;
&lt;h2&gt;采购链路里一个值得记的点&lt;/h2&gt;
&lt;p&gt;采购模块的设计文档比较完整。它把采购拆成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建采购订单&lt;/li&gt;
&lt;li&gt;按实际到货生成采购收货单&lt;/li&gt;
&lt;li&gt;按实际收货生成采购发票&lt;/li&gt;
&lt;li&gt;供应商付款登记&lt;/li&gt;
&lt;li&gt;采购退货&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里有一个关键设计原则：采购订单表示“预期采购”，真正库存入账以 &lt;code&gt;Purchase Receipt&lt;/code&gt; 为准。也就是说，如果供应商实际到货数量和订单数量不一致，系统应该允许按实收数量收货和结算。&lt;/p&gt;
&lt;p&gt;这比“采购订单一建就默认全部到货”的实现更接近真实业务。以后如果单独写采购模块，这个点值得展开讲。&lt;/p&gt;
&lt;h2&gt;测试体系&lt;/h2&gt;
&lt;p&gt;项目文档强调优先使用 HTTP 测试，而不是在宿主机里直接导入 Frappe 服务层。&lt;/p&gt;
&lt;p&gt;原因是 HTTP 测试更接近真实调用路径，可以覆盖：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;鉴权&lt;/li&gt;
&lt;li&gt;权限&lt;/li&gt;
&lt;li&gt;路由&lt;/li&gt;
&lt;li&gt;响应包装&lt;/li&gt;
&lt;li&gt;真实主数据&lt;/li&gt;
&lt;li&gt;devcontainer 网络环境&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;文档中记录了多组测试：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;销售与采购主链路&lt;/li&gt;
&lt;li&gt;商品工作台与销售状态聚合&lt;/li&gt;
&lt;li&gt;采购快捷链路&lt;/li&gt;
&lt;li&gt;幂等、并发和不同数据重放&lt;/li&gt;
&lt;li&gt;单位换算与库存结算回归&lt;/li&gt;
&lt;li&gt;性能基线脚本&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这部分我觉得很值得继续保留。很多项目写到后面乱，不只是代码问题，也是缺少一套能确认“这次改动没有把主链路弄坏”的方法。&lt;/p&gt;
&lt;h2&gt;接下来想补什么&lt;/h2&gt;
&lt;p&gt;这篇先把轮廓记下来。后面更值得写的是这些具体问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Frappe / ERPNext 自定义业务网关设计&lt;/li&gt;
&lt;li&gt;采购链路如何处理“订单数量”和“实际到货”的差异&lt;/li&gt;
&lt;li&gt;移动端如何对接 ERPNext 业务接口&lt;/li&gt;
&lt;li&gt;商品图片上传、临时文件绑定和清理策略&lt;/li&gt;
&lt;li&gt;HTTP 测试如何覆盖 ERPNext 自定义接口&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;目前最应该补的，是截图和一条完整业务链路的可视化流程图。只有文字会有点干，等把图补上，这个项目才会更像一篇可以回看的博客文章。&lt;/p&gt;
</content:encoded></item><item><title>这个博客是怎么搭起来的</title><link>https://r-gc.github.io/posts/project-rgc-blog-architecture/</link><guid isPermaLink="true">https://r-gc.github.io/posts/project-rgc-blog-architecture/</guid><description>从选 Astro、Fuwari，到部署到 Cloudflare Workers，记录这个博客的第一版。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这个站点现在还很早期，但总算从“想弄个博客”变成了“已经有地方可以写东西”。&lt;/p&gt;
&lt;p&gt;我对它的期待不是一次性做成一个很完整的网站，而是先把结构搭出来，然后边写边改。技术文章、项目记录、学习笔记、代码片段，还有一些动画、音乐、视频相关的小实验，都可以慢慢往里放。&lt;/p&gt;
&lt;h2&gt;为什么选这套&lt;/h2&gt;
&lt;p&gt;第一版选的是 Astro + Fuwari。&lt;/p&gt;
&lt;p&gt;Astro 适合内容型站点。默认静态生成，部署简单，后面如果想加一些交互组件，也不用把整个博客变成一个复杂的前端应用。&lt;/p&gt;
&lt;p&gt;Fuwari 则省掉了很多博客基础设施：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;首页文章流&lt;/li&gt;
&lt;li&gt;文章详情&lt;/li&gt;
&lt;li&gt;归档&lt;/li&gt;
&lt;li&gt;分类和标签&lt;/li&gt;
&lt;li&gt;搜索&lt;/li&gt;
&lt;li&gt;深色模式&lt;/li&gt;
&lt;li&gt;页面转场&lt;/li&gt;
&lt;li&gt;RSS 和 sitemap&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些东西自己从零写当然也能做，但博客的第一目标还是写内容。先用一个成熟主题把底座搭好，会更容易进入“开始写”的状态。&lt;/p&gt;
&lt;h2&gt;现在怎么部署&lt;/h2&gt;
&lt;p&gt;当前部署链路是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;本地开发
  -&amp;gt; git push
  -&amp;gt; GitHub 仓库
  -&amp;gt; Cloudflare Workers 构建部署
  -&amp;gt; blog.rgcdev.top
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同时保留 GitHub Pages：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GitHub Actions
  -&amp;gt; pnpm build
  -&amp;gt; dist
  -&amp;gt; r-gc.github.io
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样做的好处是：主站可以走 Cloudflare，自定义域名和后续 R2 / Workers 能力都在一个体系里；GitHub Pages 则作为备用访问和对照环境。&lt;/p&gt;
&lt;h2&gt;先把栏目放出来&lt;/h2&gt;
&lt;p&gt;现在先放了几个顶层栏目：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;首页：最新文章&lt;/li&gt;
&lt;li&gt;归档：按时间、分类、标签浏览&lt;/li&gt;
&lt;li&gt;项目：记录做过、正在做、还想继续整理的东西&lt;/li&gt;
&lt;li&gt;笔记：保存短内容、配置备忘和学习记录&lt;/li&gt;
&lt;li&gt;实验室：放动画、音乐、视频和交互 demo&lt;/li&gt;
&lt;li&gt;关于：个人介绍和站点说明&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;项目页目前是数据驱动的，项目数据统一放在 &lt;code&gt;src/data/projects.ts&lt;/code&gt;。这不是为了炫技，只是为了以后新增项目时不用每次都改页面结构。&lt;/p&gt;
&lt;h2&gt;第一版先到这里&lt;/h2&gt;
&lt;p&gt;第一版已经完成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;站点初始化&lt;/li&gt;
&lt;li&gt;中文配置&lt;/li&gt;
&lt;li&gt;Cloudflare Workers 部署&lt;/li&gt;
&lt;li&gt;GitHub Pages 备用部署&lt;/li&gt;
&lt;li&gt;自定义域名&lt;/li&gt;
&lt;li&gt;项目、笔记、实验室栏目&lt;/li&gt;
&lt;li&gt;项目页数据化&lt;/li&gt;
&lt;li&gt;第一批项目复盘文章&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;后面会慢慢补：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;替换头像和 favicon&lt;/li&gt;
&lt;li&gt;补真实项目截图&lt;/li&gt;
&lt;li&gt;为重点项目建立详情页&lt;/li&gt;
&lt;li&gt;优化首页布局&lt;/li&gt;
&lt;li&gt;增加音乐和视频实验&lt;/li&gt;
&lt;li&gt;把大图和媒体资源迁移到 Cloudflare R2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现在最重要的不是把页面一次性做漂亮，而是开始积累内容。样式、结构、动画和媒体能力都可以跟着内容慢慢长出来。&lt;/p&gt;
</content:encoded></item><item><title>这个博客的笔记结构</title><link>https://r-gc.github.io/posts/notes/blog-note-architecture/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/blog-note-architecture/</guid><description>先给笔记系统定一个轻量规则：分类保持简单，标签负责表达主题和用途。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这个博客会以笔记为主，所以先把笔记的结构定下来。&lt;/p&gt;
&lt;p&gt;第一版不打算做得太复杂。Fuwari 本身已经有文章、归档、标签、分类、搜索和 RSS。与其重新做一套知识库系统，不如先复用它的文章模型，再用一点约定把内容组织清楚。&lt;/p&gt;
&lt;h2&gt;分类只回答一件事&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;category&lt;/code&gt; 只用来说明这篇内容属于哪种大类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;笔记&lt;/li&gt;
&lt;li&gt;项目&lt;/li&gt;
&lt;li&gt;博客&lt;/li&gt;
&lt;li&gt;实验&lt;/li&gt;
&lt;li&gt;随笔&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这样分类不会越来越碎。比如一篇 Cloudflare Workers 部署记录，它的分类是“笔记”，而不是“Cloudflare”。&lt;/p&gt;
&lt;h2&gt;标签负责具体主题&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;tags&lt;/code&gt; 用来描述具体内容和用途：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Cloudflare&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Workers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;部署&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;排错&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Frappe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Docker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;速查&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以后想按技术栈、问题类型或者使用场景找内容，都可以靠标签。&lt;/p&gt;
&lt;h2&gt;笔记类型&lt;/h2&gt;
&lt;p&gt;当前先按这些类型整理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;速查：命令、参数、步骤和常用片段&lt;/li&gt;
&lt;li&gt;排错：报错原因、排查路径和最后的修复方法&lt;/li&gt;
&lt;li&gt;配置：环境、工具链、部署和服务配置&lt;/li&gt;
&lt;li&gt;学习：读文档、看源码、学框架时留下的理解&lt;/li&gt;
&lt;li&gt;项目笔记：项目推进过程里的设计、接口、测试和取舍&lt;/li&gt;
&lt;li&gt;阅读摘记：文章、文档、书和资料里值得回看的内容&lt;/li&gt;
&lt;li&gt;实验记录：动画、音乐、视频和交互效果的试验过程&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些类型目前先作为标签使用。等内容多起来之后，再决定要不要单独做成更强的字段。&lt;/p&gt;
&lt;h2&gt;写作原则&lt;/h2&gt;
&lt;p&gt;笔记不追求一次写成完美文章。&lt;/p&gt;
&lt;p&gt;对这个博客来说，更重要的是先把有用的信息放下来：当时的问题是什么，怎么查的，最后怎么解决，以及下次遇到时应该从哪里开始。&lt;/p&gt;
&lt;p&gt;如果一篇短笔记后来变得很重要，再把它扩展成完整文章也不迟。&lt;/p&gt;
</content:encoded></item><item><title>Cloudflare Workers 部署博客的记录</title><link>https://r-gc.github.io/posts/notes/cloudflare-workers-deploy-note/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/cloudflare-workers-deploy-note/</guid><description>记录这个 Astro 博客接入 Cloudflare Workers Static Assets 时用到的构建和部署配置。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这个博客目前主部署放在 Cloudflare Workers，GitHub Pages 作为备用。&lt;/p&gt;
&lt;p&gt;当前 Cloudflare 侧的构建命令是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm run build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;部署命令是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx wrangler deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;项目里保留了 &lt;code&gt;wrangler.jsonc&lt;/code&gt;，核心配置是把 Astro 构建后的 &lt;code&gt;dist&lt;/code&gt; 作为静态资源目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;r-gc-github-io&quot;,
  &quot;compatibility_date&quot;: &quot;2026-05-20&quot;,
  &quot;assets&quot;: {
    &quot;directory&quot;: &quot;./dist/&quot;,
    &quot;not_found_handling&quot;: &quot;404-page&quot;,
    &quot;html_handling&quot;: &quot;auto-trailing-slash&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;后续如果接入 R2 放图片、音频或视频，Workers 会比单纯 GitHub Pages 更方便一些。现在先保持静态博客形态，等媒体资源真的多起来再迁移。&lt;/p&gt;
</content:encoded></item><item><title>Git 代理配置速查</title><link>https://r-gc.github.io/posts/notes/git-ssh/git-proxy-config/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/git-ssh/git-proxy-config/</guid><description>记录 Git HTTP/HTTPS 代理的设置、查看、取消和按域名配置方式。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 Git 代理相关命令。&lt;/p&gt;
&lt;h2&gt;查看当前 Git 代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;git config --global --get http.proxy
git config --global --get https.proxy
git config --show-origin --get http.proxy
git config --show-origin --get https.proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看所有代理相关配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config --global --list | grep -i proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;设置 HTTP/HTTPS 代理&lt;/h2&gt;
&lt;p&gt;HTTP 代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config --global http.proxy http://127.0.0.1:10808
git config --global https.proxy http://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SOCKS5 代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config --global http.proxy socks5://127.0.0.1:10808
git config --global https.proxy socks5://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果代理软件同时提供 HTTP 和 SOCKS5 端口，Git 的 HTTP/HTTPS 拉取通常用 HTTP 代理更直接。&lt;/p&gt;
&lt;h2&gt;只给 GitHub 设置代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;git config --global http.https://github.com.proxy http://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消 GitHub 单独代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config --global --unset http.https://github.com.proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种写法只影响访问 &lt;code&gt;https://github.com&lt;/code&gt; 的 Git HTTP 请求。&lt;/p&gt;
&lt;h2&gt;取消全局代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;git config --global --unset http.proxy
git config --global --unset https.proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果不确定是否存在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config --global --unset-all http.proxy
git config --global --unset-all https.proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;临时使用代理执行一次 Git 命令&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;git -c http.proxy=http://127.0.0.1:10808 -c https.proxy=http://127.0.0.1:10808 pull
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个不会写入配置文件，只对这一次命令生效。&lt;/p&gt;
&lt;h2&gt;注意 SSH remote 不走 Git HTTP 代理&lt;/h2&gt;
&lt;p&gt;如果 remote 是 HTTPS：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://github.com/USER/REPO.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git 的 &lt;code&gt;http.proxy&lt;/code&gt; / &lt;code&gt;https.proxy&lt;/code&gt; 会生效。&lt;/p&gt;
&lt;p&gt;如果 remote 是 SSH：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git@github.com:USER/REPO.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git 的 HTTP 代理不会生效，需要配置 SSH 代理，也就是 &lt;code&gt;~/.ssh/config&lt;/code&gt; 里的 &lt;code&gt;ProxyCommand&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;http.proxy&lt;/code&gt;：Git 访问 HTTP 地址时使用的代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https.proxy&lt;/code&gt;：Git 访问 HTTPS 地址时使用的代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;http.https://github.com.proxy&lt;/code&gt;：只给指定 URL 前缀设置代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--get&lt;/code&gt;：只读取某个配置值。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--unset&lt;/code&gt;：删除某个配置值。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--unset-all&lt;/code&gt;：删除同名配置的所有值。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-c key=value&lt;/code&gt;：只在当前这次 Git 命令里临时覆盖配置。&lt;/p&gt;
</content:encoded></item><item><title>SSH 密钥生成与 GitHub 配置速查</title><link>https://r-gc.github.io/posts/notes/git-ssh/ssh-key-generation/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/git-ssh/ssh-key-generation/</guid><description>记录生成 SSH key、启动 ssh-agent、添加公钥到 GitHub 和测试连接的常用命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 SSH key 相关命令。&lt;/p&gt;
&lt;h2&gt;生成 ed25519 key&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ssh-keygen -t ed25519 -C &quot;you@example.com&quot; -f ~/.ssh/id_ed25519_github
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果是给另一个 GitHub 账号单独生成 key，可以换文件名：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-keygen -t ed25519 -C &quot;blog@example.com&quot; -f ~/.ssh/id_ed25519_r_gc
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看公钥&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;cat ~/.ssh/id_ed25519_github.pub
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;把输出内容复制到 GitHub：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GitHub -&amp;gt; Settings -&amp;gt; SSH and GPG keys -&amp;gt; New SSH key
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意复制的是 &lt;code&gt;.pub&lt;/code&gt; 公钥，不是没有后缀的私钥。&lt;/p&gt;
&lt;h2&gt;公钥放到目标服务器&lt;/h2&gt;
&lt;p&gt;原则很简单：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;私钥留在访问方
公钥放到被访问方
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;比如从自己的电脑访问一台 Linux 服务器，就在自己的电脑生成 key，然后把 &lt;code&gt;.pub&lt;/code&gt; 公钥放到目标服务器对应用户的：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果目标登录用户是 &lt;code&gt;deploy&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/home/deploy/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果目标登录用户是 &lt;code&gt;root&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/root/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;快捷添加公钥&lt;/h2&gt;
&lt;p&gt;本机执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-copy-id -i ~/.ssh/id_ed25519_github.pub user@server_ip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定 SSH 端口：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-copy-id -i ~/.ssh/id_ed25519_github.pub -p 2222 user@server_ip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它会自动把公钥追加到目标服务器的：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第一次执行通常需要输入目标服务器用户密码，因为此时目标服务器还没有你的公钥，只能先用密码登录一次。&lt;/p&gt;
&lt;p&gt;成功后测试：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh user@server_ip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你的私钥设置了 passphrase，后续登录时可能还会输入私钥密码。这个不是服务器用户密码。&lt;/p&gt;
&lt;p&gt;如果服务器已经禁用了密码登录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PasswordAuthentication no
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那么 &lt;code&gt;ssh-copy-id&lt;/code&gt; 也无法用密码进去。此时只能通过云厂商控制台、已有可登录账号、服务器面板，或者让管理员帮你把公钥放进去。&lt;/p&gt;
&lt;h2&gt;已登录服务器后手动添加&lt;/h2&gt;
&lt;p&gt;如果你已经登录到了目标服务器，可以直接在服务器上追加公钥。&lt;/p&gt;
&lt;p&gt;先在本机查看并复制公钥：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat ~/.ssh/id_ed25519_github.pub
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;复制整行内容，格式类似：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... you@example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后在目标服务器上执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -p ~/.ssh
chmod 700 ~/.ssh
cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;粘贴刚才复制的公钥整行，回车，然后按 &lt;code&gt;Ctrl + D&lt;/code&gt; 结束输入。&lt;/p&gt;
&lt;p&gt;最后设置权限：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;chmod 600 ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以用 &lt;code&gt;echo&lt;/code&gt; 一行追加：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo &apos;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... you@example.com&apos; &amp;gt;&amp;gt; ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意使用 &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;，不要随手用 &lt;code&gt;&amp;gt;&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt; 追加，不会删除原有 key
&amp;gt;  覆盖，会清空 authorized_keys 里的原有 key
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果确定要重建整个 &lt;code&gt;authorized_keys&lt;/code&gt;，才使用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo &apos;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... you@example.com&apos; &amp;gt; ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;设置权限&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519_github
chmod 644 ~/.ssh/id_ed25519_github.pub
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果权限太开放，SSH 可能会拒绝使用私钥。&lt;/p&gt;
&lt;h2&gt;启动 ssh-agent 并添加 key&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;eval &quot;$(ssh-agent -s)&quot;
ssh-add ~/.ssh/id_ed25519_github
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 agent 里已有 key：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-add -l
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;从 agent 删除某个 key：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-add -d ~/.ssh/id_ed25519_github
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;清空 agent 中所有 key：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-add -D
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;测试 GitHub SSH&lt;/h2&gt;
&lt;p&gt;普通测试：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh -T git@github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果 &lt;code&gt;~/.ssh/config&lt;/code&gt; 里配置了 Host 别名：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh -T git@github-r-gc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;成功时通常会看到类似：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Hi USER! You&apos;ve successfully authenticated, but GitHub does not provide shell access.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ssh-keygen&lt;/code&gt;：生成 SSH 密钥。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-t ed25519&lt;/code&gt;：指定密钥算法。现在一般优先用 ed25519。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-C &quot;you@example.com&quot;&lt;/code&gt;：给 key 加注释，常用邮箱或用途，方便以后识别。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-f ~/.ssh/id_ed25519_github&lt;/code&gt;：指定生成文件路径和文件名。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.pub&lt;/code&gt;：公钥文件，可以上传到 GitHub。&lt;/p&gt;
&lt;p&gt;没有 &lt;code&gt;.pub&lt;/code&gt; 后缀的文件：私钥文件，不能公开。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ssh-agent&lt;/code&gt;：本地密钥代理，可以记住已添加的私钥。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ssh-add&lt;/code&gt;：把私钥加入 agent。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ssh -T&lt;/code&gt;：测试 SSH 认证，不打开远程 shell。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;authorized_keys&lt;/code&gt;：目标服务器上保存允许登录的公钥列表。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ssh-copy-id&lt;/code&gt;：把本机公钥复制到目标服务器 &lt;code&gt;authorized_keys&lt;/code&gt; 的快捷命令。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;：追加内容到文件末尾，适合给 &lt;code&gt;authorized_keys&lt;/code&gt; 增加新公钥。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;：覆盖文件内容，可能删除已有公钥，谨慎使用。&lt;/p&gt;
</content:encoded></item><item><title>SSH 代理与多 GitHub 账号配置速查</title><link>https://r-gc.github.io/posts/notes/git-ssh/ssh-proxy-and-config/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/git-ssh/ssh-proxy-and-config/</guid><description>记录 SSH config、ProxyCommand、GitHub 443 端口、多账号 Host 别名和常用参数。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 SSH 代理和多账号配置。&lt;/p&gt;
&lt;h2&gt;基础 GitHub SSH 配置&lt;/h2&gt;
&lt;p&gt;编辑：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nano ~/.ssh/config
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;普通 GitHub SSH：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_github
  IdentitiesOnly yes
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;GitHub SSH 走 443 端口&lt;/h2&gt;
&lt;p&gt;有些网络环境下，22 端口不稳定，可以改用 GitHub 提供的 SSH over HTTPS 端口：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Host github.com
  HostName ssh.github.com
  User git
  Port 443
  IdentityFile ~/.ssh/id_ed25519_github
  IdentitiesOnly yes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh -T git@github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;SSH 通过 SOCKS5 代理（本地代理环境推荐）&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Host github.com
  HostName ssh.github.com
  User git
  Port 443
  IdentityFile ~/.ssh/id_ed25519_github
  IdentitiesOnly yes
  ProxyCommand nc -X 5 -x 127.0.0.1:10808 %h %p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里适合本地代理监听在 &lt;code&gt;127.0.0.1:10808&lt;/code&gt; 的情况。&lt;/p&gt;
&lt;h2&gt;多 GitHub 账号 Host 别名&lt;/h2&gt;
&lt;p&gt;默认账号：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Host github.com
  HostName ssh.github.com
  User git
  Port 443
  IdentityFile ~/.ssh/id_ed25519_github
  IdentitiesOnly yes
  ProxyCommand nc -X 5 -x 127.0.0.1:10808 %h %p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;博客账号：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Host github-r-gc
  HostName ssh.github.com
  User git
  Port 443
  IdentityFile ~/.ssh/id_ed25519_r_gc
  IdentitiesOnly yes
  ProxyCommand nc -X 5 -x 127.0.0.1:10808 %h %p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用别名测试：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh -T git@github-r-gc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;仓库 remote 使用别名：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git remote set-url origin git@github-r-gc:r-gc/r-gc.github.io.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样默认 &lt;code&gt;github.com&lt;/code&gt; 可以继续给主力账号使用，&lt;code&gt;github-r-gc&lt;/code&gt; 专门给博客账号使用。&lt;/p&gt;
&lt;h2&gt;查看 SSH 实际使用的配置&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ssh -G github.com | less
ssh -G github-r-gc | less
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;调试连接过程：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh -vT git@github.com
ssh -vT git@github-r-gc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果信息不够，再增加 &lt;code&gt;v&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh -vvvT git@github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Host&lt;/code&gt;：本地别名。Git remote 里写的主机名会匹配它。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;HostName&lt;/code&gt;：真实连接的服务器地址。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;User git&lt;/code&gt;：GitHub SSH 固定使用 &lt;code&gt;git&lt;/code&gt; 用户。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Port 443&lt;/code&gt;：使用 443 端口连接 GitHub SSH，适合 22 端口不通或不稳定时。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;IdentityFile&lt;/code&gt;：指定私钥路径。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;IdentitiesOnly yes&lt;/code&gt;：只使用 &lt;code&gt;IdentityFile&lt;/code&gt; 指定的 key，避免 SSH 尝试一堆其它 key。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ProxyCommand&lt;/code&gt;：连接目标服务器前，先通过这个命令建立网络通道。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nc&lt;/code&gt;：netcat，用来建立代理连接。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-X 5&lt;/code&gt;：告诉 &lt;code&gt;nc&lt;/code&gt; 使用 SOCKS5 代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-x 127.0.0.1:10808&lt;/code&gt;：指定代理地址和端口。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;%h&lt;/code&gt;：SSH 会替换成目标主机，也就是 &lt;code&gt;HostName&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;%p&lt;/code&gt;：SSH 会替换成目标端口，也就是 &lt;code&gt;Port&lt;/code&gt;。&lt;/p&gt;
</content:encoded></item><item><title>Git 多账号配置速查</title><link>https://r-gc.github.io/posts/notes/git-ssh/git-account-config/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/git-ssh/git-account-config/</guid><description>记录 Git 全局账号、单仓库账号、远程地址和多 GitHub 账号的常用配置命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 Git 账号相关命令。&lt;/p&gt;
&lt;h2&gt;查看当前配置&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;git config --list
git config --global --list
git config --local --list
git config --show-origin --list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;--show-origin&lt;/code&gt; 会显示配置来自哪个文件，排查“为什么这个仓库用错账号”时很有用。&lt;/p&gt;
&lt;h2&gt;设置全局账号&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;git config --global user.name &quot;Your Name&quot;
git config --global user.email &quot;you@example.com&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;全局配置会写入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.gitconfig
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;适合主力账号。比如一台机器主要用 &lt;code&gt;rgc318&lt;/code&gt; 工作，就把全局账号设成 &lt;code&gt;rgc318&lt;/code&gt; 对应的用户名和邮箱。&lt;/p&gt;
&lt;h2&gt;设置当前仓库账号&lt;/h2&gt;
&lt;p&gt;在仓库目录里执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config user.name &quot;Blog Account&quot;
git config user.email &quot;blog@example.com&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这会写入当前仓库的：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.git/config
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;适合某个仓库需要使用另一个身份的情况。&lt;/p&gt;
&lt;h2&gt;查看某个配置最终生效值&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;git config user.name
git config user.email
git config --show-origin user.name
git config --show-origin user.email
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Git 配置优先级大致是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;仓库 local &amp;gt; 用户 global &amp;gt; 系统 system
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以仓库里设置过 &lt;code&gt;user.name&lt;/code&gt;，就会覆盖全局配置。&lt;/p&gt;
&lt;h2&gt;修改远程仓库地址&lt;/h2&gt;
&lt;p&gt;查看远程地址：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git remote -v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;改成普通 GitHub SSH 地址：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git remote set-url origin git@github.com:USER/REPO.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;改成 HTTPS 地址：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git remote set-url origin https://github.com/USER/REPO.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;改成 SSH Host 别名地址：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git remote set-url origin git@github-r-gc:r-gc/r-gc.github.io.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里的 &lt;code&gt;github-r-gc&lt;/code&gt; 不是 GitHub 官方域名，而是 &lt;code&gt;~/.ssh/config&lt;/code&gt; 里自己定义的 Host 别名。&lt;/p&gt;
&lt;h2&gt;单仓库指定 SSH key&lt;/h2&gt;
&lt;p&gt;在仓库目录里执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config core.sshCommand &quot;ssh -i ~/.ssh/id_ed25519_r_gc -o IdentitiesOnly=yes&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看是否生效：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config --local core.sshCommand
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config --unset core.sshCommand
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个方式适合“默认 GitHub 账号保持主力账号，但某个仓库固定使用另一把 key”。&lt;/p&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;--global&lt;/code&gt;：写入当前用户的全局 Git 配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--local&lt;/code&gt;：只看或只改当前仓库配置。默认在仓库中执行 &lt;code&gt;git config&lt;/code&gt; 时就是 local。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--show-origin&lt;/code&gt;：显示配置来源文件，排查配置覆盖时常用。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;remote set-url&lt;/code&gt;：修改已有 remote 的 URL，不会重建 remote。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;core.sshCommand&lt;/code&gt;：让当前仓库执行 Git SSH 操作时使用指定 SSH 命令。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-i ~/.ssh/id_ed25519_r_gc&lt;/code&gt;：指定 SSH 私钥文件。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-o IdentitiesOnly=yes&lt;/code&gt;：只使用显式指定的 key，避免 SSH 把其它 key 也拿去尝试。&lt;/p&gt;
</content:encoded></item><item><title>终端代理与 curl / wget 配置速查</title><link>https://r-gc.github.io/posts/notes/proxy/shell-curl-wget-proxy/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/proxy/shell-curl-wget-proxy/</guid><description>记录 shell 环境变量代理、临时代理、curl 代理、wget 代理和 no_proxy 的常用写法。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制终端代理相关命令。&lt;/p&gt;
&lt;h2&gt;临时设置终端代理&lt;/h2&gt;
&lt;p&gt;HTTP 代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export http_proxy=http://127.0.0.1:10808
export https_proxy=http://127.0.0.1:10808
export HTTP_PROXY=http://127.0.0.1:10808
export HTTPS_PROXY=http://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SOCKS5 代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export all_proxy=socks5://127.0.0.1:10808
export ALL_PROXY=socks5://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常见组合：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export http_proxy=http://127.0.0.1:10808
export https_proxy=http://127.0.0.1:10808
export all_proxy=socks5://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这些只对当前终端会话生效。新开终端后需要重新设置。&lt;/p&gt;
&lt;h2&gt;取消终端代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;unset http_proxy
unset https_proxy
unset HTTP_PROXY
unset HTTPS_PROXY
unset all_proxy
unset ALL_PROXY
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看当前代理环境变量&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;env | grep -i proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo &quot;$http_proxy&quot;
echo &quot;$https_proxy&quot;
echo &quot;$all_proxy&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;设置不走代理的地址&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;export no_proxy=localhost,127.0.0.1,::1
export NO_PROXY=localhost,127.0.0.1,::1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果要让局域网地址也不走代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export no_proxy=localhost,127.0.0.1,::1,192.168.0.0/16,10.0.0.0/8
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;单次命令使用代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;http_proxy=http://127.0.0.1:10808 https_proxy=http://127.0.0.1:10808 curl https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不污染当前终端，适合临时测试。&lt;/p&gt;
&lt;h2&gt;curl 使用代理&lt;/h2&gt;
&lt;p&gt;HTTP 代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -x http://127.0.0.1:10808 https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SOCKS5 代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -x socks5://127.0.0.1:10808 https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;让 DNS 也通过 SOCKS5 代理解析：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -x socks5h://127.0.0.1:10808 https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看连接细节：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -v -x http://127.0.0.1:10808 https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只看响应头：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -I -x http://127.0.0.1:10808 https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;wget 使用代理&lt;/h2&gt;
&lt;p&gt;单次命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wget -e use_proxy=yes -e http_proxy=http://127.0.0.1:10808 -e https_proxy=http://127.0.0.1:10808 https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;写入用户配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nano ~/.wgetrc
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;use_proxy = on
http_proxy = http://127.0.0.1:10808
https_proxy = http://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;http_proxy&lt;/code&gt;：HTTP 请求使用的代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https_proxy&lt;/code&gt;：HTTPS 请求使用的代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;all_proxy&lt;/code&gt;：所有协议的通用代理，常用于 SOCKS5。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;no_proxy&lt;/code&gt;：不走代理的主机或地址。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -x&lt;/code&gt;：给当前 curl 请求指定代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;socks5://&lt;/code&gt;：使用 SOCKS5 代理，但 DNS 可能仍在本地解析。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;socks5h://&lt;/code&gt;：使用 SOCKS5 代理，并让代理端解析 DNS。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -v&lt;/code&gt;：输出详细连接过程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -I&lt;/code&gt;：只请求响应头。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;wget -e&lt;/code&gt;：临时设置 wget 配置项。&lt;/p&gt;
</content:encoded></item><item><title>npm / pnpm / yarn 代理与镜像配置速查</title><link>https://r-gc.github.io/posts/notes/proxy/node-package-manager-proxy/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/proxy/node-package-manager-proxy/</guid><description>记录 Node 包管理器的代理、registry、查看配置和取消配置命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 Node 包管理器相关配置。&lt;/p&gt;
&lt;h2&gt;npm 查看配置&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;npm config list
npm config get proxy
npm config get https-proxy
npm config get registry
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;npm 设置代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;npm config set proxy http://127.0.0.1:10808
npm config set https-proxy http://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm config delete proxy
npm config delete https-proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;npm 设置 registry&lt;/h2&gt;
&lt;p&gt;官方源：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm config set registry https://registry.npmjs.org/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;国内镜像：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm config set registry https://registry.npmmirror.com/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm config get registry
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;pnpm 查看配置&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;pnpm config list
pnpm config get proxy
pnpm config get https-proxy
pnpm config get registry
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;pnpm 设置代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;pnpm config set proxy http://127.0.0.1:10808
pnpm config set https-proxy http://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm config delete proxy
pnpm config delete https-proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;pnpm 设置 registry&lt;/h2&gt;
&lt;p&gt;官方源：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm config set registry https://registry.npmjs.org/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;国内镜像：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm config set registry https://registry.npmmirror.com/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm config get registry
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;yarn 查看与设置&lt;/h2&gt;
&lt;p&gt;查看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn config get proxy
yarn config get https-proxy
yarn config get registry
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;设置代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn config set proxy http://127.0.0.1:10808
yarn config set https-proxy http://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn config delete proxy
yarn config delete https-proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;设置 registry：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn config set registry https://registry.npmjs.org/
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;使用环境变量临时代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;http_proxy=http://127.0.0.1:10808 https_proxy=http://127.0.0.1:10808 pnpm install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;HTTP_PROXY=http://127.0.0.1:10808 HTTPS_PROXY=http://127.0.0.1:10808 npm install
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用配置文件位置&lt;/h2&gt;
&lt;p&gt;npm 用户配置通常在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.npmrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;pnpm 也会读取 npm 兼容配置。可以直接查看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat ~/.npmrc
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;proxy&lt;/code&gt;：HTTP 请求代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https-proxy&lt;/code&gt;：HTTPS 请求代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;registry&lt;/code&gt;：包下载源地址。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;config set&lt;/code&gt;：写入配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;config get&lt;/code&gt;：读取配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;config delete&lt;/code&gt;：删除配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;registry.npmjs.org&lt;/code&gt;：npm 官方源。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;registry.npmmirror.com&lt;/code&gt;：常用 npm 国内镜像源。&lt;/p&gt;
</content:encoded></item><item><title>pip / apt / Docker 代理配置速查</title><link>https://r-gc.github.io/posts/notes/proxy/python-apt-docker-proxy/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/proxy/python-apt-docker-proxy/</guid><description>记录 Python pip、Ubuntu apt 和 Docker 的代理配置、查看与取消方式。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 pip、apt 和 Docker 代理配置。&lt;/p&gt;
&lt;h2&gt;pip 临时使用代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;pip install requests --proxy http://127.0.0.1:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定源：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pip install requests -i https://pypi.org/simple
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定国内镜像：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;pip 写入用户配置&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;pip config set global.proxy http://127.0.0.1:10808
pip config set global.index-url https://pypi.org/simple
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pip config list
pip config debug
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pip config unset global.proxy
pip config unset global.index-url
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常见用户配置文件位置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.config/pip/pip.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;apt 临时使用代理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo apt -o Acquire::http::Proxy=&quot;http://127.0.0.1:10808&quot; update
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同时设置 HTTP 和 HTTPS：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt \
  -o Acquire::http::Proxy=&quot;http://127.0.0.1:10808&quot; \
  -o Acquire::https::Proxy=&quot;http://127.0.0.1:10808&quot; \
  update
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;apt 写入代理配置&lt;/h2&gt;
&lt;p&gt;创建配置文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/apt/apt.conf.d/95proxies
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;写入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Acquire::http::Proxy &quot;http://127.0.0.1:10808&quot;;
Acquire::https::Proxy &quot;http://127.0.0.1:10808&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo rm /etc/apt/apt.conf.d/95proxies
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果代理在 Windows 主机上，WSL 里 &lt;code&gt;127.0.0.1&lt;/code&gt; 是否可用取决于网络模式和代理软件监听地址；不通时可以改用 Windows 主机 IP。&lt;/p&gt;
&lt;h2&gt;Docker CLI 代理&lt;/h2&gt;
&lt;p&gt;创建 Docker 客户端配置目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -p ~/.docker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;编辑：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nano ~/.docker/config.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;写入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;proxies&quot;: {
    &quot;default&quot;: {
      &quot;httpProxy&quot;: &quot;http://127.0.0.1:10808&quot;,
      &quot;httpsProxy&quot;: &quot;http://127.0.0.1:10808&quot;,
      &quot;noProxy&quot;: &quot;localhost,127.0.0.1,::1&quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个配置主要影响 Docker 客户端给容器传递的代理环境。&lt;/p&gt;
&lt;h2&gt;Docker daemon 代理&lt;/h2&gt;
&lt;p&gt;创建 systemd drop-in 目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo mkdir -p /etc/systemd/system/docker.service.d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;编辑：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;写入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Service]
Environment=&quot;HTTP_PROXY=http://127.0.0.1:10808&quot;
Environment=&quot;HTTPS_PROXY=http://127.0.0.1:10808&quot;
Environment=&quot;NO_PROXY=localhost,127.0.0.1,::1&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重载并重启 Docker：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl restart docker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 Docker 服务环境变量：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl show --property=Environment docker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消 Docker daemon 代理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo rm /etc/systemd/system/docker.service.d/http-proxy.conf
sudo systemctl daemon-reload
sudo systemctl restart docker
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;pip --proxy&lt;/code&gt;：只给当前 pip 命令指定代理。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip config set global.proxy&lt;/code&gt;：写入 pip 用户配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip config debug&lt;/code&gt;：显示 pip 会读取哪些配置文件。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;apt -o&lt;/code&gt;：只给当前 apt 命令临时覆盖配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Acquire::http::Proxy&lt;/code&gt;：apt 的 HTTP 代理配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Acquire::https::Proxy&lt;/code&gt;：apt 的 HTTPS 代理配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/.docker/config.json&lt;/code&gt;：Docker CLI 用户配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker.service.d&lt;/code&gt;：systemd 用来覆盖 Docker 服务配置的目录。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;systemctl daemon-reload&lt;/code&gt;：重新加载 systemd 配置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;systemctl restart docker&lt;/code&gt;：重启 Docker 服务，让代理配置生效。&lt;/p&gt;
</content:encoded></item><item><title>Linux CPU / 内存 / 磁盘状态检查速查</title><link>https://r-gc.github.io/posts/notes/linux/linux-system-status/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/linux/linux-system-status/</guid><description>记录 Linux 上查看 CPU、内存、磁盘、进程和系统负载的常用命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 Linux 系统状态检查命令。&lt;/p&gt;
&lt;h2&gt;系统整体状态&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;uptime
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看系统运行时间、登录用户数和负载。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;top
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;交互式查看 CPU、内存和进程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;htop
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更好用的 &lt;code&gt;top&lt;/code&gt;，如果没有需要先安装。&lt;/p&gt;
&lt;h2&gt;CPU 信息&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;lscpu
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 CPU 型号、核心数、线程数、架构等信息。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nproc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看可用 CPU 核心数。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat /proc/cpuinfo | grep &quot;model name&quot; | head
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 CPU 型号。&lt;/p&gt;
&lt;h2&gt;CPU 使用率&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;top
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;进入后常用按键：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;P：按 CPU 使用率排序
M：按内存使用率排序
q：退出
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果安装了 &lt;code&gt;sysstat&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mpstat 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;每 1 秒刷新一次 CPU 使用情况。&lt;/p&gt;
&lt;h2&gt;内存状态&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;free -h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;人类可读格式查看内存。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;free -m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以 MB 为单位查看内存。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat /proc/meminfo | head
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看更详细的内存信息。&lt;/p&gt;
&lt;h2&gt;磁盘空间&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;df -h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看各挂载点磁盘使用情况。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;df -Th
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同时显示文件系统类型。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;du -sh .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看当前目录总大小。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;du -h --max-depth=1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看当前目录下一层文件和目录大小。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;du -h --max-depth=1 | sort -h
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按大小排序。&lt;/p&gt;
&lt;h2&gt;磁盘 IO&lt;/h2&gt;
&lt;p&gt;如果安装了 &lt;code&gt;sysstat&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;iostat -xz 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;每 1 秒刷新磁盘 IO 状态。&lt;/p&gt;
&lt;p&gt;如果安装了 &lt;code&gt;iotop&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo iotop
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看哪个进程正在读写磁盘。&lt;/p&gt;
&lt;h2&gt;进程查看&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ps aux
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看所有进程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ps aux | grep nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按关键词查进程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pgrep -af nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更简洁地按进程名查找。&lt;/p&gt;
&lt;h2&gt;杀进程&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;kill PID
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;正常结束进程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;kill -9 PID
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;强制结束进程。优先用普通 &lt;code&gt;kill&lt;/code&gt;，不行再用 &lt;code&gt;-9&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;查看端口占用进程&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo lsof -i :8080
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo ss -lntp | grep :8080
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;-h&lt;/code&gt;：human readable，人类可读格式，例如 GB / MB。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-T&lt;/code&gt;：显示文件系统类型。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--max-depth=1&lt;/code&gt;：只统计当前目录下一层。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sort -h&lt;/code&gt;：按人类可读大小排序。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ps aux&lt;/code&gt;：显示所有用户的所有进程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grep&lt;/code&gt;：按文本过滤。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kill -9&lt;/code&gt;：发送 SIGKILL，强制结束进程。&lt;/p&gt;
</content:encoded></item><item><title>Linux 网络状态检查速查</title><link>https://r-gc.github.io/posts/notes/linux/linux-network-status/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/linux/linux-network-status/</guid><description>记录 Linux 上查看 IP、端口、连接、DNS、路由和网络连通性的常用命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制网络状态检查命令。&lt;/p&gt;
&lt;h2&gt;查看 IP 地址&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ip addr
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;简写：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只看 IPv4：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip -4 addr
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看默认路由&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ip route
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看默认网关：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip route | grep default
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看监听端口&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ss -lntp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 TCP 监听端口和进程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ss -lnup
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 UDP 监听端口和进程。&lt;/p&gt;
&lt;p&gt;查看某个端口：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo ss -lntp | grep :8080
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看连接状态&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ss -ant
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看所有 TCP 连接。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ss -ant | grep ESTAB
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看已建立连接。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ss -ant | grep TIME-WAIT | wc -l
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;统计 &lt;code&gt;TIME-WAIT&lt;/code&gt; 数量。&lt;/p&gt;
&lt;h2&gt;查看端口占用&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo lsof -i :8080
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo fuser -v 8080/tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;测试连通性&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ping github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定次数：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ping -c 4 github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试 TCP 端口：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nc -vz github.com 443
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试 HTTP：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -I https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;显示详细连接过程：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -v https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;DNS 检查&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;nslookup github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果有 &lt;code&gt;dig&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dig github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只看 A 记录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dig github.com A +short
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定 DNS 服务器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dig @1.1.1.1 github.com
dig @8.8.8.8 github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看 DNS 配置&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;cat /etc/resolv.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果使用 systemd-resolved：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;resolvectl status
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;路由追踪&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;traceroute github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有 &lt;code&gt;traceroute&lt;/code&gt;，可以用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tracepath github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看公网 IP&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;curl ifconfig.me
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl https://api.ipify.org
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ss&lt;/code&gt;：查看 socket 状态，现代 Linux 上常用来替代 &lt;code&gt;netstat&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-l&lt;/code&gt;：只显示监听中的端口。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-n&lt;/code&gt;：不解析域名和服务名，显示数字端口。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-t&lt;/code&gt;：TCP。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-u&lt;/code&gt;：UDP。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-p&lt;/code&gt;：显示进程信息，通常需要 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nc -vz&lt;/code&gt;：测试 TCP 端口是否可连接。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -I&lt;/code&gt;：只请求响应头。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl -v&lt;/code&gt;：输出详细连接过程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dig +short&lt;/code&gt;：只输出简短解析结果。&lt;/p&gt;
</content:encoded></item><item><title>Docker 容器不退出与调试命令速查</title><link>https://r-gc.github.io/posts/notes/docker/docker-container-keepalive-debug/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/docker/docker-container-keepalive-debug/</guid><description>记录让 Docker 容器保持运行、进入容器、临时调试、查看退出原因和常用 run 参数。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 Docker 容器保活和调试命令。&lt;/p&gt;
&lt;h2&gt;让容器不退出&lt;/h2&gt;
&lt;p&gt;最常用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name debug-container IMAGE tail -f /dev/null
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name debug-container IMAGE sleep infinity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果镜像里没有 &lt;code&gt;sleep infinity&lt;/code&gt;，用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name debug-container IMAGE sh -c &quot;while true; do sleep 3600; done&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;交互式进入容器&lt;/h2&gt;
&lt;p&gt;进入正在运行的容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker exec -it CONTAINER bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有 bash：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker exec -it CONTAINER sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以 root 用户进入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker exec -it -u root CONTAINER bash
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;直接启动并进入临时容器&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker run --rm -it IMAGE bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有 bash：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run --rm -it IMAGE sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;挂载当前目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run --rm -it -v &quot;$PWD&quot;:/work -w /work IMAGE bash
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;容器退出后查看原因&lt;/h2&gt;
&lt;p&gt;查看所有容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker ps -a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看日志：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker logs CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看退出码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker inspect -f &apos;{{.State.ExitCode}}&apos; CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看错误信息：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker inspect -f &apos;{{.State.Error}}&apos; CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看状态：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker inspect -f &apos;{{.State.Status}}&apos; CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;重新启动已退出容器&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker start CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动并附加到终端：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker start -ai CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;停止和删除容器&lt;/h2&gt;
&lt;p&gt;停止：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker stop CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;删除：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker rm CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;强制删除运行中的容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker rm -f CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用 docker run 模板&lt;/h2&gt;
&lt;p&gt;后台运行并指定名称：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name app IMAGE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;映射端口：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name app -p 8080:80 IMAGE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;设置环境变量：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name app -e NODE_ENV=production IMAGE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;挂载目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name app -v &quot;$PWD&quot;:/app IMAGE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定工作目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name app -w /app IMAGE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定网络：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run -d --name app --network my-network IMAGE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;容器退出自动删除：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker run --rm IMAGE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Docker Compose 调试&lt;/h2&gt;
&lt;p&gt;进入服务容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec SERVICE bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有 bash：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec SERVICE sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;临时启动服务并进入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose run --rm SERVICE bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只启动某个服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose up -d SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重启某个服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose restart SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;-d&lt;/code&gt;：后台运行容器。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--name&lt;/code&gt;：指定容器名称。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-it&lt;/code&gt;：交互式终端，常用于进入 shell。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--rm&lt;/code&gt;：容器退出后自动删除。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-v&lt;/code&gt;：挂载目录或 volume。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-w&lt;/code&gt;：指定容器内工作目录。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-p 8080:80&lt;/code&gt;：把宿主机 8080 映射到容器 80。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-e KEY=value&lt;/code&gt;：设置环境变量。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--network&lt;/code&gt;：指定容器加入的 Docker 网络。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tail -f /dev/null&lt;/code&gt;：持续等待，不主动退出，常用于调试保活。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sleep infinity&lt;/code&gt;：无限睡眠，让容器保持运行。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;exec&lt;/code&gt;：在运行中的容器里执行命令。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;start -ai&lt;/code&gt;：启动已存在容器并附加输入输出。&lt;/p&gt;
</content:encoded></item><item><title>Docker 状态检查速查</title><link>https://r-gc.github.io/posts/notes/docker/docker-status-check/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/docker/docker-status-check/</guid><description>记录 Docker 服务、容器、镜像、日志、资源占用和网络状态的常用检查命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 Docker 状态检查命令。&lt;/p&gt;
&lt;h2&gt;Docker 服务状态&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看客户端和服务端版本。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker info
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 Docker daemon 信息。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl status docker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 Docker 服务状态。&lt;/p&gt;
&lt;p&gt;启动 Docker：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl start docker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重启 Docker：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl restart docker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;设置开机启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl enable docker
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看容器&lt;/h2&gt;
&lt;p&gt;运行中的容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所有容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker ps -a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只显示容器 ID：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker ps -q
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;格式化输出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker ps --format &quot;table {{.Names}}\t{{.Status}}\t{{.Ports}}&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看容器详情&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker inspect CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看容器 IP：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker inspect -f &apos;{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}&apos; CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看容器启动命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker inspect -f &apos;{{.Path}} {{range .Args}}{{.}} {{end}}&apos; CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看日志&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker logs CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看最后 100 行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker logs --tail 100 CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实时跟随：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker logs -f CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;带时间：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker logs -f --timestamps CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看资源占用&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker stats
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只看某个容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker stats CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只输出一次：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker stats --no-stream
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看镜像&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看镜像磁盘占用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker system df
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看更详细占用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker system df -v
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看网络&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker network ls
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看网络详情：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker network inspect NETWORK
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看某个容器连接的网络：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker inspect -f &apos;{{json .NetworkSettings.Networks}}&apos; CONTAINER
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看卷&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker volume ls
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看卷详情：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker volume inspect VOLUME
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Docker Compose 状态&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose ps
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看日志：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs
docker compose logs -f
docker compose logs --tail 100 SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看配置展开结果：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose config
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;docker ps&lt;/code&gt;：查看运行中的容器。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-a&lt;/code&gt;：包含已停止容器。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-q&lt;/code&gt;：只输出 ID。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--format&lt;/code&gt;：自定义输出格式。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;inspect&lt;/code&gt;：查看对象完整 JSON 信息。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-f&lt;/code&gt;：format，按模板提取字段。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;logs -f&lt;/code&gt;：持续跟随日志输出。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--tail 100&lt;/code&gt;：只显示最后 100 行。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;stats&lt;/code&gt;：查看容器 CPU、内存、网络 IO、磁盘 IO。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--no-stream&lt;/code&gt;：只输出一次，不持续刷新。&lt;/p&gt;
</content:encoded></item><item><title>文件查找与文本搜索速查</title><link>https://r-gc.github.io/posts/notes/files/file-search-text-processing/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/files/file-search-text-processing/</guid><description>记录 find、rg、grep、sed、awk、xargs 等常用文件查找和文本处理命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制文件查找和文本搜索命令。&lt;/p&gt;
&lt;h2&gt;推荐优先用 rg&lt;/h2&gt;
&lt;p&gt;查找文本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rg &quot;keyword&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查找文件名：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rg --files | rg &quot;config&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;忽略大小写：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rg -i &quot;keyword&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;显示行号：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rg -n &quot;keyword&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只查某类文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rg &quot;keyword&quot; -g &quot;*.ts&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;排除目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rg &quot;keyword&quot; -g &quot;!node_modules&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;find 查找文件&lt;/h2&gt;
&lt;p&gt;按文件名：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -name &quot;*.md&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;忽略大小写：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -iname &quot;*readme*&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按目录深度：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -maxdepth 2 -type f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只找目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -type d -name &quot;node_modules&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按大小：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -type f -size +100M
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按修改时间：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -type f -mtime -1
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;grep 搜索文本&lt;/h2&gt;
&lt;p&gt;递归搜索：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;grep -R &quot;keyword&quot; .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;显示行号：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;grep -Rni &quot;keyword&quot; .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;排除目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;grep -R &quot;keyword&quot; . --exclude-dir=node_modules
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;sed 常用替换&lt;/h2&gt;
&lt;p&gt;只输出匹配行附近内容：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sed -n &apos;1,120p&apos; file.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;替换输出，不修改文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sed &apos;s/old/new/g&apos; file.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原地替换：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sed -i &apos;s/old/new/g&apos; file.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;macOS 上原地替换：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sed -i &apos;&apos; &apos;s/old/new/g&apos; file.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;awk 常用命令&lt;/h2&gt;
&lt;p&gt;打印第一列：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;awk &apos;{print $1}&apos; file.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按冒号分隔：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;awk -F &apos;:&apos; &apos;{print $1}&apos; /etc/passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;打印匹配行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;awk &apos;/keyword/ {print}&apos; file.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;xargs 常用组合&lt;/h2&gt;
&lt;p&gt;查找并删除日志文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -name &quot;*.log&quot; -print0 | xargs -0 rm
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;批量 grep：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -name &quot;*.md&quot; -print0 | xargs -0 grep -n &quot;keyword&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配合 rg 文件列表：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rg --files -g &quot;*.md&quot; | xargs grep -n &quot;keyword&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看大文件&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;find . -type f -size +100M -print
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按大小排序：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -type f -printf &quot;%s %p\n&quot; | sort -n | tail
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;rg&lt;/code&gt;：ripgrep，速度快，默认尊重 &lt;code&gt;.gitignore&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rg --files&lt;/code&gt;：列出文件。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-g &quot;*.ts&quot;&lt;/code&gt;：只包含某类路径。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-g &quot;!node_modules&quot;&lt;/code&gt;：排除路径。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;find -name&lt;/code&gt;：按名称匹配，区分大小写。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;find -iname&lt;/code&gt;：按名称匹配，不区分大小写。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-type f&lt;/code&gt;：只找文件。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-type d&lt;/code&gt;：只找目录。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-maxdepth&lt;/code&gt;：限制搜索深度。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grep -R&lt;/code&gt;：递归搜索。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;grep -n&lt;/code&gt;：显示行号。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sed -n&lt;/code&gt;：只输出指定内容。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sed -i&lt;/code&gt;：原地修改文件。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;awk -F&lt;/code&gt;：指定字段分隔符。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xargs&lt;/code&gt;：把前一个命令的输出变成后一个命令的参数。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-print0&lt;/code&gt; 和 &lt;code&gt;xargs -0&lt;/code&gt;：用空字符分隔，能安全处理带空格的文件名。&lt;/p&gt;
</content:encoded></item><item><title>Docker Compose 常用命令速查</title><link>https://r-gc.github.io/posts/notes/docker/docker-compose-commands/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/docker/docker-compose-commands/</guid><description>记录 Docker Compose 启动、停止、日志、进入容器、构建、拉取和指定服务的常用命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 Docker Compose 常用命令。&lt;/p&gt;
&lt;h2&gt;查看服务状态&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose ps
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看所有容器，包括已退出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose ps -a
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;启动服务&lt;/h2&gt;
&lt;p&gt;前台启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;后台启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只启动某个服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose up -d SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动前重新构建：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose up -d --build
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;停止服务&lt;/h2&gt;
&lt;p&gt;停止并删除容器和默认网络：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只停止，不删除容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose stop
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重新启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose restart
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只重启某个服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose restart SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;不删除 volume 的停止方式&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;默认不会删除 named volumes。&lt;/p&gt;
&lt;p&gt;如果加了这个参数才会删除 volume：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose down -v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以不想删数据时，不要加 &lt;code&gt;-v&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;查看日志&lt;/h2&gt;
&lt;p&gt;查看全部日志：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实时跟随：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs -f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看某个服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs -f SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只看最后 100 行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs --tail 100 SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;带时间戳：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs -f --timestamps SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;进入容器&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec SERVICE bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有 bash：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec SERVICE sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以 root 进入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec -u root SERVICE bash
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;临时运行一个服务命令&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose run --rm SERVICE bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行一次命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose run --rm SERVICE npm install
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;构建镜像&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不使用缓存：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose build --no-cache
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只构建某个服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose build SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;拉取镜像&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose pull
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只拉某个服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose pull SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;指定 compose 文件&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose -f docker-compose.yml -f docker-compose.override.yml up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定项目名：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose -p PROJECT_NAME up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;profiles&lt;/h2&gt;
&lt;p&gt;启动指定 profile：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose --profile dev up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多个 profile：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose --profile dev --profile debug up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看最终配置&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose config
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个命令会展开变量、合并多个 compose 文件，排查配置时很好用。&lt;/p&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;up&lt;/code&gt;：创建并启动服务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-d&lt;/code&gt;：后台运行。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;down&lt;/code&gt;：停止并删除容器和网络。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;stop&lt;/code&gt;：只停止容器，不删除。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;restart&lt;/code&gt;：重启服务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;logs -f&lt;/code&gt;：实时跟随日志。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;exec&lt;/code&gt;：进入正在运行的服务容器执行命令。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;run --rm&lt;/code&gt;：临时创建容器执行命令，结束后删除。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;build --no-cache&lt;/code&gt;：不使用构建缓存。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-f&lt;/code&gt;：指定 compose 文件。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-p&lt;/code&gt;：指定项目名，影响容器、网络、volume 前缀。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--profile&lt;/code&gt;：启用带 profile 的服务。&lt;/p&gt;
</content:encoded></item><item><title>端口占用与进程排错速查</title><link>https://r-gc.github.io/posts/notes/linux/port-process-troubleshooting/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/linux/port-process-troubleshooting/</guid><description>记录 Linux 和 Windows 上查看端口占用、定位进程、杀进程和理解监听地址的常用命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制端口和进程排错命令。&lt;/p&gt;
&lt;h2&gt;Linux 查看端口监听&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo ss -lntp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看指定端口：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo ss -lntp | grep :3000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;UDP：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo ss -lnup
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Linux 查看端口占用进程&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo lsof -i :3000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo fuser -v 3000/tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Linux 杀掉占用端口的进程&lt;/h2&gt;
&lt;p&gt;先查 PID：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo lsof -i :3000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;正常结束：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;kill PID
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;强制结束：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;kill -9 PID
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一行命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo kill -9 $(sudo lsof -t -i :3000)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Linux 查看进程&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ps aux | grep node
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更简洁：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pgrep -af node
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看进程树：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pstree -ap
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Windows 查看端口占用&lt;/h2&gt;
&lt;p&gt;PowerShell 或 CMD：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;netstat -ano | findstr :3000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 PID 对应进程：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tasklist | findstr PID
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;杀进程：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;taskkill /PID PID /F
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PowerShell 写法：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Get-Process -Id PID
Stop-Process -Id PID -Force
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;监听地址区别&lt;/h2&gt;
&lt;p&gt;只允许本机访问：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;127.0.0.1:3000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;监听所有网卡：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0.0.0.0:3000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果服务在 WSL / Docker / 虚拟机里，想让外部访问，通常需要监听 &lt;code&gt;0.0.0.0&lt;/code&gt;，并确认端口映射或防火墙规则。&lt;/p&gt;
&lt;h2&gt;测试端口是否可连&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;nc -vz 127.0.0.1 3000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试 HTTP 服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -I http://127.0.0.1:3000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看详细连接过程：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -v http://127.0.0.1:3000
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ss -lntp&lt;/code&gt;：查看 TCP 监听端口和进程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lsof -i :3000&lt;/code&gt;：查看使用 3000 端口的进程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lsof -t&lt;/code&gt;：只输出 PID。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fuser -v 3000/tcp&lt;/code&gt;：查看使用指定 TCP 端口的进程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kill&lt;/code&gt;：发送终止信号。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kill -9&lt;/code&gt;：强制终止。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;netstat -ano&lt;/code&gt;：Windows 查看连接、监听端口和 PID。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;taskkill /F&lt;/code&gt;：Windows 强制结束进程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nc -vz&lt;/code&gt;：测试 TCP 端口连通性。&lt;/p&gt;
</content:encoded></item><item><title>systemd 服务管理速查</title><link>https://r-gc.github.io/posts/notes/systemd/systemd-service-management/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/systemd/systemd-service-management/</guid><description>记录 systemctl、journalctl、服务启停、开机启动、环境变量和自定义 service 文件的常用命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 systemd 服务管理命令。&lt;/p&gt;
&lt;h2&gt;查看服务状态&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl status SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl status docker
sudo systemctl status nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;启动、停止、重启&lt;/h2&gt;
&lt;p&gt;启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl start SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;停止：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl stop SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重启：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl restart SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重新加载配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl reload SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果不确定服务是否支持 reload：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl reload-or-restart SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;开机启动&lt;/h2&gt;
&lt;p&gt;启用开机启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl enable SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;禁用开机启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl disable SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;立即启用并启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl enable --now SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看是否开机启动：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;systemctl is-enabled SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看是否正在运行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;systemctl is-active SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看日志&lt;/h2&gt;
&lt;p&gt;查看服务日志：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;journalctl -u SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实时跟随：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;journalctl -u SERVICE -f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看最近 100 行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;journalctl -u SERVICE -n 100
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;从今天开始：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;journalctl -u SERVICE --since today
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定时间范围：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;journalctl -u SERVICE --since &quot;2026-05-20 10:00&quot; --until &quot;2026-05-20 12:00&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看失败服务&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;systemctl --failed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重置 failed 状态：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl reset-failed
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看服务环境变量&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl show --property=Environment SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看完整配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;systemctl cat SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;修改服务后重载 systemd&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改 service 文件或 drop-in 配置后，都需要执行这个命令。&lt;/p&gt;
&lt;h2&gt;创建自定义 service&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/systemd/system/myapp.service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Unit]
Description=My App
After=network.target

[Service]
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl enable --now myapp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl status myapp
journalctl -u myapp -f
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;drop-in 覆盖配置&lt;/h2&gt;
&lt;p&gt;创建覆盖目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl edit SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Service]
Environment=&quot;HTTP_PROXY=http://127.0.0.1:10808&quot;
Environment=&quot;HTTPS_PROXY=http://127.0.0.1:10808&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;保存后：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl restart SERVICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;systemctl status&lt;/code&gt;：查看服务状态和最近日志。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;start&lt;/code&gt;：启动服务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;stop&lt;/code&gt;：停止服务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;restart&lt;/code&gt;：重启服务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;reload&lt;/code&gt;：重新加载配置，不一定重启进程。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;enable&lt;/code&gt;：设置开机启动。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;disable&lt;/code&gt;：取消开机启动。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;enable --now&lt;/code&gt;：设置开机启动并立即启动。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;journalctl -u&lt;/code&gt;：查看某个服务日志。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-f&lt;/code&gt;：实时跟随日志。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-n 100&lt;/code&gt;：显示最近 100 行。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;daemon-reload&lt;/code&gt;：重新加载 systemd 单元文件。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Restart=always&lt;/code&gt;：服务退出后自动重启。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WantedBy=multi-user.target&lt;/code&gt;：让服务进入常规多用户启动目标。&lt;/p&gt;
</content:encoded></item><item><title>WSL 网络与代理配置速查</title><link>https://r-gc.github.io/posts/notes/wsl/wsl-network-proxy/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/wsl/wsl-network-proxy/</guid><description>记录 WSL 查看版本、重启、访问 Windows 代理、Windows 访问 WSL 服务和常见网络排查命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇用来复制 WSL 网络和代理相关命令。&lt;/p&gt;
&lt;h2&gt;查看 WSL 版本&lt;/h2&gt;
&lt;p&gt;在 Windows PowerShell 执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl --list --verbose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;简写：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl -l -v
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;关闭并重启 WSL&lt;/h2&gt;
&lt;p&gt;在 Windows PowerShell 执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl --shutdown
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后重新打开 WSL 终端。&lt;/p&gt;
&lt;h2&gt;查看 WSL 内 IP&lt;/h2&gt;
&lt;p&gt;在 WSL 执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hostname -I
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip addr
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;WSL 获取 Windows 主机 IP&lt;/h2&gt;
&lt;p&gt;常用方式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat /etc/resolv.conf | grep nameserver
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;提取 IP：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export WINDOWS_HOST=$(cat /etc/resolv.conf | awk &apos;/nameserver/ {print $2; exit}&apos;)
echo &quot;$WINDOWS_HOST&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;WSL 使用 Windows 代理&lt;/h2&gt;
&lt;p&gt;如果 Windows 代理监听在 &lt;code&gt;127.0.0.1:10808&lt;/code&gt;，WSL 里不一定能直接访问这个地址。更稳的方式是使用 Windows 主机 IP：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export WINDOWS_HOST=$(cat /etc/resolv.conf | awk &apos;/nameserver/ {print $2; exit}&apos;)
export http_proxy=http://$WINDOWS_HOST:10808
export https_proxy=http://$WINDOWS_HOST:10808
export all_proxy=socks5://$WINDOWS_HOST:10808
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -I https://github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;取消：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;unset http_proxy
unset https_proxy
unset all_proxy
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Windows 访问 WSL 服务&lt;/h2&gt;
&lt;p&gt;在 WSL 启动服务时，尽量监听：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0.0.0.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而不是只监听：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;127.0.0.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 WSL 服务监听：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ss -lntp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果服务监听 &lt;code&gt;0.0.0.0:3000&lt;/code&gt;，Windows 通常可以访问：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看 Windows 到 WSL 的端口&lt;/h2&gt;
&lt;p&gt;在 Windows PowerShell 中：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;netstat -ano | findstr :3000
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;DNS 异常检查&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;cat /etc/resolv.conf
nslookup github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果 DNS 临时异常，可以先重启 WSL：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl --shutdown
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;.wslconfig 位置&lt;/h2&gt;
&lt;p&gt;Windows 用户目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C:\Users\&amp;lt;你的用户名&amp;gt;\.wslconfig
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常见示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[wsl2]
memory=8GB
processors=4
swap=8GB
localhostForwarding=true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改后需要：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wsl --shutdown
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数解释&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;wsl -l -v&lt;/code&gt;：查看发行版、运行状态和 WSL 版本。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;wsl --shutdown&lt;/code&gt;：关闭所有 WSL 实例。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;hostname -I&lt;/code&gt;：输出当前 Linux 环境的 IP。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/resolv.conf&lt;/code&gt;：DNS 配置文件，WSL 中常能看到 Windows 主机相关地址。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0.0.0.0&lt;/code&gt;：监听所有网卡，方便从 Windows 或局域网访问。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;：只监听本机回环地址。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;localhostForwarding&lt;/code&gt;：WSL2 的 localhost 转发配置。&lt;/p&gt;
</content:encoded></item><item><title>Fuwari 写作规则与 Markdown 扩展速查</title><link>https://r-gc.github.io/posts/notes/blog/fuwari-writing-rules/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/blog/fuwari-writing-rules/</guid><description>整理 Fuwari 文章 frontmatter、文章位置、图片路径、提示块和 GitHub 仓库卡片语法。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇整理当前博客写文章时最容易忘的规则。&lt;/p&gt;
&lt;h2&gt;文章放哪里&lt;/h2&gt;
&lt;p&gt;正式文章放在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;笔记建议放在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/notes/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以用子目录组织文章和图片：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/content/posts/notes/example-note/
  index.md
  cover.png
  screenshot.png
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;文章 frontmatter 模板&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;---
title: 笔记标题
published: 2026-05-20
updated: 2026-05-20
description: 一句话说明这篇笔记解决什么问题。
tags: [Linux, Docker, 速查]
category: 笔记
draft: false
---
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用字段&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;title&lt;/code&gt;：文章标题。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;published&lt;/code&gt;：发布时间。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;updated&lt;/code&gt;：更新时间，可选。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;description&lt;/code&gt;：首页、归档和搜索里会显示的摘要。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tags&lt;/code&gt;：标签，用来描述主题和用途。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;category&lt;/code&gt;：一级分类。当前建议只用 &lt;code&gt;笔记&lt;/code&gt;、&lt;code&gt;项目&lt;/code&gt;、&lt;code&gt;博客&lt;/code&gt;、&lt;code&gt;实验&lt;/code&gt;、&lt;code&gt;随笔&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;draft&lt;/code&gt;：是否草稿。&lt;code&gt;true&lt;/code&gt; 时生产环境不会显示。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;image&lt;/code&gt;：封面图，可选。&lt;/p&gt;
&lt;h2&gt;图片路径规则&lt;/h2&gt;
&lt;p&gt;网络图片：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;image: https://example.com/cover.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;public&lt;/code&gt; 目录下的图片：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;image: /images/cover.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;相对文章文件的图片：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;image: ./cover.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果文章是目录形式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;my-note/
  index.md
  cover.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那么 &lt;code&gt;./cover.png&lt;/code&gt; 会相对 &lt;code&gt;index.md&lt;/code&gt; 生效。&lt;/p&gt;
&lt;h2&gt;创建新文章&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;pnpm new-post filename
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以直接手动新建 &lt;code&gt;.md&lt;/code&gt; 文件。手动建更适合现在这种按目录分类的笔记库。&lt;/p&gt;
&lt;h2&gt;提示块语法&lt;/h2&gt;
&lt;p&gt;普通提示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::::note
这里是一条 note。
::::
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;提示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::::tip
这里是一条 tip。
::::
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;警告：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::::warning
这里是一条 warning。
::::
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::::caution
这里是一条 caution。
::::
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重要：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::::important
这里是一条 important。
::::
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;自定义标题：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::::note[自定义标题]
这里是内容。
::::
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;GitHub 仓库卡片&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;::github{repo=&quot;r-gc/r-gc.github.io&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;::github{repo=&quot;rgc318/frappe_docker&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个卡片会在页面加载时请求 GitHub API 获取仓库信息，所以网络环境不稳定时可能加载慢。&lt;/p&gt;
&lt;h2&gt;代码块&lt;/h2&gt;
&lt;p&gt;普通代码块：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```bash
pnpm build
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;带文件名或标题的代码块可以继续使用 Expressive Code 支持的写法。这个项目已经接入了代码复制按钮、行号和语言标识。&lt;/p&gt;
&lt;h2&gt;写作注意事项&lt;/h2&gt;
&lt;p&gt;笔记不需要一开始写成完整文章。&lt;/p&gt;
&lt;p&gt;速查类内容优先写可复制命令，再写参数解释。&lt;/p&gt;
&lt;p&gt;排错类内容优先写现象、原因、解决命令和下次怎么判断。&lt;/p&gt;
&lt;p&gt;项目类内容优先写为什么这样做、踩过什么坑、以后怎么复用。&lt;/p&gt;
</content:encoded></item><item><title>RGC Blog 构建与部署注意事项</title><link>https://r-gc.github.io/posts/notes/blog/rgc-blog-build-deploy-tips/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/blog/rgc-blog-build-deploy-tips/</guid><description>整理当前博客项目的 pnpm、Astro、Pagefind、GitHub Pages 和 Cloudflare Workers 部署注意事项。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇记录当前博客项目自己的构建和部署注意事项。&lt;/p&gt;
&lt;h2&gt;本地开发命令&lt;/h2&gt;
&lt;p&gt;安装依赖：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动开发服务器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本地构建：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预览构建结果：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm preview
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;包管理器版本&lt;/h2&gt;
&lt;p&gt;项目指定：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;packageManager&quot;: &quot;pnpm@9.14.4&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;并且有 preinstall 限制：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;preinstall&quot;: &quot;npx only-allow pnpm&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以这个项目应该使用 &lt;code&gt;pnpm&lt;/code&gt;，不要用 &lt;code&gt;npm install&lt;/code&gt; 或 &lt;code&gt;yarn install&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;Node 版本&lt;/h2&gt;
&lt;p&gt;GitHub Actions 使用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node-version: 22
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本地如果有多个 Node 版本，优先使用 Node 22。&lt;/p&gt;
&lt;p&gt;查看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node -v
pnpm -v
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;构建命令实际做了什么&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt; 里：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;build&quot;: &quot;astro build &amp;amp;&amp;amp; pagefind --site dist&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是说 &lt;code&gt;pnpm build&lt;/code&gt; 会先生成 Astro 静态站点，再为 &lt;code&gt;dist&lt;/code&gt; 生成 Pagefind 搜索索引。&lt;/p&gt;
&lt;p&gt;如果只运行 &lt;code&gt;astro build&lt;/code&gt;，页面可以生成，但搜索索引可能不是最新的。&lt;/p&gt;
&lt;h2&gt;GitHub Pages 部署方式&lt;/h2&gt;
&lt;p&gt;当前正确方式是 GitHub Actions。&lt;/p&gt;
&lt;p&gt;workflow 文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.github/workflows/deploy.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;关键步骤：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- run: pnpm install --frozen-lockfile
- run: pnpm build
- uses: actions/upload-pages-artifact@v3
- uses: actions/deploy-pages@v4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GitHub 仓库设置里应该选择：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Settings -&amp;gt; Pages -&amp;gt; Build and deployment -&amp;gt; Source -&amp;gt; GitHub Actions
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不要选择：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Deploy from a branch
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;否则 GitHub 可能会同时触发默认 Jekyll 构建，出现一个成功的 Astro workflow 和一个失败的 &lt;code&gt;pages build and deployment&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;GitHub Pages 出现 Jekyll 日志是什么意思&lt;/h2&gt;
&lt;p&gt;如果日志里出现：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GitHub Pages: jekyll
Theme: jekyll-theme-primer
Source: /github/workspace/.
Destination: /github/workspace/./_site
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;说明 GitHub 正在把仓库根目录当成 Jekyll 站点构建。&lt;/p&gt;
&lt;p&gt;这个项目是 Astro，不应该走 Jekyll。&lt;/p&gt;
&lt;p&gt;解决方法是把 Pages Source 改成：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GitHub Actions
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Cloudflare Workers 部署&lt;/h2&gt;
&lt;p&gt;当前 Cloudflare Workers Static Assets 配置在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wrangler.jsonc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;核心配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;r-gc-github-io&quot;,
  &quot;compatibility_date&quot;: &quot;2026-05-20&quot;,
  &quot;assets&quot;: {
    &quot;directory&quot;: &quot;./dist/&quot;,
    &quot;not_found_handling&quot;: &quot;404-page&quot;,
    &quot;html_handling&quot;: &quot;auto-trailing-slash&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cloudflare 构建命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm run build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;部署命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx wrangler deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;站点地址配置&lt;/h2&gt;
&lt;p&gt;Astro 配置里：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;site: &quot;https://r-gc.github.io/&quot;,
base: &quot;/&quot;,
trailingSlash: &quot;always&quot;,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;site&lt;/code&gt; 会影响 sitemap、RSS 等生成结果。&lt;/p&gt;
&lt;p&gt;如果以后主域名完全切到：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://blog.rgcdev.top/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以考虑把 &lt;code&gt;site&lt;/code&gt; 改成主域名。&lt;/p&gt;
&lt;h2&gt;常见排查命令&lt;/h2&gt;
&lt;p&gt;本地构建：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;检查生成页面：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find dist -maxdepth 3 -type f | sort
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 GitHub Actions 配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sed -n &apos;1,220p&apos; .github/workflows/deploy.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 Cloudflare 配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sed -n &apos;1,160p&apos; wrangler.jsonc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 scripts：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node -p &quot;require(&apos;./package.json&apos;).scripts&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;注意事项&lt;/h2&gt;
&lt;p&gt;Cloudflare Workers 和 GitHub Pages 是两套部署。&lt;/p&gt;
&lt;p&gt;Cloudflare 当前是主站部署，GitHub Pages 可以作为备用和对照。&lt;/p&gt;
&lt;p&gt;GitHub Pages 默认 Jekyll 构建失败，不代表 Astro workflow 失败；看绿色的 &lt;code&gt;Deploy to GitHub Pages&lt;/code&gt; workflow 是否成功更关键。&lt;/p&gt;
&lt;p&gt;新增笔记后，Pagefind 会在构建时更新搜索索引。&lt;/p&gt;
</content:encoded></item><item><title>myapp HTTP 测试与回归注意事项</title><link>https://r-gc.github.io/posts/notes/frappe/myapp-http-testing-tips/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/frappe/myapp-http-testing-tips/</guid><description>从 myapp 测试文档整理 HTTP 测试优先级、环境变量、运行命令、bench Python 和常见误判。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇从 &lt;code&gt;apps/myapp/TESTING.zh-CN.md&lt;/code&gt; 和 README 整理。&lt;/p&gt;
&lt;h2&gt;核心原则&lt;/h2&gt;
&lt;p&gt;对 &lt;code&gt;myapp.api.gateway.*&lt;/code&gt; 这类对外接口，优先用 HTTP 测试，而不是在 WSL 宿主机里直接导入 Frappe 服务层。&lt;/p&gt;
&lt;p&gt;原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;更接近前端和移动端真实调用路径&lt;/li&gt;
&lt;li&gt;能覆盖鉴权、权限、路由、响应包装和站点上下文&lt;/li&gt;
&lt;li&gt;更容易暴露 devcontainer、站点权限和真实主数据问题&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;测试环境文件&lt;/h2&gt;
&lt;p&gt;复制示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cp apps/myapp/.env.http-test.example apps/myapp/.env.http-test
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常用配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MYAPP_HTTP_BASE_URL=http://localhost:8080
MYAPP_HTTP_USERNAME=Administrator
MYAPP_HTTP_PASSWORD=&amp;lt;password&amp;gt;
MYAPP_HTTP_API_KEY=&amp;lt;api-key&amp;gt;
MYAPP_HTTP_API_SECRET=&amp;lt;api-secret&amp;gt;
MYAPP_HTTP_BEARER_TOKEN=&amp;lt;jwt-token&amp;gt;
MYAPP_HTTP_PRINT_RESPONSES=1
MYAPP_HTTP_SAVE_RESPONSES=1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;宿主机执行时：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MYAPP_HTTP_BASE_URL=http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;backend 容器内直接执行时：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MYAPP_HTTP_BASE_URL=http://localhost:8000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当前约定：宿主机侧保持 &lt;code&gt;http://localhost:8080&lt;/code&gt;，不要随意改成 &lt;code&gt;127.0.0.1&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;鉴权优先级&lt;/h2&gt;
&lt;p&gt;HTTP 测试鉴权优先级：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MYAPP_HTTP_BEARER_TOKEN
MYAPP_HTTP_API_KEY / MYAPP_HTTP_API_SECRET
MYAPP_HTTP_USERNAME / MYAPP_HTTP_PASSWORD
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;建议：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;移动端和前后端分离场景优先用 JWT Bearer Token&lt;/li&gt;
&lt;li&gt;服务端联调用 API key / secret&lt;/li&gt;
&lt;li&gt;用户名密码适合兼容历史流程，不建议长期依赖管理员密码&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;跑 HTTP 测试&lt;/h2&gt;
&lt;p&gt;销售与采购主链路：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m unittest apps.myapp.myapp.tests.http.test_gateway_http
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;v2 商品与销售状态聚合：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m unittest apps.myapp.myapp.tests.http.test_gateway_v2_http
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;采购快捷链路：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m unittest apps.myapp.myapp.tests.http.test_purchase_quick_http
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;跑单个测试方法：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m unittest \
  apps.myapp.myapp.tests.http.test_gateway_v2_http.GatewayV2HttpTestCase.test_create_product_and_stock_idempotent_replay
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;性能基线&lt;/h2&gt;
&lt;p&gt;默认采样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m apps.myapp.myapp.tests.http.benchmark_gateway_http
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定采样次数：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m apps.myapp.myapp.tests.http.benchmark_gateway_http --samples 10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定输出：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m apps.myapp.myapp.tests.http.benchmark_gateway_http \
  --output /tmp/myapp-perf-baseline.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;适合在这些情况下运行：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;工作台查询有改动&lt;/li&gt;
&lt;li&gt;详情聚合接口有改动&lt;/li&gt;
&lt;li&gt;数据库索引调整后&lt;/li&gt;
&lt;li&gt;上线前做本机基线复核&lt;/li&gt;
&lt;li&gt;出现“接口变慢”反馈后做对比&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;容器内测试必须用 bench Python&lt;/h2&gt;
&lt;p&gt;如果在 backend 容器内跑单元测试，不要直接用系统 Python。&lt;/p&gt;
&lt;p&gt;推荐：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker exec frappe_docker-backend-1 bash -lc &apos;
  cd /home/frappe/frappe-bench &amp;amp;&amp;amp;
  env/bin/python -m unittest apps.myapp.myapp.tests.unit.test_order_service
&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;系统 Python 可能找不到 &lt;code&gt;frappe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;系统 Python 可能缺少 bench 环境依赖&lt;/li&gt;
&lt;li&gt;容易出现误导性的 &lt;code&gt;ModuleNotFoundError&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;检查方式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker exec frappe_docker-backend-1 bash -lc &apos;
  cd /home/frappe/frappe-bench &amp;amp;&amp;amp;
  env/bin/python - &amp;lt;&amp;lt; &quot;PY&quot;
import importlib.util
print(&quot;frappe:&quot;, importlib.util.find_spec(&quot;frappe&quot;))
print(&quot;orjson:&quot;, importlib.util.find_spec(&quot;orjson&quot;))
PY&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;销售单位换算与库存链路&lt;/h2&gt;
&lt;p&gt;在 backend 容器中运行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker exec frappe_docker-backend-1 bash -lc &apos;
  cd /home/frappe/frappe-bench &amp;amp;&amp;amp;
  env/bin/python -m unittest apps.myapp.myapp.tests.integration.test_sales_uom_stock_chain
&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重点校验：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Sales Order Item.stock_qty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Bin.actual_qty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Stock Ledger Entry.actual_qty&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是不只看订单换算，还要看真实库存是否按库存单位准确结算。&lt;/p&gt;
&lt;h2&gt;常见误判&lt;/h2&gt;
&lt;p&gt;日志中出现 &lt;code&gt;422&lt;/code&gt; 不一定是主链路失败。&lt;/p&gt;
&lt;p&gt;如果测试本来就是探测不存在主数据、校验参数或触发业务规则，&lt;code&gt;422&lt;/code&gt; 可能是预期结果。&lt;/p&gt;
&lt;p&gt;判断时要看响应包络：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;ok&quot;: false,
  &quot;status&quot;: &quot;error&quot;,
  &quot;code&quot;: &quot;VALIDATION_ERROR&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而不是只看 HTTP 状态码。&lt;/p&gt;
&lt;h2&gt;测试分层建议&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;myapp/tests/http/         HTTP 冒烟、链路、幂等、并发测试
myapp/tests/unit/         服务层与工具函数单元测试
myapp/tests/integration/  依赖真实站点上下文的服务链路回归
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;推荐顺序：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先跑单接口测试&lt;/li&gt;
&lt;li&gt;再跑幂等和并发测试&lt;/li&gt;
&lt;li&gt;最后跑链路 smoke test&lt;/li&gt;
&lt;li&gt;需要全量回归时再跑整份文件&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>Frappe Docker 本地开发命令速查</title><link>https://r-gc.github.io/posts/notes/frappe/frappe-docker-dev-commands/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/frappe/frappe-docker-dev-commands/</guid><description>从 frappe_docker 项目文档整理本地开发、建站、migrate、进入容器和日志查看命令。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇从 &lt;code&gt;frappe_docker&lt;/code&gt; 项目文档整理，主要用于本地开发时复制命令。&lt;/p&gt;
&lt;h2&gt;开发模式启动&lt;/h2&gt;
&lt;p&gt;使用 noproxy，直接暴露端口：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose \
  -f compose.yaml \
  -f overrides/compose.redis.yaml \
  -f overrides/compose.mariadb.yaml \
  -f overrides/compose.noproxy.yaml \
  up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果项目里有封装脚本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./start-dev.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;生产模式启动&lt;/h2&gt;
&lt;p&gt;Traefik + HTTPS：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose \
  -f compose.yaml \
  -f overrides/compose.redis.yaml \
  -f overrides/compose.mariadb.yaml \
  -f overrides/compose.traefik.yaml \
  -f overrides/compose.https.yaml \
  up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果项目里有封装脚本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./start-prod.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;停止服务&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./stop.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;进入 backend 容器&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec backend bash
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;创建新站点&lt;/h2&gt;
&lt;p&gt;在容器内执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bench new-site \
  --mariadb-user-host-login-scope=% \
  --db-root-password &amp;lt;db-root-password&amp;gt; \
  --admin-password &amp;lt;admin-password&amp;gt; \
  sitename.localhost
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意把密码和站点名换成自己的值。&lt;/p&gt;
&lt;h2&gt;migrate&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec backend bench --site sitename.localhost migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;进入 bench console&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec backend bench --site sitename.localhost console
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;查看日志&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs -f backend
docker compose logs -f frontend
docker compose logs -f websocket
docker compose logs -f queue-short
docker compose logs -f queue-long
docker compose logs -f scheduler
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;重启单个服务&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;docker compose restart backend
docker compose restart frontend
docker compose restart websocket
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;myapp 开发注意事项&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;apps/myapp&lt;/code&gt; 在开发环境中通常会 bind mount 到容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/home/frappe/frappe-bench/apps/myapp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;开发态修改代码后通常可以直接反映到容器中；如果涉及前端资源或静态文件，可能还需要：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec backend bench build
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;代码检查&lt;/h2&gt;
&lt;p&gt;进入 app 目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd apps/myapp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行 ruff：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ruff check .
ruff format .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行 pre-commit：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pre-commit run --all-files
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用环境变量&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt; 中常见配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ERPNEXT_VERSION=v16.x.x
DB_PASSWORD=&amp;lt;db-root-password&amp;gt;
FRAPPE_SITE_NAME_HEADER=sitename.localhost
HTTP_PUBLISH_PORT=8080
HTTPS_PUBLISH_PORT=443
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;FRAPPE_SITE_NAME_HEADER&lt;/code&gt; 很适合单站点调试，用来覆盖 Host 头解析。&lt;/p&gt;
&lt;h2&gt;常用服务说明&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;configurator&lt;/code&gt;：初始化服务，配置数据库和 Redis，执行完会退出。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;backend&lt;/code&gt;：Python / Werkzeug 后端服务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;frontend&lt;/code&gt;：Nginx 反向代理和静态资源服务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;websocket&lt;/code&gt;：Node.js Socket.IO 实时通信服务。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;queue-short&lt;/code&gt;：短任务队列 worker。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;queue-long&lt;/code&gt;：长任务队列 worker。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;scheduler&lt;/code&gt;：定时任务调度器。&lt;/p&gt;
&lt;h2&gt;注意事项&lt;/h2&gt;
&lt;p&gt;本地开发用 bind mount 很方便，但 staging / production 更建议把自定义 app 烘焙进镜像。&lt;/p&gt;
&lt;p&gt;如果 staging 继续挂载 &lt;code&gt;./apps/myapp&lt;/code&gt;，而服务器上没有源码目录，可能会把镜像里已经存在的 &lt;code&gt;myapp&lt;/code&gt; 覆盖掉，导致：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ModuleNotFoundError: No module named &apos;myapp&apos;
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>myapp Staging 部署问题与解决速查</title><link>https://r-gc.github.io/posts/notes/frappe/myapp-staging-deploy-pitfalls/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/frappe/myapp-staging-deploy-pitfalls/</guid><description>从 staging 部署文档整理首次部署、CORS、Host 路由、GHCR、migrate、备份恢复和常见问题。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇从 &lt;code&gt;frappe_docker/STAGING_DEPLOYMENT.zh-CN.md&lt;/code&gt; 整理，所有真实服务器信息都用占位符替换。&lt;/p&gt;
&lt;h2&gt;推荐发布流程&lt;/h2&gt;
&lt;p&gt;分支模型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;feature/* -&amp;gt; develop -&amp;gt; main -&amp;gt; build/deploy/release
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;建议：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;main&lt;/code&gt; 只放稳定、可部署版本&lt;/li&gt;
&lt;li&gt;&lt;code&gt;develop&lt;/code&gt; 做日常集成测试&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feature/*&lt;/code&gt; / &lt;code&gt;fix/*&lt;/code&gt; 做单个功能或修复&lt;/li&gt;
&lt;li&gt;staging 镜像优先基于 &lt;code&gt;main&lt;/code&gt;、tag 或明确 commit&lt;/li&gt;
&lt;li&gt;只有临时调试才建议直接用 &lt;code&gt;develop&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;当前 staging 方案&lt;/h2&gt;
&lt;p&gt;流程：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Lint
-&amp;gt; Build myapp staging image
-&amp;gt; Push to GHCR
-&amp;gt; Deploy staging stack by SSH
-&amp;gt; 首次建站 init-site.sh
-&amp;gt; 后续升级自动 bench migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;核心原则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务器只保留部署骨架&lt;/li&gt;
&lt;li&gt;不再在服务器挂载 &lt;code&gt;apps/myapp&lt;/code&gt; 源码目录&lt;/li&gt;
&lt;li&gt;&lt;code&gt;myapp&lt;/code&gt; 烘焙进镜像&lt;/li&gt;
&lt;li&gt;首次部署允许“容器起来但站点未初始化”&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;GitHub Actions Secrets&lt;/h2&gt;
&lt;p&gt;常见 secrets：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;STAGING_SSH_HOST
STAGING_SSH_PORT
STAGING_SSH_USER
STAGING_SSH_PRIVATE_KEY
GHCR_USERNAME
GHCR_TOKEN
STAGING_SITE_ADMIN_PASSWORD
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;STAGING_SSH_PRIVATE_KEY&lt;/code&gt; 必须是完整私钥&lt;/li&gt;
&lt;li&gt;不能填 &lt;code&gt;.pub&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;不能只填一行公钥&lt;/li&gt;
&lt;li&gt;建议使用无 passphrase 的 CI 专用 key&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GHCR_TOKEN&lt;/code&gt; 至少需要读取 packages 的权限&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;生成 CI key：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh-keygen -t ed25519 -N &quot;&quot; -C &quot;github-actions-staging&quot; -f ~/.ssh/github_actions_staging_ci
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本地验证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh -i ~/.ssh/github_actions_staging_ci -p &amp;lt;port&amp;gt; &amp;lt;user&amp;gt;@&amp;lt;host&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;首次部署顺序&lt;/h2&gt;
&lt;p&gt;推荐顺序：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1. Lint
2. Build myapp staging image
3. Deploy staging stack
4. init-site.sh 创建站点
5. check-staging.sh 检查
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bench new-site&lt;/code&gt; 依赖 backend / db / redis 容器&lt;/li&gt;
&lt;li&gt;所以必须先把基础栈启动起来&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;首次部署后出现这些情况是正常的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;镜像正常拉取&lt;/li&gt;
&lt;li&gt;容器栈成功启动&lt;/li&gt;
&lt;li&gt;首页返回 &lt;code&gt;404&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api/method/ping&lt;/code&gt; 返回 &lt;code&gt;404&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;deploy 脚本跳过 &lt;code&gt;migrate&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这通常表示基础栈已启动，但站点还没创建。&lt;/p&gt;
&lt;h2&gt;首次建站&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;cd /srv/frappe_docker
SITE_NAME=staging.example.com \
ADMIN_PASSWORD=&apos;&amp;lt;admin-password&amp;gt;&apos; \
./deploy/staging/init-site.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;底层动作：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bench new-site &amp;lt;site&amp;gt;
bench --site &amp;lt;site&amp;gt; install-app erpnext
bench --site &amp;lt;site&amp;gt; install-app myapp
bench --site &amp;lt;site&amp;gt; migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;建站完成后，后续 deploy 就可以自动 migrate。&lt;/p&gt;
&lt;h2&gt;CORS 修改与验证&lt;/h2&gt;
&lt;p&gt;如果浏览器端要直接访问 staging 后端，需要把完整 origin 加入 Frappe 的 &lt;code&gt;allow_cors&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;实际读取文件通常是容器内：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/home/frappe/frappe-bench/sites/common_site_config.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改后至少重启：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose -p staging restart backend frontend websocket
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;验证预检请求：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -sS -X OPTIONS -D - -o /dev/null \
  -H &quot;Origin: https://frontend.example.com&quot; \
  -H &quot;Access-Control-Request-Method: POST&quot; \
  -H &quot;Access-Control-Request-Headers: content-type&quot; \
  https://erpnext.example.com/api/method/login
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;生效时应看到：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Credentials: true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：CORS 放开只代表浏览器能发请求，不代表跨站 Cookie / Session 一定稳定。长期使用更推荐同主域名方案。&lt;/p&gt;
&lt;h2&gt;直接访问 IP 返回 404&lt;/h2&gt;
&lt;p&gt;现象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -I http://127.0.0.1:28080
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;返回 &lt;code&gt;404&lt;/code&gt;，但：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -I -H &apos;Host: staging.example.com&apos; http://127.0.0.1:28080
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;返回 &lt;code&gt;200&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Frappe / Nginx 按 &lt;code&gt;Host&lt;/code&gt; 头路由站点&lt;/li&gt;
&lt;li&gt;直接访问 IP 时 Host 不是站点名&lt;/li&gt;
&lt;li&gt;所以没有命中对应 site&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FRAPPE_SITE_NAME_HEADER=staging.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后重启 staging。&lt;/p&gt;
&lt;h2&gt;常见问题：SSH 失败&lt;/h2&gt;
&lt;p&gt;现象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;missing server host
unable to authenticate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常见原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;STAGING_SSH_*&lt;/code&gt; secrets 不完整&lt;/li&gt;
&lt;li&gt;私钥内容错误&lt;/li&gt;
&lt;li&gt;端口或用户名带空格/换行&lt;/li&gt;
&lt;li&gt;服务器 &lt;code&gt;authorized_keys&lt;/code&gt; 没有对应公钥&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;workflow 增加 secrets 校验&lt;/li&gt;
&lt;li&gt;使用 CI 专用 SSH key&lt;/li&gt;
&lt;li&gt;本地先用同一把 key 验证能登录服务器&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;常见问题：git pull 被拒绝&lt;/h2&gt;
&lt;p&gt;现象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Your local changes would be overwritten by merge
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可能原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务器上的脚本只有文件 mode 变化，例如 &lt;code&gt;100644 -&amp;gt; 100755&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /srv/frappe_docker
git checkout -- deploy/staging/*.sh
git pull --ff-only origin main
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常见问题：No module named myapp&lt;/h2&gt;
&lt;p&gt;现象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ModuleNotFoundError: No module named &apos;myapp&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;staging 还在沿用开发态 compose&lt;/li&gt;
&lt;li&gt;compose 挂载了宿主机 &lt;code&gt;./apps/myapp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;服务器没有这份源码目录&lt;/li&gt;
&lt;li&gt;bind mount 把镜像内置的 &lt;code&gt;myapp&lt;/code&gt; 覆盖掉&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;staging 使用专用 compose&lt;/li&gt;
&lt;li&gt;不挂载服务器上的 &lt;code&gt;apps/myapp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;让 &lt;code&gt;myapp&lt;/code&gt; 来自镜像&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;常见问题：数据库端口冲突&lt;/h2&gt;
&lt;p&gt;现象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Bind for 0.0.0.0:3307 failed: port is already allocated
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解决：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;staging 数据库不映射宿主机端口&lt;/li&gt;
&lt;li&gt;或使用 staging 专用 compose 覆盖端口配置&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;常见问题：migrate 时站点不存在&lt;/h2&gt;
&lt;p&gt;现象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: 404 Not Found: staging.example.com does not exist.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一次部署只启动了基础栈&lt;/li&gt;
&lt;li&gt;站点尚未 &lt;code&gt;new-site&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;deploy 脚本先检查站点是否存在&lt;/li&gt;
&lt;li&gt;不存在就跳过 migrate&lt;/li&gt;
&lt;li&gt;先执行 &lt;code&gt;init-site.sh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;常见问题：formatter 导致 CI 失败&lt;/h2&gt;
&lt;p&gt;现象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;files were modified by this hook
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不是业务逻辑错误&lt;/li&gt;
&lt;li&gt;是 prettier / shfmt / shellcheck 认为格式还没对齐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;建议：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;改 Markdown / YAML / JSON 后关注 prettier&lt;/li&gt;
&lt;li&gt;改 shell 脚本后关注 shfmt 和 shellcheck&lt;/li&gt;
&lt;li&gt;CI 日志里未显示 &lt;code&gt;(unchanged)&lt;/code&gt; 的文件，通常就是被 formatter 修改过的文件&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;常见问题：恢复后短暂 503&lt;/h2&gt;
&lt;p&gt;可能原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据恢复后站点仍处于 maintenance mode&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bench --site &amp;lt;site&amp;gt; set-maintenance-mode off
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;restore 脚本也应该在末尾自动关闭维护模式、执行 migrate 并清缓存。&lt;/p&gt;
&lt;h2&gt;备份与恢复&lt;/h2&gt;
&lt;p&gt;升级前备份：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SITE_NAME=all ./deploy/staging/backup-staging.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;恢复：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SITE_NAME=staging.example.com \
RESTORE_DIR=/srv/frappe_docker/tmp/restore-localhost-YYYYMMDD \
./deploy/staging/restore-staging.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据跟着 site 走，不是跟着 app 走&lt;/li&gt;
&lt;li&gt;恢复会覆盖目标站点数据库和文件&lt;/li&gt;
&lt;li&gt;不要恢复清理前的旧备份&lt;/li&gt;
&lt;li&gt;恢复前确认备份时间点&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>WMS / ERPNext 单机 Compose 配置注意事项</title><link>https://r-gc.github.io/posts/notes/wms/wms-frappe-compose-notes/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/wms/wms-frappe-compose-notes/</guid><description>从 wms-system 目录整理 ERPNext 单机 Docker Compose、Nginx、MariaDB、Redis、站点配置和安全注意事项。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇从 &lt;code&gt;wms-system&lt;/code&gt; 当前目录结构整理，偏环境快照和注意事项。&lt;/p&gt;
&lt;h2&gt;当前服务结构&lt;/h2&gt;
&lt;p&gt;Compose 中包含：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;db           MariaDB 10.11
redis-cache  Redis cache
redis-queue  Redis queue / socketio
frontend     Nginx
erp-app      frappe/erpnext:v16.0.0
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;端口映射&lt;/h2&gt;
&lt;p&gt;Nginx：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ports:
  - &quot;8080:80&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ERPNext app：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ports:
  - &quot;8000:8000&quot;
  - &quot;9000:9000&quot;
  - &quot;5678:5678&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;含义：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;8080&lt;/code&gt;：宿主机访问 Nginx&lt;/li&gt;
&lt;li&gt;&lt;code&gt;8000&lt;/code&gt;：Frappe web 服务&lt;/li&gt;
&lt;li&gt;&lt;code&gt;9000&lt;/code&gt;：Socket.IO&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5678&lt;/code&gt;：调试端口&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;MariaDB 配置&lt;/h2&gt;
&lt;p&gt;当前 MariaDB 命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;command:
  - --character-set-server=utf8mb4
  - --collation-server=utf8mb4_unicode_ci
  - --skip-character-set-client-handshake
  - --innodb-file-per-table=1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这些配置用于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用 &lt;code&gt;utf8mb4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;避免字符集握手不一致&lt;/li&gt;
&lt;li&gt;每张 InnoDB 表独立表空间&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Redis 配置&lt;/h2&gt;
&lt;p&gt;Frappe common site config 中需要类似：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;redis_cache&quot;: &quot;redis://redis-cache:6379&quot;,
  &quot;redis_queue&quot;: &quot;redis://redis-queue:6379&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Compose 环境变量也要对应：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;environment:
  - REDIS_CACHE=redis-cache:6379
  - REDIS_QUEUE=redis-queue:6379
  - REDIS_SOCKETIO=redis-queue:6379
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;apps 和 sites 挂载&lt;/h2&gt;
&lt;p&gt;当前挂载：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;volumes:
  - ./apps:/home/frappe/frappe-bench/apps
  - ./sites:/home/frappe/frappe-bench/sites
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;含义：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;apps&lt;/code&gt; 保存 Frappe / ERPNext 应用代码&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sites&lt;/code&gt; 保存站点配置、assets、日志、私有文件和备份&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sites/site_config.json&lt;/code&gt; 里可能包含数据库账号和密码&lt;/li&gt;
&lt;li&gt;这类文件不适合公开提交&lt;/li&gt;
&lt;li&gt;如果这是本地实验快照，要注意不要把真实生产配置放进去&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;站点配置&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sites/apps.txt&lt;/code&gt; 中记录已安装应用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;frappe
erpnext
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;sites/common_site_config.json&lt;/code&gt; 中记录通用配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;db_host&quot;: &quot;db&quot;,
  &quot;redis_cache&quot;: &quot;redis://redis-cache:6379&quot;,
  &quot;redis_queue&quot;: &quot;redis://redis-queue:6379&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;单个站点的 &lt;code&gt;site_config.json&lt;/code&gt; 会包含：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;db_name&quot;: &quot;&amp;lt;db-name&amp;gt;&quot;,
  &quot;db_password&quot;: &quot;&amp;lt;db-password&amp;gt;&quot;,
  &quot;db_type&quot;: &quot;mariadb&quot;,
  &quot;db_user&quot;: &quot;&amp;lt;db-user&amp;gt;&quot;,
  &quot;developer_mode&quot;: 1
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不要把真实值直接写进公开笔记或公开仓库。&lt;/p&gt;
&lt;h2&gt;常用检查命令&lt;/h2&gt;
&lt;p&gt;查看服务：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose ps
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看日志：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs -f frontend
docker compose logs -f erp-app
docker compose logs -f db
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;进入 ERPNext 容器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec erp-app bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;进入数据库：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec db mariadb -uroot -p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看 Redis：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose exec redis-cache redis-cli ping
docker compose exec redis-queue redis-cli ping
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Nginx 注意事项&lt;/h2&gt;
&lt;p&gt;Nginx 挂载：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./sites:/home/frappe/frappe-bench/sites
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这说明 Nginx 会直接读取宿主机 &lt;code&gt;sites&lt;/code&gt; 下的静态资源。&lt;/p&gt;
&lt;p&gt;如果页面资源 404，优先检查：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker compose logs -f frontend
ls -la sites/assets
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;安全注意事项&lt;/h2&gt;
&lt;p&gt;不要公开：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;site_config.json&lt;/code&gt; 中的数据库密码&lt;/li&gt;
&lt;li&gt;生产站点的私有文件&lt;/li&gt;
&lt;li&gt;&lt;code&gt;private/backups&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;真实管理员密码&lt;/li&gt;
&lt;li&gt;真实 token / secret&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果要把环境整理成可复用模板，建议把真实配置替换成：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;db-password&amp;gt;
&amp;lt;admin-password&amp;gt;
&amp;lt;site-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;并提供 &lt;code&gt;.env.example&lt;/code&gt; 或 &lt;code&gt;site_config.example.json&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;适合后续整理的方向&lt;/h2&gt;
&lt;p&gt;这个目录更像一个本地 ERPNext / WMS 环境快照。&lt;/p&gt;
&lt;p&gt;后续如果继续整理，优先补：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当前站点创建命令&lt;/li&gt;
&lt;li&gt;Nginx 配置说明&lt;/li&gt;
&lt;li&gt;初始化数据来源&lt;/li&gt;
&lt;li&gt;WMS 相关自定义 app 是否存在&lt;/li&gt;
&lt;li&gt;备份恢复流程&lt;/li&gt;
&lt;li&gt;哪些文件应该 gitignore&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>博客视觉资源更换速查</title><link>https://r-gc.github.io/posts/notes/blog/site-visual-customization/</link><guid isPermaLink="true">https://r-gc.github.io/posts/notes/blog/site-visual-customization/</guid><description>记录 RGC Blog 更换头像、顶部 banner、顶部氛围背景图和视觉参数的位置。</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇记录博客里和“外观换装”有关的位置，后续换图片时不用重新翻代码。&lt;/p&gt;
&lt;h2&gt;头像&lt;/h2&gt;
&lt;p&gt;配置位置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/config.ts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;字段：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;profileConfig.avatar
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当前值：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;avatar: &quot;assets/images/profile-avatar.png&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;图片放在：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/assets/images/
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;顶部 banner&lt;/h2&gt;
&lt;p&gt;配置位置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/config.ts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;字段：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;siteConfig.banner
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;开启：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;banner: {
  enable: true,
  src: &quot;assets/images/demo-banner.png&quot;,
  position: &quot;center&quot;,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果不想显示顶部大图：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;enable: false
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;顶部氛围背景图&lt;/h2&gt;
&lt;p&gt;配置位置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/config.ts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;字段：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;siteConfig.background
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当前背景图：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src: &quot;/images/meteor-shower-background.png&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;图片位置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public/images/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更换方式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把新图片放到 &lt;code&gt;public/images/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;修改 &lt;code&gt;src&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;运行构建检查&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;pnpm build
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;常用参数&lt;/h2&gt;
&lt;p&gt;顶部背景高度：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;height: &quot;clamp(24rem, 42vh, 36rem)&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;透明度：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;opacity: 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;图片位置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;position: &quot;center&quot;
position: &quot;top&quot;
position: &quot;bottom&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;模糊：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;blur: &quot;4px&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;缩放：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;scale: 1.03
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;遮罩：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;overlay: {
  light: &quot;transparent&quot;,
  dark: &quot;transparent&quot;,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;推荐习惯&lt;/h2&gt;
&lt;p&gt;博客图片尽量放本地，不依赖外链。&lt;/p&gt;
&lt;p&gt;背景图建议只放在顶部氛围区，长文章阅读区保持干净。常见做法是让顶部背景覆盖导航栏和首屏内容的一部分，然后在固定高度处直接切回页面底色。&lt;/p&gt;
&lt;p&gt;如果背景细节比较多，优先降低 &lt;code&gt;height&lt;/code&gt; 或换一张更干净的图，不要直接把文章卡片做得很透明。&lt;/p&gt;
&lt;p&gt;如果图片比较大，可以压缩成 WebP：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cwebp input.png -q 82 -o meteor-shower-background.webp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后把配置改成：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src: &quot;/images/meteor-shower-background.webp&quot;
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item></channel></rss>