<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>运维 on 魔都水滴</title>
    <link>https://blog.margrop.net/tag/%E8%BF%90%E7%BB%B4/</link>
    <description>Recent content in 运维 on 魔都水滴</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-CN</language>
    <lastBuildDate>Fri, 10 Jul 2026 22:00:00 +0800</lastBuildDate>
    <atom:link href="https://blog.margrop.net/tag/%E8%BF%90%E7%BB%B4/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>受够远程控制被限速？我把 RustDesk 服务端搬回自己家：多合一部署、避坑与安全加固</title>
      <link>https://blog.margrop.net/post/rustdesk-all-in-one-server-guide/</link>
      <pubDate>Fri, 10 Jul 2026 22:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/rustdesk-all-in-one-server-guide/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;RustDesk 是一款强调开源与自托管的远程桌面工具。客户端之间能直接连接时，画面和键鼠数据优先点对点传输；直连失败时，才由中继服务转发。把服务端部署在自己控制的机器上，最大的价值不是“完全不要服务器”，而是把设备登记、中继路径、密钥、账号和日志重新放回自己的控制范围。&lt;/p&gt;&#xA;&lt;p&gt;本文使用社区维护的 &lt;code&gt;lejianwen/rustdesk-server-s6&lt;/code&gt; 多合一镜像，把 RustDesk OSS 的 &lt;code&gt;hbbs&lt;/code&gt;、&lt;code&gt;hbbr&lt;/code&gt; 与社区 API、Web 管理功能放进一个容器。它适合家庭、实验室和小团队简化部署，但&lt;strong&gt;不是 RustDesk 官方发行的多合一服务端&lt;/strong&gt;。生产环境仍需自行评估社区镜像、固定版本或镜像摘要、备份数据，并测试升级和回滚。&lt;/p&gt;&#xA;&lt;p&gt;本文所有域名都使用 &lt;code&gt;example.com&lt;/code&gt;，没有展示真实 IP、私有域名、主机名、设备 ID、账号、密钥、Token、Cookie 或镜像仓库地址。公开截图来自项目官方页面或社区仓库公开素材。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>我把 Docker 命令行装进了“驾驶舱”：Portainer 2.39.4 从部署到避坑，一篇就够</title>
      <link>https://blog.margrop.net/post/portainer-ce-docker-deployment-guide/</link>
      <pubDate>Fri, 10 Jul 2026 15:30:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/portainer-ce-docker-deployment-guide/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Portainer 不是 Docker 的替代品，它更像 Docker 主机的“驾驶舱”：底层发动机仍然是 Docker Engine，Portainer 只是把容器、镜像、网络、卷和 Compose Stack 整理成网页按钮、表格与状态卡片。&lt;/p&gt;&#xA;&lt;p&gt;我用 &lt;code&gt;portainer/portainer-ce:2.39.4&lt;/code&gt; 做了一次隔离部署，完成初始化、接入本机 Docker、查看仪表盘、筛选容器、创建演示 Stack，并记录了真实截图。部署本身只要一条 &lt;code&gt;docker run&lt;/code&gt;，真正需要认真理解的却是三件事：&lt;code&gt;/data&lt;/code&gt; 必须持久化、&lt;code&gt;/var/run/docker.sock&lt;/code&gt; 权限非常高、生产环境不要把管理页面毫无遮挡地暴露到公网。&lt;/p&gt;&#xA;&lt;p&gt;本文没有展示完整 IP 地址、真实主机名、内网域名、管理员密码、Token、Cookie、私有镜像地址或生产容器名称。截图里的实验资源使用专门的演示名称，容器地址已遮盖。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>我最后留下的自用 Web 剪贴板，居然只有一个文本框</title>
      <link>https://blog.margrop.net/post/minimalist-web-notepad-lightweight-clipboard/</link>
      <pubDate>Fri, 10 Jul 2026 15:30:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/minimalist-web-notepad-lightweight-clipboard/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;我试过不少“跨设备剪贴板”“在线便签”“临时文本同步”工具，最后反而留下了一个看起来最寒酸的东西：&lt;code&gt;minimalist-web-notepad&lt;/code&gt;。它打开之后几乎什么都没有，只有一个文本编辑框，只支持纯文本，不支持登录用户、不支持富文本、不支持图片、不支持标签分类，甚至连“保存按钮”都不明显。&lt;/p&gt;&#xA;&lt;p&gt;但正是这种“功能少到没什么可炫耀”的设计，让它特别适合做自用轻量级 Web 剪贴板：临时从手机传一段命令到电脑、从电脑丢一段说明到平板、给自己留一段短文本、用 &lt;code&gt;curl&lt;/code&gt; 在脚本里读写一小段状态。它不像知识库，也不像团队协作文档，更像桌面旁边那张随手撕下来的便签纸。&lt;/p&gt;&#xA;&lt;p&gt;本文会用 &lt;code&gt;ahfeil/minimalist-web-notepad:latest&lt;/code&gt; 镜像演示 Docker Compose 部署；同时给出 Windows 11、Ubuntu 26.04、macOS 26 三套一键脚本，以及人工自动执行和 Agent 自动配置两种方法。全文不展示任何完整内网地址、内网域名、完整计算机名称或真实隐私数据。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>别把青龙数据直接硬搬！我实测了一次青龙迁白虎，真正的坑在这 5 个地方</title>
      <link>https://blog.margrop.net/post/qinglong-to-baihu-safe-migration/</link>
      <pubDate>Thu, 09 Jul 2026 10:30:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/qinglong-to-baihu-safe-migration/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;从青龙面板迁移到白虎面板，最危险的做法不是“不会迁”，而是“以为复制目录就等于迁移成功”。这次我在一台隔离 Docker 实验环境里实际跑了一遍：新建青龙容器，造了两条环境变量、两个定时任务和几份脚本；再把它们迁到一套全新白虎面板里，最后用 API 和白虎页面截图核对。&lt;/p&gt;&#xA;&lt;p&gt;最终可稳定迁移的是三类核心资产：&lt;code&gt;scripts&lt;/code&gt; 脚本文件、环境变量、定时任务。真正需要转换的是：青龙的数字 ID 要变成白虎的字符串 ID；青龙任务里的 &lt;code&gt;task xxx.py&lt;/code&gt; 要变成白虎能执行的命令；青龙的标签、启停状态、环境变量关系要写进白虎自己的表结构。迁移前必须备份白虎库，迁移时最好停掉白虎容器，迁移后必须做数量核对和页面验证。&lt;/p&gt;&#xA;&lt;p&gt;本文不展示任何真实内网地址、主机名、私有镜像仓库、真实 Cookie、真实 Token 或生产路径。截图来自实验环境，变量值也只使用脱敏样例。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>青龙面板还能公网裸奔吗？几个月前那次致命漏洞后，我更建议你看白虎面板</title>
      <link>https://blog.margrop.net/post/qinglong-baihu-panel-security/</link>
      <pubDate>Thu, 09 Jul 2026 10:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/qinglong-baihu-panel-security/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;青龙面板曾经是很多人自托管定时任务的默认选择：跑脚本、管环境变量、看日志、定时同步仓库都很方便。但 2026 年初公开爆出的青龙面板致命漏洞，把一个老问题重新摆到台面上：&lt;strong&gt;定时任务面板不是普通网页，它往往握着脚本、变量、通知密钥和执行权限。一旦认证被绕过，攻击者看到的不是一个登录页，而是一台可以被调度的机器。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;如果你只是新装一个轻量任务面板，我现在更建议优先评估白虎面板。白虎面板采用 Go + Vue3，主打轻量、高性能、低系统开销，并且官方 README 已经明确支持 Docker / Docker Compose 部署、Mise 运行时管理、仓库任务同步、执行日志和多渠道通知。它不是“青龙的一比一复制品”，但对很多个人脚本托管场景已经够用。&lt;/p&gt;&#xA;&lt;p&gt;如果你因为兼容旧脚本、历史任务或迁移成本，必须临时继续用青龙面板：&lt;strong&gt;不要把它直接暴露在公网。&lt;/strong&gt; 至少在前面加 VPN、零信任访问、反向代理二次认证、IP allowlist、WAF 或其它访问控制。本文给出 Windows 11、Ubuntu 26.04、macOS 26 三套一键脚本，默认部署白虎；只有显式指定时才部署青龙，并且都会把面板放到 Basic Auth 保护后面。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>电脑越用越满？让 AI Agent 安全清掉 Windows 11、Ubuntu 26.04 和 macOS 26 的垃圾文件</title>
      <link>https://blog.margrop.net/post/ai-agent-cleanup-windows11-ubuntu2604-macos26/</link>
      <pubDate>Sun, 28 Jun 2026 07:15:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/ai-agent-cleanup-windows11-ubuntu2604-macos26/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;清理垃圾文件这件事，最怕的不是“清不干净”，而是“清得太猛”。Windows 11、Ubuntu 26.04、macOS 26 上真正值得自动化清理的，通常是临时目录、包管理缓存、旧日志、回收站或废纸篓、可再生成的缓存文件；不应该让脚本随手碰用户文档、照片、浏览器 Profile、密钥、证书、虚拟机镜像和业务数据。&lt;/p&gt;&#xA;&lt;p&gt;这篇文章给出两条路：&lt;strong&gt;人工自动执行&lt;/strong&gt;，也就是你自己复制脚本，先 dry-run 看清楚，再加执行开关；&lt;strong&gt;Agent 自动配置&lt;/strong&gt;，也就是把清理目标、边界、预演、确认和验收交给 Codex、Claude、OpenClaw、HermesAgent 等 Agent 执行。三套脚本分别覆盖 Windows 11、Ubuntu 26.04、macOS 26，不依赖第三方服务，不下载清理软件，也不包含任何真实内网地址、真实计算机名、私有域名或密钥。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>macOS 26 后台守护进程开机自启：frp / EasyTier 应该放进 LaunchDaemon，而不是登录项</title>
      <link>https://blog.margrop.net/post/macos-26-launchdaemon-boot-service-frp-easytier/</link>
      <pubDate>Sat, 27 Jun 2026 17:12:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/macos-26-launchdaemon-boot-service-frp-easytier/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;如果你要让 &lt;code&gt;frp&lt;/code&gt;、&lt;code&gt;EasyTier&lt;/code&gt;、同步器、采集器、机器人、代理程序这类后台服务在 macOS 26 上开机自动运行，核心不是“把命令藏在哪里”，而是“让系统的服务管理器负责它”。这篇文章只讨论后台常驻服务，不讨论普通桌面 App 的登录启动。&lt;/p&gt;&#xA;&lt;p&gt;macOS 26 上如果希望后台服务在用户登录前就启动，应该用 /Library/LaunchDaemons。登录项和 LaunchAgent 更像“人进门后打开的工具”，而 LaunchDaemon 才像“楼里的电梯和水泵”，机器起来就要工作。&lt;/p&gt;&#xA;&lt;p&gt;我会给出两条路：&lt;strong&gt;人工配置&lt;/strong&gt;，适合你想理解每一步；&lt;strong&gt;Agent/一键脚本自动配置&lt;/strong&gt;，适合你已经知道二进制和配置文件放在哪里，希望复制一段脚本直接落地。脚本不依赖第三方服务，不下载外部 wrapper，也不会写入任何真实 IP、真实主机名或私有域名。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Windows 11/10 后台服务开机自启：把 frp、EasyTier 变成真正无人值守的后台任务</title>
      <link>https://blog.margrop.net/post/windows-11-10-background-service-autostart-frp-easytier/</link>
      <pubDate>Sat, 27 Jun 2026 17:11:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/windows-11-10-background-service-autostart-frp-easytier/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;如果你要让 &lt;code&gt;frp&lt;/code&gt;、&lt;code&gt;EasyTier&lt;/code&gt;、同步器、采集器、机器人、代理程序这类后台服务在 Windows 11/10 上开机自动运行，核心不是“把命令藏在哪里”，而是“让系统的服务管理器负责它”。这篇文章只讨论后台常驻服务，不讨论普通桌面 App 的登录启动。&lt;/p&gt;&#xA;&lt;p&gt;Windows 的关键判断是：程序是不是原生 Windows Service。frp、EasyTier 这类常见命令行守护进程通常更适合用计划任务在系统启动时运行，因为计划任务是系统内置能力，不需要 NSSM、WinSW 之类第三方 wrapper。&lt;/p&gt;&#xA;&lt;p&gt;我会给出两条路：&lt;strong&gt;人工配置&lt;/strong&gt;，适合你想理解每一步；&lt;strong&gt;Agent/一键脚本自动配置&lt;/strong&gt;，适合你已经知道二进制和配置文件放在哪里，希望复制一段脚本直接落地。脚本不依赖第三方服务，不下载外部 wrapper，也不会写入任何真实 IP、真实主机名或私有域名。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Ubuntu 26.04 后台服务开机自启：把 frp / EasyTier 交给 systemd，别再手敲命令了</title>
      <link>https://blog.margrop.net/post/ubuntu-2604-systemd-boot-service-frp-easytier/</link>
      <pubDate>Sat, 27 Jun 2026 17:10:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/ubuntu-2604-systemd-boot-service-frp-easytier/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;如果你要让 &lt;code&gt;frp&lt;/code&gt;、&lt;code&gt;EasyTier&lt;/code&gt;、同步器、采集器、机器人、代理程序这类后台服务在 Ubuntu 26.04 上开机自动运行，核心不是“把命令藏在哪里”，而是“让系统的服务管理器负责它”。这篇文章只讨论后台常驻服务，不讨论普通桌面 App 的登录启动。&lt;/p&gt;&#xA;&lt;p&gt;Ubuntu 26.04 上后台服务的标准答案不是把命令塞进 shell 启动脚本，而是写成 systemd unit。systemd 能在网络就绪后启动它，能记录日志，能失败重启，也能在关机时按顺序停止。&lt;/p&gt;&#xA;&lt;p&gt;我会给出两条路：&lt;strong&gt;人工配置&lt;/strong&gt;，适合你想理解每一步；&lt;strong&gt;Agent/一键脚本自动配置&lt;/strong&gt;，适合你已经知道二进制和配置文件放在哪里，希望复制一段脚本直接落地。脚本不依赖第三方服务，不下载外部 wrapper，也不会写入任何真实 IP、真实主机名或私有域名。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>别再让 Agent 吞掉你的 Token：我把 Headroom 接到 NewAPI、OpenClaw 和 HermesAgent 的完整实战</title>
      <link>https://blog.margrop.net/post/headroom-newapi-openclaw-hermesagent-token-compression-guide/</link>
      <pubDate>Sat, 20 Jun 2026 12:30:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/headroom-newapi-openclaw-hermesagent-token-compression-guide/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这次我没有替换原来的 NewAPI，也没有让 OpenClaw / HermesAgent 直接改用一个不确定的新网关。真正做法是：在 NewAPI 前面加一层 Headroom 代理，把所有已经使用 OpenAI-compatible 协议的调用改到 &lt;code&gt;http://&amp;lt;headroom-host&amp;gt;:8787/v1&lt;/code&gt;，而原来的 NewAPI 入口继续保留。这样 Agent 发来的长上下文先经过 Headroom 压缩，再转发给 NewAPI，最后仍由 NewAPI 统一路由到后端模型。&lt;/p&gt;&#xA;&lt;p&gt;最关键的原则只有一句：&lt;strong&gt;先测试，后修改；只迁移测试通过的 OpenAI-compatible 项；非 OpenAI 协议的 fallback 不碰。&lt;/strong&gt; 这篇文章既是复盘，也是一份可以直接交给 Agent 或人工照着执行的操作指南。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Ubuntu 关机要等 90 秒?Python asyncio 服务不肯接 SIGTERM 的排查与修复</title>
      <link>https://blog.margrop.net/post/ubuntu-shutdown-stuck/</link>
      <pubDate>Fri, 19 Jun 2026 10:58:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/ubuntu-shutdown-stuck/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;这台升级到 24.04 的代理机,关机变成了一件折磨人的事:&lt;code&gt;systemctl reboot&lt;/code&gt; 之后,SSH 不掉、灯不灭,要干等 &lt;strong&gt;90 秒&lt;/strong&gt; 才进入真正的 shutdown 流程。journalctl 里很明确:&lt;code&gt;smart-proxy.service: State &#39;stop-sigterm&#39; timed out. Killing.&lt;/code&gt;——systemd 给了 SIGTERM,等 90 秒没人响应,只能 SIGKILL 强杀。&lt;/p&gt;&#xA;&lt;p&gt;根因不是 systemd 的错,也不是 Ubuntu 的错,是 &lt;strong&gt;Python 的 asyncio 服务在收到 SIGTERM 后,没有真正去结束它的子任务&lt;/strong&gt;——它正卡在某个 &lt;code&gt;socket.recv&lt;/code&gt; 上,Python 解释器根本不主动去看&amp;quot;有人叫我走&amp;quot;。&lt;/p&gt;&#xA;&lt;p&gt;修复分两步,缺一不可:&lt;strong&gt;(1)&lt;/strong&gt; 给两个 Python unit 写 systemd drop-in,把 &lt;code&gt;TimeoutStopSec&lt;/code&gt; 从默认的 90s 缩到 20s;&lt;strong&gt;(2)&lt;/strong&gt; 在 Python 服务里主动遍历 &lt;code&gt;asyncio.all_tasks()&lt;/code&gt;,收到 SIGTERM 后把所有 in-flight 的 handler &lt;code&gt;cancel()&lt;/code&gt; 掉,再用 &lt;code&gt;asyncio.wait_for(self.stop(), timeout=10)&lt;/code&gt; 包一层做兜底。改完之后,同样一次 &lt;code&gt;reboot&lt;/code&gt;,从 90 秒掉到 1 秒。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Portainer 改个 stack 一直 500？我花了一晚上才明白，是 Docker 引擎里多了一个「重影」网络</title>
      <link>https://blog.margrop.net/post/portainer-500-duplicate-compose-network-enigma/</link>
      <pubDate>Sat, 13 Jun 2026 08:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/portainer-500-duplicate-compose-network-enigma/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Portainer 改一个 stack，浏览器上弹出 &lt;code&gt;500 Internal Server Error&lt;/code&gt;。你以为又是 YAML 写错了，回去检查 compose 语法、缩进、引号、镜像 tag，全部都对。但每次重试都是同一个 500。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;真正的问题藏在 HTTP response body 的 &lt;code&gt;message&lt;/code&gt; 字段最深处：&lt;code&gt;network librespeed_default is ambiguous (2 matches found on name)&lt;/code&gt;。&lt;/strong&gt; 也就是说，Docker 引擎里同时存在两个 &lt;code&gt;librespeed_default&lt;/code&gt; 网络——两个 ID、两个 &lt;code&gt;Created&lt;/code&gt; 时间、两个 &lt;code&gt;com.docker.compose.config-hash&lt;/code&gt;，但名字一模一样。Compose 启动时让引擎去 lookup 名字，引擎说「我选不出来」，compose up 失败，Portainer 把这条错误原样包成 500 退给浏览器。&lt;/p&gt;&#xA;&lt;p&gt;修复办法朴素到尴尬：在引擎上&lt;strong&gt;删掉其中一个孤儿网络&lt;/strong&gt;（&lt;code&gt;docker network rm &amp;lt;id&amp;gt;&lt;/code&gt; 或在 Portainer 的 Networks 里点 Remove），再原样点一次 Update the stack，就过了。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;这篇文章源于一次真实的 stack 改挂载路径的过程。全程我已经把所有内网地址、镜像仓库地址、卷挂载路径、容器名、用户名密码用 &lt;code&gt;&amp;lt;PLACEHOLDER&amp;gt;&lt;/code&gt; 替换，只保留公开信息、官方源码、错误文本这些可分享的内容。&lt;/p&gt;</description>
    </item>
    <item>
      <title>后台进程一断开 Shell 就消失？别只靠 nohup 了，理解 setsid 和进程生命周期的真相</title>
      <link>https://blog.margrop.net/post/setsid-daemon-process-survival/</link>
      <pubDate>Mon, 01 Jun 2026 07:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/setsid-daemon-process-survival/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;你启动了一个后台服务，&lt;code&gt;nohup&lt;/code&gt; 用了，&lt;code&gt;&amp;amp;&lt;/code&gt; 也加了，日志也重定向了，一切看起来都很正常。但当你关闭终端、断开 SSH，或者——更隐蔽的情况——当自动化工具执行完脚本后，这个进程就悄无声息地消失了。你检查 &lt;code&gt;ps&lt;/code&gt;，找不到它；检查端口，也没有监听。如果你遇到过这种情况，你不是一个人。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;真正的根因不是 SIGHUP——至少不完全是。问题出在进程组和会话的归属关系上。&lt;/strong&gt; &lt;code&gt;nohup&lt;/code&gt; 只是让进程忽略 SIGHUP 信号，但如果进程所属的会话 leader 被销毁了，终端 IO 断裂了，或者父进程组被一起收割了，进程仍然可能死掉。真正彻底的解决方案是 &lt;code&gt;setsid&lt;/code&gt;：它创建一个全新的会话，让进程完全脱离原会话的控制终端，不再属于父 shell 的进程组——因此父 shell 退出时，SIGHUP 根本传播不到它那里去。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;这篇文章源自一次真实的 CLIProxyAPI 服务排障。服务通过 &lt;code&gt;nohup&lt;/code&gt; 启动后，每次自动化脚本执行完毕就消失，管理界面一直报“网络连接失败”。排查后发现是一个隐蔽的 Unix 进程生命周期问题。这类问题在云原生开发机、CI runner、SSH jump host 和容器化工作流里非常常见，但往往因为对进程模型理解不深而被误判为“软件有 bug”。&lt;/p&gt;&#xA;&lt;p&gt;为了不泄露隐私，本文不会出现真实内网地址、真实 token 或路径。所有配置片段使用 &lt;code&gt;&amp;lt;PLACEHOLDER&amp;gt;&lt;/code&gt; 占位。&lt;/p&gt;</description>
    </item>
    <item>
      <title>HermesAgent 为什么一直不回微信和企业微信？我最后排到的根因居然是本地 relay 的 3 秒超时</title>
      <link>https://blog.margrop.net/post/hermesagent-wechat-wecom-relay-timeout-debugging/</link>
      <pubDate>Sun, 31 May 2026 08:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/hermesagent-wechat-wecom-relay-timeout-debugging/</guid>
      <description>先说结论 这次故障看起来像“模型不行”或者“微信通道坏了”，但真正把消息链路掐断的，是我本地那层 relay 的超时设置。它把整条上游请求的等待窗口限制成了 3 秒，而真实的 WeChat / WeCom 消息 turn 往往需要更久才能从新 API 网关拿到完整回复。结果就是：relay 先断开，HermesAgent 只能看到 Connection error、RemoteProtocolError，然后主模型和 fallback 一起被耗尽。&#xA;更准确地说，这不是 HermesAgent 核心代码的问题，也不是模型名的问题，而是一个本地外置组件的连接策略问题。把 connect timeout 和 response wait 混成同一个超时，等于给长请求做了一个错误的截止时间。修复方式也不复杂：连接阶段保留短超时，连接成功后把 socket 切回阻塞等待；同时把 relay 做成独立、可持续启动的服务，不再把它绑死在临时 shell 里。&#xA;问题背景 HermesAgent 这条链路不是单机脚本，而是一条完整的消息生产线。用户从微信或企业微信发出一句话，消息会先进入 Hermes 的通道层，再进入 Gateway，接着经过本地 relay 转发到自建的 NewAPI 网关，最后才到模型服务。模型回来的内容还要经过 Hermes 的消息整理、工具调用处理、最终拼接，再发回原始通道。&#xA;这种结构的好处是灵活，坏处也很现实：任何一层都可能制造“看起来像模型故障”的表象。你看到的是“没有回复”或者“Connection error”，但根因可能在更外层的 relay、socket、超时、代理或者会话路由里。&#xA;这次我一开始也走了老路，先怀疑模型配置。因为从表象看，主模型和 fallback 都失败了，日志里反复出现：&#xA;Primary model failed switching to fallback API failed after 1 retries Connection error Max retries exhausted 如果你只看这一段，很容易得出“模型端不稳定”的结论。但这类结论通常太早。因为同一批模型在别的入口上是能正常工作的，/v1/models 也能返回，简单的 health check 也没有异常。真正出问题的是“真实消息 turn”。</description>
    </item>
    <item>
      <title>OpenClaw 升级指南：从入门到精通的完整攻略</title>
      <link>https://blog.margrop.net/post/openclaw-hermesagent-upgrade-guide/</link>
      <pubDate>Fri, 29 May 2026 09:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/openclaw-hermesagent-upgrade-guide/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;OpenClaw是一款强大的个人 AI 助手，支持多种消息渠道和 AI 模型。升级 OpenClaw 其实非常简单，最推荐的方式是使用 &lt;code&gt;openclaw update&lt;/code&gt; 命令。本文将详细介绍各种升级方式，包括从 npm 包安装到 git 源码安装的切换，以及升级后的验证和回滚策略。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;本文所有示例都使用公开项目、公开链接和占位符，不包含真实服务器地址、账号、Token、业务配置或任何内网信息。文中配图来自 OpenClaw 官方仓库和文档，内容按其 MIT 授权引用。&lt;/p&gt;</description>
    </item>
    <item>
      <title>彻底打通内网！在 Ubuntu 26.04 上完美部署 Tailscale 实现无感异地组网</title>
      <link>https://blog.margrop.net/post/seamless-homelab-networking-deploy-tailscale-ubuntu-2604/</link>
      <pubDate>Tue, 26 May 2026 14:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/seamless-homelab-networking-deploy-tailscale-ubuntu-2604/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;跨运营商、无公网 IP、多端互联，一直都是 Homelab 玩家与企业运维的核心痛点。本文将详细演示如何在最新发布的 Ubuntu 26.04 (Resolute Raccoon) 系统上，利用最新的 APT 秘钥环（Keyring）标准，优雅地安装和配置最新版的 Tailscale。我们不仅会给出干净利落的命令行安装过程，还会深入剖析 Tailscale 的网络拓扑、子网路由（Subnet Router）以及出口节点（Exit Node）的高级配置，帮助你彻底打通家里的群晖 NAS、PVE 虚拟机以及随身携带的手机与笔记本电脑。&lt;/p&gt;&#xA;&lt;p&gt;本文所有操作均在 Ubuntu 26.04 (Resolute Raccoon) 干净的环境中测试通过，所有内部 IP、密钥、令牌和主机名均已进行脱敏处理，以保障网络安全。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>Proxmox VE 9.2 正式发布：这次不只是换内核，集群终于会自己找平衡了</title>
      <link>https://blog.margrop.net/post/proxmox-ve-9-2-dynamic-load-balancer-release/</link>
      <pubDate>Sat, 23 May 2026 12:46:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/proxmox-ve-9-2-dynamic-load-balancer-release/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Proxmox VE 9.2 已经在 2026 年 5 月 21 日正式发布。表面看，它是 Debian 13.5 Trixie、Linux Kernel 7.0、QEMU 11.0、LXC 7.0、ZFS 2.4、Ceph Squid/Tentacle 的一次版本栈更新；但真正值得关注的，是它把“集群怎么自己变得更均衡”“维护窗口怎么避免 HA 误动作”“SDN 怎么从 VLAN/VXLAN 走向 Fabric 化”这些长期存在的运维问题，推进到了更可操作的层面。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;如果你只在单节点 Homelab 上跑几台虚拟机，9.2 未必会让你立刻觉得天翻地覆；但如果你已经有三节点以上集群、HA 资源、Ceph、复杂网络、跨节点迁移、Windows 安全启动或者自定义 CPU 兼容性需求，这个版本就不只是“可以升级”，而是值得认真读 release notes 的版本。&lt;/p&gt;&#xA;&lt;p&gt;本文整理 Proxmox VE 9.2 正式发布内容，并结合实际运维视角，把“发布了什么”“解决了什么痛点”“升级前要注意什么”“哪些场景可以先等一等”讲清楚。文中所有主机名、地址、集群名、账号和命令输出都使用占位符，不包含任何真实内网信息。&lt;/p&gt;</description>
    </item>
    <item>
      <title>PVE 8 升 9 别硬刚：一句话交给 Agent，或者按这份清单手工升级</title>
      <link>https://blog.margrop.net/post/pve8-to-pve9-agent-manual-upgrade-guide/</link>
      <pubDate>Tue, 12 May 2026 19:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/pve8-to-pve9-agent-manual-upgrade-guide/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Proxmox VE 8 升级到 9 的本质不是“复制几条命令”，而是一次 Debian Bookworm 到 Trixie、PVE 8.4 到 PVE 9.x、内核与存储网络组件一起变化的系统升级。最省时间的方式，是把检查、备份核对、日志记录、命令执行和升级后验证交给 Codex、Claude、OpenClaw、HermesAgent 这类 Agent；但涉及重启、仓库切换、包删除提示、配置文件覆盖提示时，仍然必须由人确认。想完全手工做也没问题，本文后半部分给出一套可以逐步执行的人工升级清单。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;这篇文章写给两类人：一类是已经习惯让 Agent 管理机器，想用一句话把 PVE 8 到 9 的升级流程交给工具跑完；另一类是更喜欢自己敲命令，希望有一份顺序清楚、风险点明确、可以照着核对的手工操作稿。&lt;/p&gt;&#xA;&lt;p&gt;文中所有主机名、地址、仓库、token、账号都使用占位符，不包含任何真实内网信息。请把 &lt;code&gt;&amp;lt;PVE_NODE&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;BACKUP_TARGET&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;ADMIN_CONSOLE&amp;gt;&lt;/code&gt; 这类内容替换成你自己的环境。生产环境升级前，请以 Proxmox 官方文档为准，并先确认备份可以恢复。&lt;/p&gt;</description>
    </item>
    <item>
      <title>【转】ImmortalWrt 旁路由安装与配置</title>
      <link>https://blog.margrop.net/post/zhuan-immortalwrt-pang-lu-you-install-config/</link>
      <pubDate>Mon, 11 May 2026 21:10:55 +0800</pubDate>
      <guid>https://blog.margrop.net/post/zhuan-immortalwrt-pang-lu-you-install-config/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;这篇文章转载自 Egg Targaryen 的《ImmortalWrt旁路由安装与配置》，原文采用 &lt;code&gt;CC BY-NC-SA 4.0&lt;/code&gt; 许可发布。本文保留原文的操作顺序与截图，并按本站排版做了轻微格式调整。&lt;/p&gt;&#xA;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>【转】Synology DiskStation Administration CLI Guide 官方文档导读与命令速查</title>
      <link>https://blog.margrop.net/post/zhuan-synology-diskstation-administration-cli-guide/</link>
      <pubDate>Thu, 30 Apr 2026 18:14:05 +0800</pubDate>
      <guid>https://blog.margrop.net/post/zhuan-synology-diskstation-administration-cli-guide/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;先说结论&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Synology 这份官方 CLI 管理指南并不是一本面向普通 DSM 图形界面用户的入门手册，而是一份给脚本、自动化和系统集成场景准备的命令参考。它覆盖了 DSM 中最常见的几类管理动作：本地用户、本地群组、共享文件夹、网络配置、服务控制、工作组或 ADS 域设置，以及错误码查询。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;这篇文章是基于 Synology 官方 PDF《CLI Administrator Guide for Synology NAS》整理的中文导读和命令速查。由于原 PDF 属于 Synology 官方版权文档，本文不会全文复制或逐段翻译原文，而是按博客阅读习惯重新组织成一份便于检索、理解和日常运维使用的双语整理稿。需要逐字核对参数定义、版本差异或法律声明时，请直接阅读文末的官方 PDF 来源。&lt;/p&gt;</description>
    </item>
    <item>
      <title>PVE 中给 Ubuntu 虚拟机扩容磁盘——从 Web 界面到系统内部的完整操作</title>
      <link>https://blog.margrop.net/post/pve-ubuntu-vm-disk-resize/</link>
      <pubDate>Mon, 23 Mar 2026 10:30:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/pve-ubuntu-vm-disk-resize/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;写在前面&lt;/strong&gt;&#xA;在使用 Proxmox VE 管理虚拟化环境时，磁盘空间不足是迟早会遇到的问题。也许是一台跑 Docker 的 Ubuntu 镜像越拉越多，也许是数据库日志把根分区撑满了——总之，扩容是 PVE 运维的必修课。本文从 PVE Web 界面的磁盘 Resize 开始，到 Ubuntu 虚拟机内部 LVM 扩容的每一步命令，手把手带你完成整个流程。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-为什么需要扩容&#34;&gt;1 为什么需要扩容？&lt;/h2&gt;&#xA;&lt;p&gt;PVE 创建虚拟机时通常会分配一个固定大小的虚拟磁盘（比如 32GB）。随着业务发展，这个空间可能不够用了。好在 PVE 支持在线扩容虚拟磁盘，而 Ubuntu 默认安装使用的 LVM 也天然支持动态扩展逻辑卷，两者配合非常方便。&lt;/p&gt;</description>
    </item>
    <item>
      <title>SSH 密钥算法 Ed25519 与 RSA 的前世今生，以及今天该怎么用</title>
      <link>https://blog.margrop.net/post/ssh-ed25519-and-rsa-history-and-best-practices/</link>
      <pubDate>Mon, 02 Mar 2026 09:00:00 +0800</pubDate>
      <guid>https://blog.margrop.net/post/ssh-ed25519-and-rsa-history-and-best-practices/</guid>
      <description>&lt;p&gt;很多人第一次接触 SSH，都是从一行命令开始的：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssh-keygen -t rsa&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这条命令并没有错，但它背后有一个经常被忽略的问题：&#xA;我们讨论的到底是“RSA 这种密钥类型”，还是 &lt;code&gt;ssh-rsa&lt;/code&gt; 这种“签名算法”？&lt;/p&gt;&#xA;&lt;p&gt;这两个概念在很多旧教程里被混用，导致不少人一边以为自己“还在用老旧不安全方案”，一边又不知道怎么迁移，甚至在新系统和老设备之间反复踩坑。&lt;/p&gt;&#xA;&lt;p&gt;这篇文章就把这件事讲清楚：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;RSA 和 Ed25519 在 SSH 世界里是怎么一路走来的。&lt;/li&gt;&#xA;&lt;li&gt;为什么今天大家都在推荐 Ed25519。&lt;/li&gt;&#xA;&lt;li&gt;如果你线上还有一堆老机器，应该怎么稳妥迁移。&lt;/li&gt;&#xA;&lt;li&gt;2026 年这个时间点，个人和团队应该采用什么默认策略。&lt;/li&gt;&#xA;&lt;/ol&gt;</description>
    </item>
  </channel>
</rss>
