<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DevOps on 随手记</title><link>https://www.bufio.cn/tags/devops/</link><description>Recent content in DevOps on 随手记</description><generator>Hugo</generator><language>zh-cn</language><copyright>© 2026 &lt;a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener"&gt;苏ICP备2023022553号-1&lt;/a&gt;</copyright><lastBuildDate>Wed, 20 May 2026 09:30:04 +0800</lastBuildDate><atom:link href="https://www.bufio.cn/tags/devops/index.xml" rel="self" type="application/rss+xml"/><item><title>USB-SATA 桥接芯片的 UAS 兼容性问题排查</title><link>https://www.bufio.cn/posts/usb-sata-uas-compatibility/</link><pubDate>Wed, 20 May 2026 09:30:04 +0800</pubDate><guid>https://www.bufio.cn/posts/usb-sata-uas-compatibility/</guid><description>&lt;p&gt;通过 USB 外接硬盘时，如果遇到磁盘看起来一直很忙，但实际吞吐很低，问题不一定出在文件系统或硬盘本体上。一次比较典型的场景是：USB-SATA 桥接芯片声称支持 UAS，但它的固件实现不稳定，Linux 自动启用 UAS 后反而触发命令超时、USB 设备重置，最终表现成系统层面的 I/O 卡顿。&lt;/p&gt;
&lt;p&gt;这篇文章记录一次这类问题的现象、原因和处理方式。&lt;/p&gt;
&lt;h2 id="问题现象"&gt;问题现象&lt;/h2&gt;
&lt;p&gt;故障最直观的表现是：外接硬盘几乎不可用，但监控上又看不出正常的高吞吐。&lt;/p&gt;
&lt;p&gt;常见现象包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;iostat&lt;/code&gt; 中磁盘 &lt;code&gt;%util&lt;/code&gt; 长时间接近或等于 &lt;code&gt;100%&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;实际 &lt;code&gt;r/s&lt;/code&gt;、&lt;code&gt;w/s&lt;/code&gt;、&lt;code&gt;rkB/s&lt;/code&gt;、&lt;code&gt;wkB/s&lt;/code&gt; 并不高；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;await&lt;/code&gt;、&lt;code&gt;svctm&lt;/code&gt; 或应用侧读写延迟异常升高；&lt;/li&gt;
&lt;li&gt;文件复制、解压、数据库读写、备份任务间歇性卡住；&lt;/li&gt;
&lt;li&gt;偶尔出现 &lt;code&gt;Input/output error&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dmesg&lt;/code&gt; 或 &lt;code&gt;journalctl -k&lt;/code&gt; 中反复出现 UAS abort、SCSI timeout、USB reset。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以先用下面这些命令观察：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;iostat -xz &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dmesg -T &lt;span class="p"&gt;|&lt;/span&gt; grep -Ei &lt;span class="s1"&gt;&amp;#39;uas|usb|reset|abort|I/O error|blk_update_request&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;journalctl -k -b &lt;span class="p"&gt;|&lt;/span&gt; grep -Ei &lt;span class="s1"&gt;&amp;#39;uas|usb|reset|abort|I/O error&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;比较典型的内核日志类似这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uas_eh_abort_handler ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scsi host... uas_eh_device_reset_handler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;usb ... reset SuperSpeed USB device number ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;blk_update_request: I/O error, dev sdX, sector ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果这些日志和外接硬盘卡顿时间点高度重合，就要怀疑 USB 存储协议层的问题。&lt;/p&gt;</description></item><item><title>在 Docker 中部署 mihomo，并让本机与局域网电脑接入</title><link>https://www.bufio.cn/posts/mihomo-docker-lan-setup/</link><pubDate>Tue, 19 May 2026 00:00:00 +0800</pubDate><guid>https://www.bufio.cn/posts/mihomo-docker-lan-setup/</guid><description>&lt;p&gt;mihomo 是 Clash.Meta 的延续版本，常见用法是把它作为一个代理内核运行在一台长期在线的机器上，然后让本机、手机、Windows 电脑、Linux 电脑都通过这台机器访问代理服务。&lt;/p&gt;
&lt;p&gt;这篇文章记录一个最实用的部署方式：在 Docker 里运行 mihomo，宿主机负责提供端口，局域网里的其他设备只需要把 HTTP / SOCKS 代理指向这台机器即可。&lt;/p&gt;
&lt;h2 id="总览先看整体链路"&gt;总览：先看整体链路&lt;/h2&gt;
&lt;p&gt;假设运行 Docker 的机器局域网 IP 是 &lt;code&gt;192.168.1.10&lt;/code&gt;，mihomo 在这台机器上监听 &lt;code&gt;7890&lt;/code&gt; 端口：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Windows / Linux / 手机
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | HTTP / SOCKS 代理：192.168.1.10:7890
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Docker 宿主机：192.168.1.10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | mihomo 容器
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;按规则直连或走代理节点
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;关键点只有三个：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;mihomo 配置里开启 &lt;code&gt;allow-lan: true&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;mihomo 监听地址使用 &lt;code&gt;bind-address: &amp;quot;*&amp;quot;&lt;/code&gt; 或宿主机局域网 IP。&lt;/li&gt;
&lt;li&gt;Docker 把 &lt;code&gt;7890&lt;/code&gt; 端口暴露给局域网。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="第一步准备目录"&gt;第一步：准备目录&lt;/h2&gt;
&lt;p&gt;在准备用作代理网关的机器上创建目录：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p ~/mihomo/config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/mihomo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;后面所有文件都放在 &lt;code&gt;~/mihomo&lt;/code&gt; 目录里：&lt;/p&gt;</description></item><item><title>在 macOS 上打包 Windows EXE 的好办法：用 GitHub Actions 自动编译</title><link>https://www.bufio.cn/posts/macos-build-windows-exe-github-actions/</link><pubDate>Fri, 15 May 2026 12:00:00 +0800</pubDate><guid>https://www.bufio.cn/posts/macos-build-windows-exe-github-actions/</guid><description>&lt;p&gt;如果你平时在 macOS 上写 Python 脚本、桌面小工具或命令行工具，最后却要发给 Windows 用户使用，最容易遇到的问题就是：我能不能直接在 Mac 上打包出 &lt;code&gt;.exe&lt;/code&gt;？&lt;/p&gt;
&lt;p&gt;结论先说清楚：&lt;strong&gt;不建议在 macOS 本机强行交叉打包 Windows EXE。更稳的办法是把代码推到 GitHub，让 GitHub Actions 在 Windows 环境里自动打包。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这篇文章按使用教程来写，从准备项目、创建 workflow、触发构建、下载产物，到常见问题排查，完整走一遍。&lt;/p&gt;
&lt;h2 id="总览为什么要用-github-actions-打包-exe"&gt;总览：为什么要用 GitHub Actions 打包 EXE&lt;/h2&gt;
&lt;p&gt;PyInstaller 这类打包工具通常不是“万能交叉编译器”。也就是说：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;要打 Windows &lt;code&gt;.exe&lt;/code&gt;，最好在 Windows 上运行打包命令。&lt;/li&gt;
&lt;li&gt;要打 macOS 应用，就在 macOS 上打。&lt;/li&gt;
&lt;li&gt;要打 Linux 可执行文件，就在 Linux 上打。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是 GitHub Actions 的特殊限制，而是很多 Python 原生依赖、动态库、运行时文件和系统 API 都跟目标操作系统绑定。你在 macOS 上直接打包，得到的通常是 macOS 可执行文件，而不是 Windows 真正可用的 &lt;code&gt;.exe&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;GitHub Actions 的思路是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;macOS 本地开发
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; git push 到 GitHub
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; GitHub Actions 启动 Windows Runner
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 安装 Python 和依赖
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 执行 PyInstaller
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 上传 exe 产物
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 在 Actions 页面下载
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样做的好处是：&lt;/p&gt;</description></item><item><title>Docker 日常维护、运行调试与排错教程：从 Compose 到 Swarm</title><link>https://www.bufio.cn/posts/docker-maintenance-debugging-compose-swarm/</link><pubDate>Wed, 29 Apr 2026 16:25:00 +0800</pubDate><guid>https://www.bufio.cn/posts/docker-maintenance-debugging-compose-swarm/</guid><description>&lt;p&gt;Docker 用久以后，问题通常不在“会不会启动一个容器”，而在日常维护和排错：容器为什么退出、日志在哪里看、端口为什么不通、磁盘为什么爆了、Compose 更新为什么没生效、Swarm 服务为什么一直 Pending。&lt;/p&gt;
&lt;p&gt;这篇文章按实际运维顺序整理：先看单机 Docker 的容器、镜像、日志、网络、存储和资源排查，再看 Compose 的项目级管理，最后看 Swarm 的集群级服务维护。&lt;/p&gt;
&lt;h2 id="总览docker-排错先分清三种运行层级"&gt;总览：Docker 排错先分清三种运行层级&lt;/h2&gt;
&lt;p&gt;Docker 相关问题先不要急着敲命令，先判断当前应用跑在哪一层：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;层级&lt;/th&gt;
 &lt;th&gt;常见命令&lt;/th&gt;
 &lt;th&gt;管理对象&lt;/th&gt;
 &lt;th&gt;适合场景&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;单机 Docker&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker run&lt;/code&gt;、&lt;code&gt;docker ps&lt;/code&gt;、&lt;code&gt;docker logs&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;container、image、volume、network&lt;/td&gt;
 &lt;td&gt;单机服务、临时调试、本地开发&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Docker Compose&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker compose up&lt;/code&gt;、&lt;code&gt;docker compose logs&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;一个项目里的多服务&lt;/td&gt;
 &lt;td&gt;开发环境、小型部署、依赖编排&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Docker Swarm&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;docker service&lt;/code&gt;、&lt;code&gt;docker stack&lt;/code&gt;、&lt;code&gt;docker node&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;service、task、stack、node&lt;/td&gt;
 &lt;td&gt;多节点集群、滚动更新、副本调度&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;排错时也按这个顺序看：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;服务不可用
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 容器是否存在、是否在运行
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 日志里有没有启动失败或业务异常
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 端口映射和网络是否正确
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; volume、配置、环境变量是否正确
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; CPU、内存、磁盘是否打满
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 如果是 Compose，看 project/service 维度
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 如果是 Swarm，看 node/service/task 维度
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="一日常巡检先看-docker-基本状态"&gt;一、日常巡检：先看 Docker 基本状态&lt;/h2&gt;
&lt;p&gt;先确认 Docker daemon 是否正常：&lt;/p&gt;</description></item><item><title>一次 HTTP 请求的完整旅程：从浏览器到 Nginx 再到后端服务</title><link>https://www.bufio.cn/posts/http-request-flow-browser-nginx-backend/</link><pubDate>Wed, 29 Apr 2026 15:05:00 +0800</pubDate><guid>https://www.bufio.cn/posts/http-request-flow-browser-nginx-backend/</guid><description>&lt;p&gt;我们在浏览器里输入一个网址，比如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://www.example.com/api/users
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;看起来只是按下回车，页面就返回了。但在这几百毫秒甚至几十毫秒里，浏览器、操作系统、DNS、TCP、TLS、Nginx、后端应用、数据库和缓存可能都参与了一次协作。&lt;/p&gt;
&lt;p&gt;这篇文章按时间顺序，把一次典型的 HTTPS 请求完整拆开：从浏览器发起请求，到 TCP 三次握手、TLS 密钥协商，再到 Nginx 接收连接、反向代理给后端服务，最后响应返回浏览器。&lt;/p&gt;
&lt;h2 id="总览请求链路长什么样"&gt;总览：请求链路长什么样&lt;/h2&gt;
&lt;p&gt;可以先看一个简化版流程图：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;用户输入 URL
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;浏览器解析 URL
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;DNS 解析域名 -&amp;gt; 得到服务器 IP
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TCP 三次握手 -&amp;gt; 建立可靠连接
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TLS 握手/密钥协商 -&amp;gt; 建立加密通道
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;浏览器发送 HTTP 请求
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nginx 接收请求
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─ 匹配 server_name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─ 匹配 location
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─ 处理静态资源 / gzip / header / 日志
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;proxy_pass 反向代理到后端应用
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;后端应用处理业务逻辑
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;后端返回 HTTP 响应
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nginx 返回响应给浏览器
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;浏览器解析 HTML/CSS/JS 并渲染页面
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;实际生产环境里，中间还可能有 CDN、负载均衡、WAF、Service Mesh、网关、缓存、队列、数据库等组件。但核心路径大体就是上面这些层次。&lt;/p&gt;</description></item><item><title>Fail2Ban 工作原理与常用运维操作</title><link>https://www.bufio.cn/posts/fail2ban-principles-and-operations/</link><pubDate>Tue, 28 Apr 2026 17:35:00 +0800</pubDate><guid>https://www.bufio.cn/posts/fail2ban-principles-and-operations/</guid><description>&lt;p&gt;Fail2Ban 是 Linux 服务器上很常见的一类安全防护工具，主要用来应对 SSH、Web 登录、邮件服务等场景里的暴力破解和重复异常请求。它不会替代防火墙、密钥登录、最小权限这些基础安全措施，但非常适合做一层自动化封禁：发现某个 IP 在短时间内频繁失败，就把它临时加入黑名单，过一段时间后再自动释放。&lt;/p&gt;
&lt;p&gt;这篇记录一下 Fail2Ban 的工作原理、安装和开机启动方式、常用规则配置，以及误封后如何把某个 IP 从黑名单里移出来。&lt;/p&gt;
&lt;h2 id="fail2ban-的工作原理"&gt;Fail2Ban 的工作原理&lt;/h2&gt;
&lt;p&gt;Fail2Ban 的核心逻辑可以概括成四步：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;监听日志文件或 systemd journal。&lt;/li&gt;
&lt;li&gt;用 filter 里的正则表达式匹配失败行为。&lt;/li&gt;
&lt;li&gt;在指定时间窗口内统计同一个 IP 的失败次数。&lt;/li&gt;
&lt;li&gt;达到阈值后执行 action，把 IP 加入防火墙黑名单。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这里有几个关键概念。&lt;/p&gt;
&lt;h2 id="jail"&gt;jail&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;jail&lt;/code&gt; 是 Fail2Ban 的规则单元。一个 jail 通常对应一个服务，例如 SSH、Nginx、Postfix、Dovecot 等。每个 jail 会指定：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;监控哪个服务。&lt;/li&gt;
&lt;li&gt;读取哪个日志。&lt;/li&gt;
&lt;li&gt;使用哪个 filter。&lt;/li&gt;
&lt;li&gt;允许失败多少次。&lt;/li&gt;
&lt;li&gt;统计时间窗口是多少。&lt;/li&gt;
&lt;li&gt;封禁多久。&lt;/li&gt;
&lt;li&gt;使用什么 action 封禁 IP。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如 SSH 的 jail 就是监听 SSH 登录日志，匹配登录失败记录，当同一个 IP 在一段时间内失败太多，就通过防火墙封禁。&lt;/p&gt;
&lt;h2 id="filter"&gt;filter&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;filter&lt;/code&gt; 负责识别“什么日志算失败”。它通常放在：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/etc/fail2ban/filter.d/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例如 SSH 常见 filter 是：&lt;/p&gt;</description></item><item><title>用 MCP 管理 Hugo 博客：这个项目是怎么搭起来的</title><link>https://www.bufio.cn/posts/how-to-create-ai-blog-by-mcp/</link><pubDate>Tue, 28 Apr 2026 16:45:00 +0800</pubDate><guid>https://www.bufio.cn/posts/how-to-create-ai-blog-by-mcp/</guid><description>&lt;p&gt;这个仓库表面上是一个很轻量的 Hugo 博客，实际目标更明确：把博客内容、构建部署、以及 AI 写作入口放在同一个工程里。最终形成的工作流是：文章仍然以 Markdown 存在仓库中，Hugo 负责生成静态站点，仓库流水线负责构建部署，而 &lt;code&gt;mcp/&lt;/code&gt; 目录里的 MCP 服务负责给 AI 提供一组可控的读写工具。&lt;/p&gt;
&lt;h2 id="项目目标"&gt;项目目标&lt;/h2&gt;
&lt;p&gt;这个项目解决的是一个很具体的问题：写博客时不想每次都手动打开仓库、创建 frontmatter、提交文章、再等待部署。更理想的方式是直接和 AI 对话，让 AI 能够读取已有文章、理解站点配置、创建新文章、修改元数据，必要时还能上传图片。&lt;/p&gt;
&lt;p&gt;为了不把 AI 直接暴露给整个文件系统，项目没有设计成“随便执行命令”的形式，而是把能力收敛成 MCP 工具。每个工具只做一件事，例如列文章、读文章、创建文章、更新文章、上传图片。这样既方便使用，也比较容易控制边界。&lt;/p&gt;
&lt;h2 id="顶层结构"&gt;顶层结构&lt;/h2&gt;
&lt;p&gt;当前仓库大致分成几块：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── hugo.toml # Hugo 站点配置
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── content/ # 博客内容
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── about.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── posts/ # Markdown 文章目录
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── layouts/partials/ # 本站覆盖的局部模板
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── themes/terminal/ # Hugo terminal 主题
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── .github/workflows/ # 构建与部署流水线
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── mcp/ # 自定义 blog MCP 服务
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;hugo.toml&lt;/code&gt; 定义站点基础信息，例如语言、标题、主题、分页和菜单。文章目录使用 Hugo 默认的 &lt;code&gt;content/posts&lt;/code&gt;。内容层仍然保持 Hugo 最朴素的方式：每篇文章是一个 Markdown 文件，文件头部用 TOML frontmatter 描述标题、日期、标签、摘要等信息。这样即使以后不使用 MCP，也不会被锁死在某个特殊系统里。&lt;/p&gt;</description></item></channel></rss>