<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>喵の史</title>
  
  
  <link href="https://szxiot.com/atom.xml" rel="self"/>
  
  <link href="https://szxiot.com/"/>
  <updated>2026-07-07T14:06:47.266Z</updated>
  <id>https://szxiot.com/</id>
  
  <author>
    <name>Cat</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>一次 SSH 登录卡死的完整排查:macOS ssh-agent 静默崩溃 61 次的真凶</title>
    <link href="https://szxiot.com/2026/07/07/ssh-agent-error/"/>
    <id>https://szxiot.com/2026/07/07/ssh-agent-error/</id>
    <published>2026-07-07T14:30:00.000Z</published>
    <updated>2026-07-07T14:06:47.266Z</updated>
    
    <content type="html"><![CDATA[<p>今天回来,要帮同学远程运维一下之前的服务器(他忘记续费了),忽然发现运维脚本执行后没反应(往常1分钟一台跑完的).</p><span id="more"></span><h2 id="问题现象"><a href="#问题现象" class="headerlink" title="问题现象"></a>问题现象</h2><p>在 macOS 上 SSH 登录一台 Ubuntu 服务器,连接永久卡死。<code>ssh -v</code> 的调试输出停在:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">debug1: Authentications that can continue: publickey</span><br><span class="line">debug1: Next authentication method: publickey</span><br></pre></td></tr></table></figure><p>之后再无任何输出,进程既不报错也不超时,就这样一直挂着。</p><p>更诡异的是:</p><ul><li><code>ssh-add -l</code> 同样卡死</li><li><strong>重启电脑后问题依旧</strong></li><li>换用系统自带的 <code>/usr/bin/ssh</code>(9.x)和 Homebrew 的 OpenSSH 10.2 都卡</li></ul><!-- more --><h2 id="排查思路-逐层缩小范围"><a href="#排查思路-逐层缩小范围" class="headerlink" title="排查思路:逐层缩小范围"></a>排查思路:逐层缩小范围</h2><h3 id="第一层-定位卡死的环节"><a href="#第一层-定位卡死的环节" class="headerlink" title="第一层:定位卡死的环节"></a>第一层:定位卡死的环节</h3><p><code>-v</code> 日志停在 <code>Next authentication method: publickey</code>,下一步本应是 <code>Offering public key ...</code>。在这两步之间,ssh 客户端会做一件事:<strong>向 ssh-agent 查询可用密钥</strong>。agent 不响应,客户端就无限等待。</p><p>初步怀疑 agent。检查环境变量:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">echo</span> <span class="variable">$SSH_AUTH_SOCK</span></span><br><span class="line">/var/run/com.apple.launchd.b6Kz3tJtrK/Listeners</span><br></pre></td></tr></table></figure><p>这是 macOS 系统 launchd 管理的标准 agent socket,路径本身正常。</p><h3 id="第二层-绕过-agent-做对照实验"><a href="#第二层-绕过-agent-做对照实验" class="headerlink" title="第二层:绕过 agent 做对照实验"></a>第二层:绕过 agent 做对照实验</h3><p>关键的分流测试——让 ssh 完全不碰 agent:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh -o IdentityAgent=none -o IdentitiesOnly=<span class="built_in">yes</span> -i ~/.ssh/id_rsa root@&lt;server&gt;</span><br></pre></td></tr></table></figure><p><strong>立即成功登录。</strong> 这一步把问题 100% 锁定在 ssh-agent 环节:服务器没问题、网络没问题、密钥没问题,就是 agent 死了。</p><blockquote><p>小插曲:先用 <code>id_ed25519</code> 测试时返回 <code>Permission denied (publickey)</code>——虽然被拒,但”立即返回”本身就是有效信息(说明绕过 agent 后流程通畅),换成服务器上实际授权的 <code>id_rsa</code> 即成功。</p></blockquote><h3 id="第三层-审问-launchd"><a href="#第三层-审问-launchd" class="headerlink" title="第三层:审问 launchd"></a>第三层:审问 launchd</h3><p>macOS 上系统 ssh-agent 是 socket 激活式的:launchd 监听 socket,有连接进来才拉起 <code>/usr/bin/ssh-agent -l</code>。查看服务状态:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ launchctl <span class="built_in">print</span> gui/$(<span class="built_in">id</span> -u)/com.openssh.ssh-agent</span><br><span class="line">...</span><br><span class="line">state = spawn scheduled</span><br><span class="line">runs = 61</span><br><span class="line">last <span class="built_in">exit</span> code = 255</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p><strong>铁证:<code>runs = 61</code>,<code>last exit code = 255</code>。</strong> launchd 一直在拉起 agent,但它每次启动后立即以 255 退出,已经反复崩了 61 次。客户端卡死的机制也清晰了:</p><ol><li><code>ssh</code> &#x2F; <code>ssh-add</code> 连接 socket</li><li>launchd 收下连接,拉起 agent</li><li>agent 秒退,连接悬空</li><li>客户端永远等不到响应</li><li>launchd 有 10 秒的重启节流,于是日志里每 10 秒一次”Successfully spawned → service inactive”的循环</li></ol><p>用统一日志确认了这个循环:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">log</span> show --last 2m --predicate <span class="string">&#x27;process == &quot;ssh-agent&quot; OR eventMessage CONTAINS &quot;ssh-agent&quot;&#x27;</span> --info --debug</span><br></pre></td></tr></table></figure><p>每次生命周期只有 <strong>5 毫秒</strong>:spawn → 查询用户信息(getpwuid)→ 退出。没有留下任何错误日志——launchd 模式下 stderr 被丢弃了。</p><h3 id="第四层-让它当面崩给我看"><a href="#第四层-让它当面崩给我看" class="headerlink" title="第四层:让它当面崩给我看"></a>第四层:让它当面崩给我看</h3><p>既然 launchd 模式下看不到报错,那就手动跑,把 stderr 抓出来:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ /usr/bin/ssh-agent; <span class="built_in">echo</span> <span class="string">&quot;exit: $?&quot;</span></span><br><span class="line">agent_cleanup_stale: <span class="built_in">stat</span> <span class="string">&quot;/Users/cat/.ssh/agent/.&quot;</span>: Permission denied</span><br><span class="line">agent_cleanup_stale: <span class="built_in">stat</span> <span class="string">&quot;/Users/cat/.ssh/agent/..&quot;</span>: Permission denied</span><br><span class="line">unix_listener_tmp: <span class="built_in">bind</span> <span class="string">&quot;/Users/cat/.ssh/agent/s.xxxx.agent.xxxx&quot;</span>: Permission denied</span><br><span class="line">main: Couldn<span class="string">&#x27;t prepare agent socket</span></span><br><span class="line"><span class="string">exit: 255</span></span><br></pre></td></tr></table></figure><p><strong>真相大白。</strong> 新版 ssh-agent 会在 <code>~/.ssh/agent/</code> 目录下创建 socket,而这个目录的权限坏了,导致 bind 失败,<code>fatal()</code> 退出 255。</p><h2 id="根因-一个缺失的-x-位"><a href="#根因-一个缺失的-x-位" class="headerlink" title="根因:一个缺失的 x 位"></a>根因:一个缺失的 x 位</h2><p>看权限:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">ls</span> -ld ~/.ssh/agent</span><br><span class="line">drw-------@ 3 <span class="built_in">cat</span>  staff  96  4月  4 10:37 /Users/cat/.ssh/agent</span><br></pre></td></tr></table></figure><p>属主没问题,坏在权限位:<code>drw-------</code>——<strong>目录缺了 execute(x)位</strong>。</p><p>对目录而言,<code>x</code> 是”进入&#x2F;穿越”权限。没有它:</p><ul><li>可以 <code>ls</code> 列出文件名(靠 <code>r</code> 位)</li><li>但无法 <code>stat</code> 目录内任何文件</li><li>无法在目录内创建新文件(socket 的 bind 也就必然失败)</li></ul><p>这种坏法的典型成因:某次对 <code>~/.ssh</code> 递归执行了 <code>chmod 600</code>。<code>600</code> 对私钥文件是正确的,但<strong>对目录是致命的</strong>——目录必须有 <code>x</code> 才能正常使用。</p><p>这也完美解释了所有诡异现象:</p><table><thead><tr><th>现象</th><th>解释</th></tr></thead><tbody><tr><td>重启无效</td><td>权限持久化在磁盘上,与进程&#x2F;会话无关</td></tr><tr><td>两个版本的 ssh 客户端都卡</td><td>问题在 agent 端,客户端无辜</td></tr><tr><td>agent 静默死亡</td><td>launchd 丢弃了 stderr,错误信息无处可看</td></tr><tr><td>socket 存在且可连接</td><td>socket 由 launchd 持有,与 agent 是否活着无关</td></tr></tbody></table><h2 id="修复-一条命令"><a href="#修复-一条命令" class="headerlink" title="修复:一条命令"></a>修复:一条命令</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">chmod</span> 700 ~/.ssh/agent</span><br></pre></td></tr></table></figure><p>验证:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ ssh-add -l          <span class="comment"># 立即返回,agent 复活</span></span><br><span class="line">$ ssh-add ~/.ssh/id_rsa ~/.ssh/id_ed25519</span><br><span class="line">$ ssh root@&lt;server&gt;   <span class="comment"># 秒进</span></span><br></pre></td></tr></table></figure><h2 id="经验总结"><a href="#经验总结" class="headerlink" title="经验总结"></a>经验总结</h2><ol><li><p><strong>“卡死”和”报错”是两种线索。</strong> 卡死意味着某一方在无限等待,顺着协议流程找”下一步本应发生什么”,就能定位是在等谁。</p></li><li><p><strong>对照实验是最快的手术刀。</strong> <code>-o IdentityAgent=none</code> 一条命令就把嫌疑范围从”客户端&#x2F;网络&#x2F;服务器&#x2F;agent”缩到只剩 agent。</p></li><li><p><strong>socket 激活服务的报错会被吞掉。</strong> launchd 拉起的进程 stderr 默认丢弃,<code>launchctl print</code> 里的 <code>runs</code> 和 <code>last exit code</code> 是最重要的健康指标;拿不到日志时,手动在终端复现启动是终极手段。</p></li><li><p><strong><code>chmod 600</code> 不要递归用在目录上。</strong> <code>~/.ssh</code> 的标准权限:目录 <code>700</code>,私钥 <code>600</code>,公钥&#x2F;config&#x2F;known_hosts <code>644</code> 或 <code>600</code>。修权限时用 <code>chmod 700 目录</code> + <code>chmod 600 私钥</code> 分开处理,或者:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">find ~/.ssh -<span class="built_in">type</span> d -<span class="built_in">exec</span> <span class="built_in">chmod</span> 700 &#123;&#125; \;</span><br><span class="line">find ~/.ssh -<span class="built_in">type</span> f -name <span class="string">&#x27;id_*&#x27;</span> ! -name <span class="string">&#x27;*.pub&#x27;</span> -<span class="built_in">exec</span> <span class="built_in">chmod</span> 600 &#123;&#125; \;</span><br></pre></td></tr></table></figure></li><li><p><strong>exit code 255 在 OpenSSH 语境里就是 <code>fatal()</code>。</strong> 看到它,去找初始化阶段的失败点(socket、权限、配置解析),而不是运行时逻辑。</p></li></ol><p>一个丢失的 <code>x</code> 位,让 ssh-agent 无声地崩溃了 61 次,拖着两个版本的 ssh 客户端一起陪葬,还扛过了一次重启。定位它花了四层排查,修复它只要九个字符。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;今天回来,要帮同学远程运维一下之前的服务器(他忘记续费了),忽然发现运维脚本执行后没反应(往常1分钟一台跑完的).&lt;/p&gt;</summary>
    
    
    
    
    <category term="SSH" scheme="https://szxiot.com/tags/SSH/"/>
    
    <category term="macOS" scheme="https://szxiot.com/tags/macOS/"/>
    
    <category term="launchd" scheme="https://szxiot.com/tags/launchd/"/>
    
    <category term="故障排查" scheme="https://szxiot.com/tags/%E6%95%85%E9%9A%9C%E6%8E%92%E6%9F%A5/"/>
    
  </entry>
  
  <entry>
    <title>CloudPanBridge — 统一管理 115 网盘与 123 云盘的自动化实践</title>
    <link href="https://szxiot.com/2026/05/23/cloudpan-bridge-intro/"/>
    <id>https://szxiot.com/2026/05/23/cloudpan-bridge-intro/</id>
    <published>2026-05-23T11:00:00.000Z</published>
    <updated>2026-07-07T14:06:47.264Z</updated>
    
    <content type="html"><![CDATA[<p>手上有两个云盘：115 网盘存了大量影视资源，123 云盘有不错的带宽和直链能力。日常需求很简单——<strong>让 媒体库的文件,可以通过 115 和 123 的通道播放和下载</strong>。</p><span id="more"></span><p>很多工具都是之前已经实现的零碎任务,这次结合核心诉求,把下面的问题整合起来：</p><ul><li>两个平台的 API 风格完全不同，一个 OAuth2 PKCE，一个 clientId + clientSecret</li><li>文件需要在两边做匹配，靠的是 SHA1 而不是文件名</li><li>想做增量同步，就得维护一份文件索引</li><li>生成媒体库的 strm 文件，还要写入远程 NAS</li><li>最后需要一个下载服务，能把 123 的直链能力用起来</li></ul><p>一个个手动操作太累了，于是有了 <strong>CloudPanBridge</strong>。</p><!-- more --><h2 id="架构总览"><a href="#架构总览" class="headerlink" title="架构总览"></a>架构总览</h2><p>整个项目分为三层：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">┌─────────────────────────────────────────────┐</span><br><span class="line">│              CLI 命令行工具                    │</span><br><span class="line">│  export  dedup  match  sync  strm  serve     │</span><br><span class="line">├─────────────────────────────────────────────┤</span><br><span class="line">│          CloudPan SDK (统一封装)               │</span><br><span class="line">│    ┌──────────────┐  ┌──────────────┐        │</span><br><span class="line">│    │  115 Client  │  │  123 Client  │        │</span><br><span class="line">│    └──────────────┘  └──────────────┘        │</span><br><span class="line">├─────────────────────────────────────────────┤</span><br><span class="line">│         Database (SQLite / MySQL)            │</span><br><span class="line">│         HTTP Service (FastAPI)               │</span><br><span class="line">└─────────────────────────────────────────────┘</span><br></pre></td></tr></table></figure><p>最底层是 <strong>SDK 层</strong>，分别封装了两个平台的完整开放 API；中间是 <strong>CLI 工具层</strong>，把业务逻辑编排成一个个命令；上层是 <strong>运维层</strong>，靠一个 shell 脚本编排定时任务。</p><p>数据库是整个系统的核心枢纽，所有信息流经它串联——文件索引、云盘匹配关系、同步任务状态，全部落库管理。</p><h2 id="核心工作流"><a href="#核心工作流" class="headerlink" title="核心工作流"></a>核心工作流</h2><p>整个自动化管线按照 1→2→3→4→5 的顺序执行：</p><h3 id="1-文件导出"><a href="#1-文件导出" class="headerlink" title="1. 文件导出"></a>1. 文件导出</h3><p>把云盘上的文件列表完整拉到数据库，这是后续一切操作的基础。</p><p><strong>115 的导出</strong>做了三阶段设计：先分页拉取文件列表（不拉目录信息），再批量调用目录信息 API 构建路径，最后回填数据库。增量模式下，拉到比上次更新时间更旧的文件就自动停止，效率很高。</p><p><strong>123 的导出</strong>用了 UPSERT 批量写入（5000 条一批），支持并发扫描子目录，还有指数退避的限流保护。回收站里的文件自动跳过。</p><blockquote><p>这部分在代码里是最复杂的——要处理分页、限流、断点续传、增量同步、多用户隔离。</p></blockquote><h3 id="2-重复文件检测"><a href="#2-重复文件检测" class="headerlink" title="2. 重复文件检测"></a>2. 重复文件检测</h3><p>同一目录下，通过文件大小 + SHA1（或 MD5、ETag）判断重复。特别针对网盘场景做了 <code>--detect-suffix</code> 支持——匹配文件名末尾的 <code>(1)</code> 或 <code>（1）</code> 这类后缀，配合 <code>--delete</code> 可以安全批量清理。</p><h3 id="3-跨云盘匹配"><a href="#3-跨云盘匹配" class="headerlink" title="3. 跨云盘匹配"></a>3. 跨云盘匹配</h3><p>匹配逻辑没有在 Python 里做循环，而是直接生成 SQL，在数据库服务端完成 JOIN：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> f115.<span class="operator">*</span>, f123.<span class="operator">*</span></span><br><span class="line"><span class="keyword">FROM</span> files f115</span><br><span class="line"><span class="keyword">INNER</span> <span class="keyword">JOIN</span> files f123</span><br><span class="line">    <span class="keyword">ON</span> f123.size <span class="operator">=</span> f115.size</span><br><span class="line">   <span class="keyword">AND</span> SUBSTR(f123.full_path, <span class="keyword">offset</span>) <span class="operator">=</span> SUBSTR(f115.full_path, <span class="keyword">offset</span>)</span><br></pre></td></tr></table></figure><p>匹配结果通过临时表 + 单条 UPDATE 批量写入，100 万级数据分分钟搞定(1C1G的垃圾服务器)。全程数据库服务端计算，Python 只收结果，内存零压力。</p><h3 id="4-生成-strm-文件"><a href="#4-生成-strm-文件" class="headerlink" title="4. 生成 strm 文件"></a>4. 生成 strm 文件</h3><p>为媒体播放器生成 .strm 文件（本质是一个指向 HTTP URL 的文本文件），内容形如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://172.16.16.170:8808/sha1/&#123;sha1&#125;/size/&#123;size&#125;/&#123;encoded_name&#125;</span><br></pre></td></tr></table></figure><p>支持两种模式：本地写入和远程 SFTP 写入。我用的是 <code>--ssh-password</code> 参数直接写入 NAS 上的目录。47 万个文件，8 线程并行写入，大约 8 分钟跑完。</p><h3 id="5-同步与下载服务"><a href="#5-同步与下载服务" class="headerlink" title="5. 同步与下载服务"></a>5. 同步与下载服务</h3><p><strong>同步（115 → 123）</strong> 基于 123 云盘的 SHA1 秒传接口，文件不需要下载再上传，服务端直接复制。大文件优先处理，已匹配的文件自动跳过。并发数通过 <code>-c</code> 参数控制。</p><p><strong>下载服务</strong> 基于 FastAPI + uvicorn 构建，支持两种模式：</p><ul><li><strong>302 重定向模式</strong>：查询直链后 302 跳转，服务端不接触文件数据</li><li><strong>代理缓存模式</strong>（<code>--proxy</code>）：文件边下边转，支持 HTTP Range 断点续传，缓存到本地磁盘</li></ul><p>代理模式做了一些有意思的优化：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 多线程分段下载：123 的文件用 2 个线程同时拉</span></span><br><span class="line"><span class="comment"># os.pwrite 按偏移量原子写入，线程安全</span></span><br><span class="line"><span class="comment"># LRU 缓存按 mtime 淘汰，默认 50GB 上限</span></span><br><span class="line"><span class="comment"># 403 自动重试：自动换 URL 再试</span></span><br><span class="line"><span class="comment"># 多 reader 保护：最后一个消费者断开才清理缓存</span></span><br></pre></td></tr></table></figure><p>最妙的是 SHA1 秒传兜底机制——所有常规下载路径都失败时，自动触发 123 的 SHA1 秒传接口完成兜底，并更新数据库关联供后续复用。</p><h2 id="技术亮点"><a href="#技术亮点" class="headerlink" title="技术亮点"></a>技术亮点</h2><h3 id="双数据库后端的优雅抽象"><a href="#双数据库后端的优雅抽象" class="headerlink" title="双数据库后端的优雅抽象"></a>双数据库后端的优雅抽象</h3><p>项目同时支持 SQLite 和 MySQL，但不是用 ORM，而是自己做了抽象层：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">DatabaseBackend (抽象基类)</span><br><span class="line">├── SQLiteBackend  — UPSERT: ON CONFLICT</span><br><span class="line">└── MySQLBackend   — UPSERT: ON DUPLICATE KEY</span><br></pre></td></tr></table></figure><p>环境变量一键切换：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> CLOUDPAN_DB_TYPE=mysql</span><br><span class="line"><span class="built_in">export</span> CLOUDPAN_DB_HOST=...</span><br></pre></td></tr></table></figure><h3 id="Mark-and-Sweep-增量清理"><a href="#Mark-and-Sweep-增量清理" class="headerlink" title="Mark-and-Sweep 增量清理"></a>Mark-and-Sweep 增量清理</h3><p>每次导出生成唯一的 <code>sync_id</code>，写入每条记录时标记 <code>last_sync_id = sync_id</code>。导出完成后，清理该云盘下 <code>last_sync_id != sync_id</code> 的记录——这就是云盘上已被删除的文件。增量模式下不执行清理，防止误删。</p><h3 id="授权管理"><a href="#授权管理" class="headerlink" title="授权管理"></a>授权管理</h3><p>115 用的是 PKCE 扫码授权（比传统授权码模式更安全），Token 刷新后旧的立即作废。123 则是 clientId + clientSecret 直接获取 access_token，30 天有效期。缓存统一存放在 <code>~/.cloudpan/auth_cache.json</code>。</p><h2 id="生产部署"><a href="#生产部署" class="headerlink" title="生产部署"></a>生产部署</h2><p>日常运维通过一个 shell 脚本编排：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 每 4 小时：导出 → 去重 → 匹配 → 生成 strm</span></span><br><span class="line">0 */4 * * * /path/to/cloudpan-ops.sh every-4h</span><br><span class="line"></span><br><span class="line"><span class="comment"># 每天凌晨 3 点：同步文件</span></span><br><span class="line">0 3 * * * /path/to/cloudpan-ops.sh daily</span><br><span class="line"></span><br><span class="line"><span class="comment"># 下载服务常驻运行</span></span><br><span class="line">./cloudpan-ops.sh serve</span><br></pre></td></tr></table></figure><p>脚本加了日志、PID 管理、命令可用性检测，放在 crontab 里基本不用管。</p><h2 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">CloudPanBridge/</span><br><span class="line">├── src/cloudpan_sdk/</span><br><span class="line">│   ├── base/              # 抽象基类、异常、数据模型</span><br><span class="line">│   ├── platform_115/      # 115 API 实现</span><br><span class="line">│   ├── platform_123/      # 123 API 实现</span><br><span class="line">│   ├── cli/               # CLI 工具和业务逻辑</span><br><span class="line">│   └── server/            # FastAPI 下载服务</span><br><span class="line">└──cloudpan-ops.sh        # 运维编排脚本</span><br></pre></td></tr></table></figure><p><code>platform_115</code> 和 <code>platform_123</code> 是纯粹的 SDK 封装，<code>cli/</code> 目录才是真正的业务逻辑所在。这种分层让 SDK 可以独立复用——即使不用这套自动化管线，单纯想调 115 或 123 的 API，也可以直接 <code>pip install</code> 后 import 使用。</p><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>这个项目不是一个大而全的框架，而是一组解决具体问题的工具集合。每个命令单独拿出来都能用，组合起来就形成了一条完整的自动化管线。</p><p>如果你也有类似的场景——管理多个云盘、做媒体库自动化、或者单纯想研究网盘 API 的封装方式，希望对你有参考价值。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;手上有两个云盘：115 网盘存了大量影视资源，123 云盘有不错的带宽和直链能力。日常需求很简单——&lt;strong&gt;让 媒体库的文件,可以通过 115 和 123 的通道播放和下载&lt;/strong&gt;。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Python" scheme="https://szxiot.com/tags/Python/"/>
    
    <category term="云盘" scheme="https://szxiot.com/tags/%E4%BA%91%E7%9B%98/"/>
    
    <category term="自动化" scheme="https://szxiot.com/tags/%E8%87%AA%E5%8A%A8%E5%8C%96/"/>
    
    <category term="FastAPI" scheme="https://szxiot.com/tags/FastAPI/"/>
    
    <category term="CLI" scheme="https://szxiot.com/tags/CLI/"/>
    
    <category term="开源" scheme="https://szxiot.com/tags/%E5%BC%80%E6%BA%90/"/>
    
  </entry>
  
  <entry>
    <title>性能翻倍：Qwen3-Coder-30B 开启 KV Cache 量化后的终极实测</title>
    <link href="https://szxiot.com/2026/05/10/ollama-qwen3-code-dev-3/"/>
    <id>https://szxiot.com/2026/05/10/ollama-qwen3-code-dev-3/</id>
    <published>2026-05-10T12:00:00.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p>极致优化：如何将 128k 上下文的显存占用从 87GB 降至 66GB？</p><p>在上一篇博文中，我们展示了双 3090&#x2F;四 3090 环境下部署 Qwen3-30B 的基础性能。今天，通过引入 <code>OLLAMA_KV_CACHE_TYPE=q8_0</code>，我们将这项测试推向了新的巅峰：在不损失响应速度的前提下，显存占用降低了 **24%**。</p><span id="more"></span><h2 id="1-核心调优：什么是-KV-Cache-量化？"><a href="#1-核心调优：什么是-KV-Cache-量化？" class="headerlink" title="1. 核心调优：什么是 KV Cache 量化？"></a>1. 核心调优：什么是 KV Cache 量化？</h2><p>大模型在处理长文本时，会把历史对话的 key 和 value 存在显存里（即 KV Cache）。对于 128k 这种超长上下文，这部分内存占用往往比模型本身还要大。<br>通过设置环境变量：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> OLLAMA_KV_CACHE_TYPE=q8_0</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>我们将 KV Cache 从 16 位压缩到 8 位。结果令人震惊。</p><h2 id="2-优化前后数据全量对比"><a href="#2-优化前后数据全量对比" class="headerlink" title="2. 优化前后数据全量对比"></a>2. 优化前后数据全量对比</h2><p>基于 4x 3090 (96GB VRAM) 环境，模型为 <code>Qwen3-Coder-30B-A3B-Instruct-Q8</code>：</p><h3 id="显存占用对照表"><a href="#显存占用对照表" class="headerlink" title="显存占用对照表"></a>显存占用对照表</h3><table><thead><tr><th>Context</th><th>默认 FP16 Cache</th><th><strong>Q8 Cache (优化后)</strong></th><th>节省空间</th></tr></thead><tbody><tr><td>32k</td><td>46 GB</td><td>40 GB</td><td>6 GB</td></tr><tr><td>64k</td><td>59 GB</td><td>48 GB</td><td>11 GB</td></tr><tr><td>128k</td><td>87 GB</td><td><strong>66 GB</strong></td><td><strong>21 GB</strong></td></tr></tbody></table><p><img src="https://123static.szxiot.com/yk6baz03t0l000ddvb7xiirer94lokyiDIYvDwa2DdUvDGxPAIeODF==.png" loading="lazy"></p><h3 id="推理性能对照表-4-并发"><a href="#推理性能对照表-4-并发" class="headerlink" title="推理性能对照表 (4 并发)"></a>推理性能对照表 (4 并发)</h3><table><thead><tr><th>指标</th><th>默认配置</th><th><strong>Q8 Cache (优化后)</strong></th></tr></thead><tbody><tr><td><strong>128k TPS</strong></td><td>112 - 132</td><td><strong>131 - 134</strong> (更稳)</td></tr><tr><td><strong>TTFT (首字延迟)</strong></td><td>0.44s</td><td>0.42s</td></tr></tbody></table><p><img src="https://123static.szxiot.com/yk6baz03t0l000ddvbbpkyxmh94nch6xDIYvDwa2DdUvDGxPAIeODF==.png" loading="lazy"></p><h2 id="3-技术分析：为什么必开-Q8-Cache？"><a href="#3-技术分析：为什么必开-Q8-Cache？" class="headerlink" title="3. 技术分析：为什么必开 Q8 Cache？"></a>3. 技术分析：为什么必开 Q8 Cache？</h2><ol><li><strong>带宽解耦</strong>：在 128k 场景下，计算不再是瓶颈，显存数据的搬运速度才是。Q8 减少了搬运量，让 A3B 推理引擎跑得更欢。</li><li><strong>容错空间</strong>：在 128k 仅需 66GB 的情况下，你的系统不仅能稳定运行 AI 编程插件（Trae&#x2F;Cursor），还能同时开启 4K 显示器渲染、多浏览器窗口，甚至后端本地调试环境，而完全不必担心显存溢出导致的系统卡死。</li></ol><h2 id="4-总结：生产力环境的最佳实践"><a href="#4-总结：生产力环境的最佳实践" class="headerlink" title="4. 总结：生产力环境的最佳实践"></a>4. 总结：生产力环境的最佳实践</h2><p>如果你拥有 48GB 以上的显存，部署 Qwen3-30B 时的<strong>黄金法则</strong>：</p><ul><li><strong>锁死 128k 上下文</strong>：给 AI 最完整的项目记忆。</li><li><strong>强制开启 q8_0 Cache</strong>：用极微小的精度损失换取巨大的显存余量和更稳的 TPS。</li><li><strong>并发数设为 4-8</strong>：充分利用 3090 集群的多卡并行能力。</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;极致优化：如何将 128k 上下文的显存占用从 87GB 降至 66GB？&lt;/p&gt;
&lt;p&gt;在上一篇博文中，我们展示了双 3090&amp;#x2F;四 3090 环境下部署 Qwen3-30B 的基础性能。今天，通过引入 &lt;code&gt;OLLAMA_KV_CACHE_TYPE=q8_0&lt;/code&gt;，我们将这项测试推向了新的巅峰：在不损失响应速度的前提下，显存占用降低了 **24%**。&lt;/p&gt;</summary>
    
    
    
    
    <category term="AI" scheme="https://szxiot.com/tags/AI/"/>
    
    <category term="Ollama" scheme="https://szxiot.com/tags/Ollama/"/>
    
    <category term="Qwen3" scheme="https://szxiot.com/tags/Qwen3/"/>
    
    <category term="3090集群" scheme="https://szxiot.com/tags/3090%E9%9B%86%E7%BE%A4/"/>
    
    <category term="显存优化" scheme="https://szxiot.com/tags/%E6%98%BE%E5%AD%98%E4%BC%98%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>4x 3090 巅峰性能：Qwen3-Coder-30B (MoE) 128k 上下文实测</title>
    <link href="https://szxiot.com/2026/05/10/ollama-qwen3-code-dev-2/"/>
    <id>https://szxiot.com/2026/05/10/ollama-qwen3-code-dev-2/</id>
    <published>2026-05-10T04:00:00.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p>追求极致：当 4 张 3090 遇上 Qwen3 MoE</p><p>在本地部署大模型的道路上，显存容量决定了“深度”，而架构设计决定了“速度”。最近我将本地环境升级到了 4x RTX 3090 (96GB VRAM)，并部署了 <strong>Qwen3-Coder-30B-A3B-Instruct-Q8</strong>。以下是针对 32k 到 128k 上下文的真实性能压测报告。</p><span id="more"></span><h1 id="1-模型架构：A3B-的魔力"><a href="#1-模型架构：A3B-的魔力" class="headerlink" title="1. 模型架构：A3B 的魔力"></a>1. 模型架构：A3B 的魔力</h1><p>Qwen3-Coder-30B 采用了 <strong>Mixture of Experts (MoE)</strong> 架构。虽然它有 30B 的总参数量确保了逻辑深度，但推理时仅激活 <strong>3B</strong> 参数。这使得它在处理大规模代码理解时，响应速度甚至超越了许多 14B 的稠密模型。</p><h1 id="2-内存与性能矩阵"><a href="#2-内存与性能矩阵" class="headerlink" title="2. 内存与性能矩阵"></a>2. 内存与性能矩阵</h1><p>通过（4 并发）实测，数据如下：</p><table><thead><tr><th align="left">上下文长度</th><th align="left">显存占用</th><th align="left">峰值 Total TPS</th><th align="left">首字延迟 (Hot)</th><th align="left">生产力评价</th></tr></thead><tbody><tr><td align="left"><strong>32k</strong></td><td align="left">46 GB</td><td align="left">141.91 tokens&#x2F;s</td><td align="left">0.38s</td><td align="left">极速补全，几乎瞬发</td></tr><tr><td align="left"><strong>64k</strong></td><td align="left">59 GB</td><td align="left">133.27 tokens&#x2F;s</td><td align="left">0.41s</td><td align="left">平衡点，适合中型项目</td></tr><tr><td align="left"><strong>128k</strong></td><td align="left"><strong>87 GB</strong></td><td align="left"><strong>132.59 tokens&#x2F;s</strong></td><td align="left">0.46s</td><td align="left"><strong>究极体</strong>：Repo-level 级理解</td></tr></tbody></table><p><img src="https://123static.szxiot.com/yk6baz03t0m000ddvb9t2zoqfr4mg69pDIYvDwa2DdUvDGxPAIeODF==.png" loading="lazy"></p><p><img src="https://123static.szxiot.com/ymjew503t0n000ddulyefdvtdjzba808DIYvDwa2DdUvDGxPAIeODF==.png" loading="lazy"></p><h1 id="3-关键洞察：128k-为什么不掉速？"><a href="#3-关键洞察：128k-为什么不掉速？" class="headerlink" title="3. 关键洞察：128k 为什么不掉速？"></a>3. 关键洞察：128k 为什么不掉速？</h1><p>传统的 Dense（稠密）模型在上下文增加时，计算压力会显著增大。但在本次 128k 压测中，TPS 仅从 141 跌落至 132，损耗极小。</p><ol><li><strong>显存完全覆盖</strong>：87GB 的占用完美落在 96GB 的物理上限内，避免了任何系统交换（Swap）导致的卡顿。</li><li><strong>KV Cache 效率</strong>：Q8 量化下的 KV Cache 虽然巨大（约 56GB），但由于 4 卡并行带宽极高，注意力机制的计算开销被有效摊平。</li><li><strong>冷启动 vs 热启动</strong>：实测显示冷启动（加载模型）需要约 45 秒，但一旦热身完成，TTFT 稳定在 <strong>0.4s</strong> 级别。</li></ol><h1 id="4-最终配置建议-4x-3090-用户"><a href="#4-最终配置建议-4x-3090-用户" class="headerlink" title="4. 最终配置建议 (4x 3090 用户)"></a>4. 最终配置建议 (4x 3090 用户)</h1><p>如果你的显存超过 80GB，不要犹豫，直接锁死 <strong>128k</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 环境变量</span></span><br><span class="line"><span class="built_in">export</span> OLLAMA_NUM_PARALLEL=4</span><br><span class="line"><span class="built_in">export</span> OLLAMA_FLASH_ATTENTION=1</span><br><span class="line"></span><br><span class="line"><span class="comment"># Modelfile 核心参数</span></span><br><span class="line">PARAMETER num_ctx 131072</span><br><span class="line">PARAMETER temperature 0.1</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>128k 带来的“长效记忆”是编程 AI 的终极杀手锏。在本地算力的支撑下，我们终于告别了云端模型的 Token 焦虑。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;追求极致：当 4 张 3090 遇上 Qwen3 MoE&lt;/p&gt;
&lt;p&gt;在本地部署大模型的道路上，显存容量决定了“深度”，而架构设计决定了“速度”。最近我将本地环境升级到了 4x RTX 3090 (96GB VRAM)，并部署了 &lt;strong&gt;Qwen3-Coder-30B-A3B-Instruct-Q8&lt;/strong&gt;。以下是针对 32k 到 128k 上下文的真实性能压测报告。&lt;/p&gt;</summary>
    
    
    
    
    <category term="LLM" scheme="https://szxiot.com/tags/LLM/"/>
    
    <category term="Qwen3" scheme="https://szxiot.com/tags/Qwen3/"/>
    
    <category term="Trae" scheme="https://szxiot.com/tags/Trae/"/>
    
    <category term="3090集群" scheme="https://szxiot.com/tags/3090%E9%9B%86%E7%BE%A4/"/>
    
    <category term="MoE" scheme="https://szxiot.com/tags/MoE/"/>
    
  </entry>
  
  <entry>
    <title>极致丝滑：双 3090 部署 Qwen3-Coder-30B 开发全记录</title>
    <link href="https://szxiot.com/2026/05/09/ollama-qwen3-code-dev-1/"/>
    <id>https://szxiot.com/2026/05/09/ollama-qwen3-code-dev-1/</id>
    <published>2026-05-09T13:30:00.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p>在 AI 编程工具（如 Trae, Cursor）百家争鸣的时代，拥有一套高性能的本地大模型环境，不仅能保护代码私密性，更能通过极低的延迟提升“人机合一”的快感。本文记录了在 NVIDIA RTX 3090（多卡）环境下，利用 Ollama 部署 Qwen3-Coder-30B (MoE) 并进行深度调优的全过程。</p><span id="more"></span><h1 id="1-硬件与模型选型：为什么是-Qwen3-30B？"><a href="#1-硬件与模型选型：为什么是-Qwen3-30B？" class="headerlink" title="1. 硬件与模型选型：为什么是 Qwen3-30B？"></a>1. 硬件与模型选型：为什么是 Qwen3-30B？</h1><p>对于有充足显存的配置，<strong>Qwen3-Coder-30B</strong> 是目前相对较优的“版本答案”：</p><ul><li><strong>MoE 架构</strong>：总参数 30B，推理时仅激活约 3.3B。这意味着它拥有大模型的“深度”，却具备小模型的“速度”。</li><li><strong>长上下文支持</strong>：原生支持 128k 上下文，适合 Repo-level 的代码理解。</li></ul><h1 id="2-核心部署配置"><a href="#2-核心部署配置" class="headerlink" title="2. 核心部署配置"></a>2. 核心部署配置</h1><h3 id="2-1-环境变量调优-Server-Side"><a href="#2-1-环境变量调优-Server-Side" class="headerlink" title="2.1 环境变量调优 (Server-Side)"></a>2.1 环境变量调优 (Server-Side)</h3><p>为了压榨并发性能，我们在启动 Ollama 前设置了如下关键参数：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启用 Flash Attention 减少长文本压力</span></span><br><span class="line"><span class="built_in">export</span> OLLAMA_FLASH_ATTENTION=1</span><br><span class="line"><span class="comment"># 模型驻留显存，消除冷启动等待</span></span><br><span class="line"><span class="built_in">export</span> OLLAMA_KEEP_ALIVE=12h</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="2-2-自定义-Modelfile"><a href="#2-2-自定义-Modelfile" class="headerlink" title="2.2 自定义 Modelfile"></a>2.2 自定义 Modelfile</h3><p>我们创建了 <code>my-code-qwen3</code> 模型，固定了黄金生产力参数：</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> qwen3-coder:<span class="number">30</span>b-instruct-q8_0</span><br><span class="line">PARAMETER num_ctx <span class="number">65536</span></span><br><span class="line">PARAMETER temperature <span class="number">0.1</span></span><br><span class="line">PARAMETER repeat_penalty <span class="number">1.15</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="3-性能压测实录-Benchmark"><a href="#3-性能压测实录-Benchmark" class="headerlink" title="3. 性能压测实录 (Benchmark)"></a>3. 性能压测实录 (Benchmark)</h1><p>在并发数 $N&#x3D;4$ 的高频压力测试下，不同上下文长度的表现如下：</p><table><thead><tr><th>配置 (Context)</th><th>首字延迟 (TTFT)</th><th>总吞吐量 (Total TPS)</th><th>人均生成速度</th><th>结论</th></tr></thead><tbody><tr><td><strong>32k</strong></td><td>0.39s</td><td>121.22 tokens&#x2F;s</td><td>30.3 tokens&#x2F;s</td><td>极速响应，无感延迟</td></tr><tr><td><strong>64k</strong></td><td>0.40s</td><td><strong>124.24 tokens&#x2F;s</strong></td><td><strong>31.0 tokens&#x2F;s</strong></td><td><strong>黄金平衡点</strong></td></tr><tr><td><strong>128k</strong></td><td>0.44s</td><td>112.13 tokens&#x2F;s</td><td>28.0 tokens&#x2F;s</td><td>略有衰减但依然流畅</td></tr></tbody></table><h3 id="数据解读："><a href="#数据解读：" class="headerlink" title="数据解读："></a>数据解读：</h3><ul><li><strong>0.4s 的 TTFT</strong>：意味着在你按下快捷键的瞬间，代码已经开始流式输出。</li><li><strong>120+ TPS 的总输出</strong>：证明了 MoE 架构在 3090 上的巨大带宽优势，足以支撑多人或多任务同时运行。</li><li><strong>64k 甜点位</strong>：测试显示 64k 下性能不降反升，说明该尺寸最契合目前的算力调度。</li></ul><h1 id="4-总结"><a href="#4-总结" class="headerlink" title="4. 总结"></a>4. 总结</h1><p>双 3090 配合 Qwen3-Coder-30B MoE 模型，为单人开发者提供了一个“低延迟、高智力、大容量”的完美私有大脑。</p><ul><li><strong>如果你追求极致速度</strong>：32k 上下文 + Q4 量化。</li><li><strong>如果你追求生产力平衡</strong>：64k 上下文 + Q8 量化（推荐）。</li><li><strong>如果你需要处理庞大工程</strong>：128k 上下文 + KV Cache 量化。</li></ul><p><strong>写在最后</strong>：本地 AI 的魅力在于，它不只是一件工具，更是你算力的延伸。如果你需要大量的token消耗,除了大厂的Coding Plan,本地也许是个不错的选择。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;在 AI 编程工具（如 Trae, Cursor）百家争鸣的时代，拥有一套高性能的本地大模型环境，不仅能保护代码私密性，更能通过极低的延迟提升“人机合一”的快感。本文记录了在 NVIDIA RTX 3090（多卡）环境下，利用 Ollama 部署 Qwen3-Coder-30B (MoE) 并进行深度调优的全过程。&lt;/p&gt;</summary>
    
    
    
    
    <category term="AI" scheme="https://szxiot.com/tags/AI/"/>
    
    <category term="LLM" scheme="https://szxiot.com/tags/LLM/"/>
    
    <category term="Ollama" scheme="https://szxiot.com/tags/Ollama/"/>
    
    <category term="Qwen3" scheme="https://szxiot.com/tags/Qwen3/"/>
    
    <category term="Trae" scheme="https://szxiot.com/tags/Trae/"/>
    
    <category term="生产力" scheme="https://szxiot.com/tags/%E7%94%9F%E4%BA%A7%E5%8A%9B/"/>
    
  </entry>
  
  <entry>
    <title>跨越边界：从常规服务器到 K8s 容器的 WireGuard 部署全攻略</title>
    <link href="https://szxiot.com/2026/05/06/crossing-boundaries-deploying-wireguard-across-servers-and-k8s/"/>
    <id>https://szxiot.com/2026/05/06/crossing-boundaries-deploying-wireguard-across-servers-and-k8s/</id>
    <published>2026-05-06T10:00:00.000Z</published>
    <updated>2026-07-07T14:06:47.264Z</updated>
    
    <content type="html"><![CDATA[<p>在现代网络架构中，WireGuard 凭借其极简的代码实现和现代加密算法，已成为高效组建虚拟局域网（VLAN）的首选方案。但在实际部署中，无论是跨境链路的 MTU 陷阱，还是 K8s 容器环境下缺失 <code>systemd</code> 与 <code>resolvconf</code> 的限制，都让初学者颇为头疼。</p><span id="more"></span><p>本文结合实战经验，深度分析三类核心部署脚本的设计逻辑，助你构建稳健的私有网络。</p><h2 id="一、-服务端：自动化网关的基石"><a href="#一、-服务端：自动化网关的基石" class="headerlink" title="一、 服务端：自动化网关的基石"></a>一、 服务端：自动化网关的基石</h2><p>服务端的职责不仅仅是握手，更重要的是充当流量转发的中转站。</p><h3 id="1-核心自动化逻辑"><a href="#1-核心自动化逻辑" class="headerlink" title="1. 核心自动化逻辑"></a>1. 核心自动化逻辑</h3><ul><li><strong>网络环境初始化</strong>：自动开启内核级别的 <code>net.ipv4.ip_forward</code> 转发功能，确保虚拟网卡与物理网卡之间流量互通。</li><li><strong>动态流量伪装</strong>：通过 <code>iptables</code> 自动配置 <code>MASQUERADE</code> 规则。脚本能智能识别宿主机的物理网卡名称，实现 NAT 转发，让客户端能够通过服务器访问公网。</li><li><strong>热加载节点管理</strong>：引入 <code>wg syncconf</code> 机制，在添加新 Peer（客户端）时，无需重启整个服务即可实时生效，保证了已有连接的稳定性。</li></ul><p><code>wg_install.sh</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ====================================================</span></span><br><span class="line"><span class="comment"># 服务端固定配置</span></span><br><span class="line"><span class="comment"># ====================================================</span></span><br><span class="line">SERVER_PRIV=<span class="string">&quot;your private key&quot;</span></span><br><span class="line">SERVER_PUB=<span class="string">&quot;your public key&quot;</span></span><br><span class="line">SERVER_PORT=15321</span><br><span class="line">SERVER_IP_RANGE=<span class="string">&quot;10.10.10.1/24&quot;</span></span><br><span class="line">INTERFACE=<span class="string">&quot;wg0&quot;</span></span><br><span class="line">CONF_PATH=<span class="string">&quot;/etc/wireguard/<span class="variable">$&#123;INTERFACE&#125;</span>.conf&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">show_help</span></span>() &#123;</span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;用法: sudo <span class="variable">$0</span> [选项]&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;选项:&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;  gen                             生成一组全新的客户端密钥对&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;  add [名称] [公钥] [IP/32]       添加一个新的客户端 (例如: add Phone xxxx 10.10.10.5/32)&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;  --help, -h                      显示此帮助信息&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;示例:&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;  首次安装: sudo <span class="variable">$0</span>&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;  增加设备: sudo <span class="variable">$0</span> add Node_A xxxxxxxx 10.10.10.3/32&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 处理指令</span></span><br><span class="line"><span class="keyword">case</span> <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="keyword">in</span></span><br><span class="line">    gen)</span><br><span class="line">        <span class="built_in">command</span> -v wg &gt;/dev/null 2&gt;&amp;1 || sudo apt update &amp;&amp; sudo apt install wireguard -y</span><br><span class="line">        _tmp_priv=$(wg genkey)</span><br><span class="line">        _tmp_pub=$(<span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$_tmp_priv</span>&quot;</span> | wg pubkey)</span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;PRIVATE_KEY: <span class="variable">$_tmp_priv</span>&quot;</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;PUBLIC_KEY:  <span class="variable">$_tmp_pub</span>&quot;</span></span><br><span class="line">        <span class="built_in">exit</span> 0</span><br><span class="line">        ;;</span><br><span class="line">    add)</span><br><span class="line">        <span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$3</span>&quot;</span> ] || [ -z <span class="string">&quot;<span class="variable">$4</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">            <span class="built_in">echo</span> <span class="string">&quot;错误: add 指令需要 [名称] [公钥] [IP] 三个参数。&quot;</span></span><br><span class="line">            <span class="built_in">exit</span> 1</span><br><span class="line">        <span class="keyword">fi</span></span><br><span class="line">        CLIENT_NAME=<span class="string">&quot;<span class="variable">$2</span>&quot;</span></span><br><span class="line">        CLIENT_PUB=<span class="string">&quot;<span class="variable">$3</span>&quot;</span></span><br><span class="line">        CLIENT_IP=<span class="string">&quot;<span class="variable">$4</span>&quot;</span></span><br><span class="line">        ;;</span><br><span class="line">    --<span class="built_in">help</span>|-h)</span><br><span class="line">        show_help</span><br><span class="line">        <span class="built_in">exit</span> 0</span><br><span class="line">        ;;</span><br><span class="line">    <span class="string">&quot;&quot;</span>)</span><br><span class="line">        <span class="comment"># 默认模式：初始化或显示当前状态</span></span><br><span class="line">        ;;</span><br><span class="line">    *)</span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;未知指令: <span class="variable">$1</span>&quot;</span></span><br><span class="line">        show_help</span><br><span class="line">        <span class="built_in">exit</span> 1</span><br><span class="line">        ;;</span><br><span class="line"><span class="keyword">esac</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行逻辑</span></span><br><span class="line"><span class="built_in">command</span> -v wg &gt;/dev/null 2&gt;&amp;1 || sudo apt update &amp;&amp; sudo apt install wireguard iptables -y</span><br><span class="line">sudo sysctl -w net.ipv4.ip_forward=1</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;net.ipv4.ip_forward=1&quot;</span> | sudo <span class="built_in">tee</span> /etc/sysctl.d/99-wireguard.conf &gt; /dev/null</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ ! -f <span class="string">&quot;<span class="variable">$CONF_PATH</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    ETH_NAME=$(ip route | grep default | awk <span class="string">&#x27;&#123;print $5&#125;&#x27;</span> | <span class="built_in">head</span> -n1)</span><br><span class="line">    <span class="built_in">cat</span> &lt;&lt;<span class="string">EOF | sudo tee $CONF_PATH</span></span><br><span class="line"><span class="string">[Interface]</span></span><br><span class="line"><span class="string">PrivateKey = $&#123;SERVER_PRIV&#125;</span></span><br><span class="line"><span class="string">Address = $&#123;SERVER_IP_RANGE&#125;</span></span><br><span class="line"><span class="string">ListenPort = $&#123;SERVER_PORT&#125;</span></span><br><span class="line"><span class="string">PostUp = iptables -A FORWARD -i $&#123;INTERFACE&#125; -j ACCEPT; iptables -t nat -A POSTROUTING -o $&#123;ETH_NAME&#125; -j MASQUERADE</span></span><br><span class="line"><span class="string">PostDown = iptables -D FORWARD -i $&#123;INTERFACE&#125; -j ACCEPT; iptables -t nat -D POSTROUTING -o $&#123;ETH_NAME&#125; -j MASQUERADE</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ -n <span class="string">&quot;<span class="variable">$CLIENT_PUB</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="keyword">if</span> grep -q <span class="string">&quot;<span class="variable">$CLIENT_PUB</span>&quot;</span> <span class="string">&quot;<span class="variable">$CONF_PATH</span>&quot;</span>; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;提示: 公钥 <span class="variable">$CLIENT_PUB</span> 已存在。&quot;</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;正在追加 Peer: <span class="variable">$CLIENT_NAME</span> (<span class="variable">$CLIENT_IP</span>)&quot;</span></span><br><span class="line">        <span class="built_in">cat</span> &lt;&lt;<span class="string">EOF | sudo tee -a $CONF_PATH</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"># $CLIENT_NAME</span></span><br><span class="line"><span class="string">[Peer]</span></span><br><span class="line"><span class="string">PublicKey = $&#123;CLIENT_PUB&#125;</span></span><br><span class="line"><span class="string">AllowedIPs = $&#123;CLIENT_IP&#125;</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">sudo systemctl <span class="built_in">enable</span> wg-quick@<span class="variable">$&#123;INTERFACE&#125;</span></span><br><span class="line"><span class="keyword">if</span> sudo systemctl is-active --quiet wg-quick@<span class="variable">$&#123;INTERFACE&#125;</span>; <span class="keyword">then</span></span><br><span class="line">    sudo wg syncconf <span class="variable">$&#123;INTERFACE&#125;</span> &lt;(sudo wg-quick strip <span class="variable">$&#123;INTERFACE&#125;</span>)</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    sudo systemctl start wg-quick@<span class="variable">$&#123;INTERFACE&#125;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;--- 当前 WireGuard 状态 ---&quot;</span></span><br><span class="line">sudo wg show</span><br></pre></td></tr></table></figure><hr><h2 id="二、-常规客户端：交互式简化与自启动"><a href="#二、-常规客户端：交互式简化与自启动" class="headerlink" title="二、 常规客户端：交互式简化与自启动"></a>二、 常规客户端：交互式简化与自启动</h2><p>对于标准的 Linux 服务器或虚拟机，部署的重点在于快速入网与开机持久化。</p><h3 id="1-部署亮点"><a href="#1-部署亮点" class="headerlink" title="1. 部署亮点"></a>1. 部署亮点</h3><ul><li><strong>交互式配置</strong>：通过命令行交互自动获取服务端 IP 与端口，避免手动编辑配置文件的低效。</li><li><strong>MTU 优化策略</strong>：针对跨运营商或跨境链路，脚本默认将 MTU 设定为 <code>1280</code>，有效避免了大包在复杂网络节点中被静默丢弃的问题。</li><li><strong>Systemd 托管</strong>：通过 <code>systemctl enable</code> 实现服务级别的自启动，确保设备重启后隧道能够自动重连。</li></ul><p><code>wg_install_client.sh</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ====================================================</span></span><br><span class="line"><span class="comment"># WireGuard 客户端优化脚本</span></span><br><span class="line"><span class="comment"># 功能：自动安装依赖、密钥管理、配置校验、服务自启</span></span><br><span class="line"><span class="comment"># ====================================================</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 基础配置</span></span><br><span class="line">CLIENT_WG_IP=<span class="string">&quot;10.10.10.4/24&quot;</span></span><br><span class="line">ALLOWED_IPS=<span class="string">&quot;10.10.10.0/24&quot;</span></span><br><span class="line">SERVER_PUB=<span class="string">&quot;dHJLSDvhCkYlDvj/3ic3thYV9rxJfda10SphYZXEcQk=&quot;</span></span><br><span class="line">INTERFACE=<span class="string">&quot;wg0&quot;</span></span><br><span class="line">CONF_PATH=<span class="string">&quot;/etc/wireguard/<span class="variable">$&#123;INTERFACE&#125;</span>.conf&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查 root 权限</span></span><br><span class="line">[[ <span class="variable">$EUID</span> -ne 0 ]] &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;错误: 请使用 sudo 运行&quot;</span> &amp;&amp; <span class="built_in">exit</span> 1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 自动安装 WireGuard 相关工具</span></span><br><span class="line"><span class="function"><span class="title">install_wg</span></span>() &#123;</span><br><span class="line">    <span class="keyword">if</span> ! <span class="built_in">command</span> -v wg &amp;&gt; /dev/null; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;正在安装 wireguard-tools...&quot;</span></span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">command</span> -v apt-get &amp;&gt; /dev/null; <span class="keyword">then</span></span><br><span class="line">            apt-get update &amp;&amp; apt-get install -y wireguard resolvconf</span><br><span class="line">        <span class="keyword">elif</span> <span class="built_in">command</span> -v yum &amp;&gt; /dev/null; <span class="keyword">then</span></span><br><span class="line">            yum install -y epel-release &amp;&amp; yum install -y wireguard-tools</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            <span class="built_in">echo</span> <span class="string">&quot;错误: 无法识别的包管理器，请手动安装 wireguard-tools&quot;</span></span><br><span class="line">            <span class="built_in">exit</span> 1</span><br><span class="line">        <span class="keyword">fi</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 交互式输入 (增加验证)</span></span><br><span class="line"><span class="function"><span class="title">get_server_info</span></span>() &#123;</span><br><span class="line">    <span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$SERVER_IP</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">read</span> -p <span class="string">&quot;请输入海外服务器公网 IP: &quot;</span> SERVER_IP</span><br><span class="line">        <span class="keyword">while</span> [[ ! <span class="variable">$SERVER_IP</span> =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; <span class="keyword">do</span></span><br><span class="line">            <span class="built_in">read</span> -p <span class="string">&quot;IP 格式错误，请重新输入: &quot;</span> SERVER_IP</span><br><span class="line">        <span class="keyword">done</span></span><br><span class="line">        </span><br><span class="line">        <span class="built_in">read</span> -p <span class="string">&quot;请输入端口 [15321]: &quot;</span> SERVER_PORT</span><br><span class="line">        SERVER_PORT=<span class="variable">$&#123;SERVER_PORT:-15321&#125;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 密钥管理逻辑 (优化提取逻辑)</span></span><br><span class="line"><span class="function"><span class="title">manage_keys</span></span>() &#123;</span><br><span class="line">    <span class="built_in">mkdir</span> -p /etc/wireguard/</span><br><span class="line">    <span class="built_in">chmod</span> 700 /etc/wireguard/</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> [ -f <span class="string">&quot;<span class="variable">$CONF_PATH</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">        CLIENT_PRIV=$(grep <span class="string">&quot;PrivateKey&quot;</span> <span class="string">&quot;<span class="variable">$CONF_PATH</span>&quot;</span> | sed <span class="string">&#x27;s/ //g&#x27;</span> | <span class="built_in">cut</span> -d<span class="string">&#x27;=&#x27;</span> -f2)</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$CLIENT_PRIV</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">        CLIENT_PRIV=$(wg genkey)</span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;生成新私钥并已存入配置文件。&quot;</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;对应的公钥为: <span class="subst">$(echo <span class="string">&quot;<span class="variable">$CLIENT_PRIV</span>&quot;</span> | wg pubkey)</span>&quot;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 执行安装与配置</span></span><br><span class="line">install_wg</span><br><span class="line">get_server_info</span><br><span class="line">manage_keys</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 写入配置</span></span><br><span class="line"><span class="built_in">cat</span> &lt;&lt;<span class="string">EOF &gt; &quot;$CONF_PATH&quot;</span></span><br><span class="line"><span class="string">[Interface]</span></span><br><span class="line"><span class="string">PrivateKey = $&#123;CLIENT_PRIV&#125;</span></span><br><span class="line"><span class="string">Address = $&#123;CLIENT_WG_IP&#125;</span></span><br><span class="line"><span class="string">MTU = 1280</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[Peer]</span></span><br><span class="line"><span class="string">PublicKey = $&#123;SERVER_PUB&#125;</span></span><br><span class="line"><span class="string">Endpoint = $&#123;SERVER_IP&#125;:$&#123;SERVER_PORT&#125;</span></span><br><span class="line"><span class="string">AllowedIPs = $&#123;ALLOWED_IPS&#125;</span></span><br><span class="line"><span class="string">PersistentKeepalive = 25</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">chmod</span> 600 <span class="string">&quot;<span class="variable">$CONF_PATH</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 启动与验证</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;正在重启 WireGuard 接口: <span class="variable">$&#123;INTERFACE&#125;</span>...&quot;</span></span><br><span class="line">systemctl stop wg-quick@<span class="variable">$&#123;INTERFACE&#125;</span> &gt;/dev/null 2&gt;&amp;1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启用并启动服务</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line">systemctl <span class="built_in">enable</span> wg-quick@<span class="variable">$&#123;INTERFACE&#125;</span> &gt;/dev/null 2&gt;&amp;1</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> systemctl restart wg-quick@<span class="variable">$&#123;INTERFACE&#125;</span>; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;====================================================&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;状态: 启动成功！&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;模式: 安全分流 (仅处理 <span class="variable">$&#123;ALLOWED_IPS&#125;</span>)&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;测试: ping -c 3 10.10.10.1&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;====================================================&quot;</span></span><br><span class="line">    wg show <span class="string">&quot;<span class="variable">$&#123;INTERFACE&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;启动失败，请检查日志: journalctl -xeu wg-quick@<span class="variable">$&#123;INTERFACE&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br></pre></td></tr></table></figure><hr><h2 id="三、-K8s-x2F-PM2-深度优化版：攻克容器环境"><a href="#三、-K8s-x2F-PM2-深度优化版：攻克容器环境" class="headerlink" title="三、 K8s&#x2F;PM2 深度优化版：攻克容器环境"></a>三、 K8s&#x2F;PM2 深度优化版：攻克容器环境</h2><p>这是最具挑战性的场景。在 K8s 容器或精简版镜像中，由于缺乏 <code>systemd</code> 守护进程且 <code>/etc/resolv.conf</code> 受到系统严格锁定，传统脚本往往会失效。</p><h3 id="1-探索与突破点分析"><a href="#1-探索与突破点分析" class="headerlink" title="1. 探索与突破点分析"></a>1. 探索与突破点分析</h3><ul><li><strong>剔除 <code>resolvconf</code> 依赖</strong>：在容器中，<code>/etc/resolv.conf</code> 通常是挂载的只读文件。脚本显式移除了对 <code>resolvconf</code> 的依赖，解决了因文件锁定导致的安装失败问题。</li><li><strong>PM2 进程托管</strong>：在没有 <code>systemd</code> 的环境下，利用 PM2 接管隧道。通过一个“包装脚本”执行 <code>wg-quick up</code> 后进入 <code>sleep infinity</code> 状态，欺骗 PM2 维持进程常驻。</li><li><strong>生命周期管理</strong>：利用 Shell 的 <code>trap</code> 机制捕获 <code>SIGTERM</code> 和 <code>SIGINT</code> 信号。当执行 <code>pm2 stop</code> 时，脚本能自动触发 <code>wg-quick down</code> 清理网卡，防止网卡名称冲突。</li><li><strong>环境变量补全</strong>：在容器内，PM2 的运行路径可能不包含 <code>/sbin</code>。脚本通过显式导出 <code>PATH</code>，确保了 <code>ip</code> 和 <code>wg</code> 等核心命令能被正确调用。</li></ul><p><code>wg_install_pm2.sh</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ====================================================</span></span><br><span class="line"><span class="comment"># WireGuard 客户端 (PM2 适配版 - K8s 深度优化)</span></span><br><span class="line"><span class="comment"># 修复：移除 resolvconf 依赖，解决 /etc/resolv.conf 被锁定问题</span></span><br><span class="line"><span class="comment"># ====================================================</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 基础配置</span></span><br><span class="line">CLIENT_WG_IP=<span class="string">&quot;10.10.10.3/24&quot;</span></span><br><span class="line">ALLOWED_IPS=<span class="string">&quot;10.10.10.0/24&quot;</span></span><br><span class="line">SERVER_PUB=<span class="string">&quot;dHJLSDvhCkYlDvj/3ic3thYV9rxJfda10SphYZXEcQk=&quot;</span></span><br><span class="line">INTERFACE=<span class="string">&quot;wg0&quot;</span></span><br><span class="line">CONF_PATH=<span class="string">&quot;/etc/wireguard/<span class="variable">$&#123;INTERFACE&#125;</span>.conf&quot;</span></span><br><span class="line">WRAPPER_PATH=<span class="string">&quot;/etc/wireguard/wg_pm2_run.sh&quot;</span></span><br><span class="line"></span><br><span class="line">[[ <span class="variable">$EUID</span> -ne 0 ]] &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;错误: 请使用 sudo 运行&quot;</span> &amp;&amp; <span class="built_in">exit</span> 1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 强力安装依赖 (剔除 resolvconf)</span></span><br><span class="line"><span class="function"><span class="title">install_deps</span></span>() &#123;</span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;正在清理受损的 resolvconf (如果存在)...&quot;</span></span><br><span class="line">    apt-get purge -y resolvconf &amp;&gt; /dev/null</span><br><span class="line">    </span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;正在同步并安装网络工具包 (iproute2, wireguard-tools)...&quot;</span></span><br><span class="line">    apt-get update &amp;&amp; apt-get install -y iproute2 wireguard-tools</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> ! <span class="built_in">command</span> -v ip &amp;&gt; /dev/null; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;错误: ip 命令安装失败，请检查系统源！&quot;</span></span><br><span class="line">        <span class="built_in">exit</span> 1</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 密钥管理 (修复等号截断)</span></span><br><span class="line"><span class="function"><span class="title">manage_keys</span></span>() &#123;</span><br><span class="line">    <span class="built_in">mkdir</span> -p /etc/wireguard/</span><br><span class="line">    <span class="built_in">chmod</span> 700 /etc/wireguard/</span><br><span class="line">    <span class="keyword">if</span> [ -f <span class="string">&quot;<span class="variable">$CONF_PATH</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">        CLIENT_PRIV=$(grep <span class="string">&quot;PrivateKey&quot;</span> <span class="string">&quot;<span class="variable">$CONF_PATH</span>&quot;</span> | sed <span class="string">&#x27;s/ //g&#x27;</span> | <span class="built_in">cut</span> -d<span class="string">&#x27;=&#x27;</span> -f2-)</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">    <span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$CLIENT_PRIV</span>&quot;</span> ] || [ <span class="variable">$&#123;#CLIENT_PRIV&#125;</span> -lt 43 ]; <span class="keyword">then</span></span><br><span class="line">        CLIENT_PRIV=$(wg genkey)</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">    CLIENT_PUB=$(<span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$CLIENT_PRIV</span>&quot;</span> | wg pubkey)</span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;====================================================&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;客户端公钥: <span class="variable">$CLIENT_PUB</span>&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;====================================================&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 获取服务端信息</span></span><br><span class="line"><span class="function"><span class="title">get_server_info</span></span>() &#123;</span><br><span class="line">    <span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$SERVER_IP</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">read</span> -p <span class="string">&quot;请输入海外服务器公网 IP: &quot;</span> SERVER_IP</span><br><span class="line">        <span class="built_in">read</span> -p <span class="string">&quot;请输入端口 [15321]: &quot;</span> SERVER_PORT</span><br><span class="line">        SERVER_PORT=<span class="variable">$&#123;SERVER_PORT:-15321&#125;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">install_deps</span><br><span class="line">get_server_info</span><br><span class="line">manage_keys</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 写入配置 (显式去掉 DNS 选项防止调用 resolvconf)</span></span><br><span class="line"><span class="built_in">cat</span> &lt;&lt;<span class="string">EOF &gt; &quot;$CONF_PATH&quot;</span></span><br><span class="line"><span class="string">[Interface]</span></span><br><span class="line"><span class="string">PrivateKey = $&#123;CLIENT_PRIV&#125;</span></span><br><span class="line"><span class="string">Address = $&#123;CLIENT_WG_IP&#125;</span></span><br><span class="line"><span class="string">MTU = 1380</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[Peer]</span></span><br><span class="line"><span class="string">PublicKey = $&#123;SERVER_PUB&#125;</span></span><br><span class="line"><span class="string">Endpoint = $&#123;SERVER_IP&#125;:$&#123;SERVER_PORT&#125;</span></span><br><span class="line"><span class="string">AllowedIPs = $&#123;ALLOWED_IPS&#125;</span></span><br><span class="line"><span class="string">PersistentKeepalive = 25</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"><span class="built_in">chmod</span> 600 <span class="string">&quot;<span class="variable">$CONF_PATH</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. PM2 包装脚本 (显式补全环境变量)</span></span><br><span class="line"><span class="built_in">cat</span> &lt;&lt;<span class="string">EOF &gt; &quot;$WRAPPER_PATH&quot;</span></span><br><span class="line"><span class="string">#!/bin/bash</span></span><br><span class="line"><span class="string"># 确保 PM2 环境能找到 sbin 下的 ip 命令</span></span><br><span class="line"><span class="string">export PATH=\$PATH:/sbin:/usr/sbin:/usr/local/sbin</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">function cleanup &#123;</span></span><br><span class="line"><span class="string">    echo &quot;正在关闭隧道...&quot;</span></span><br><span class="line"><span class="string">    wg-quick down $&#123;INTERFACE&#125;</span></span><br><span class="line"><span class="string">    exit</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">trap cleanup SIGTERM SIGINT</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">echo &quot;正在启动 WireGuard 隧道...&quot;</span></span><br><span class="line"><span class="string">wg-quick up $&#123;INTERFACE&#125;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">echo &quot;隧道运行中...&quot;</span></span><br><span class="line"><span class="string">sleep infinity</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"><span class="built_in">chmod</span> +x <span class="string">&quot;<span class="variable">$WRAPPER_PATH</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 7. 启动 PM2</span></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">command</span> -v pm2 &amp;&gt; /dev/null; <span class="keyword">then</span></span><br><span class="line">    pm2 delete <span class="string">&quot;wg-client&quot;</span> &amp;&gt; /dev/null</span><br><span class="line">    pm2 start <span class="string">&quot;<span class="variable">$WRAPPER_PATH</span>&quot;</span> --name <span class="string">&quot;wg-client&quot;</span></span><br><span class="line">    pm2 save</span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;配置完成！请检查：pm2 logs wg-client&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;未找到 PM2，请手动启动 <span class="variable">$WRAPPER_PATH</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br></pre></td></tr></table></figure><hr><h2 id="四、-实战避坑指南：那些让你握手失败的细节"><a href="#四、-实战避坑指南：那些让你握手失败的细节" class="headerlink" title="四、 实战避坑指南：那些让你握手失败的细节"></a>四、 实战避坑指南：那些让你握手失败的细节</h2><p>在探索过程中，我们总结了几个极易忽视的“深坑”：</p><h3 id="1-依赖包的精准补全"><a href="#1-依赖包的精准补全" class="headerlink" title="1. 依赖包的精准补全"></a>1. 依赖包的精准补全</h3><p>精简版镜像往往不含 <code>iproute2</code>。如果报错 <code>ip: command not found</code>，<code>wg-quick</code> 将彻底瘫痪。必须确保安装了此包。</p><h3 id="2-私钥提取的截断问题"><a href="#2-私钥提取的截断问题" class="headerlink" title="2. 私钥提取的截断问题"></a>2. 私钥提取的截断问题</h3><p>在自动化提取旧配置中的私钥时，简单的 <code>cut</code> 命令可能会截断 Base64 末尾的 <code>=</code> 号。WireGuard 对密钥格式有严格要求，任何字符缺失都会导致静默丢包。</p><h3 id="3-MTU-的“木桶效应”"><a href="#3-MTU-的“木桶效应”" class="headerlink" title="3. MTU 的“木桶效应”"></a>3. MTU 的“木桶效应”</h3><p>如果隧道能 Ping 通但无法加载网页，通常是 MTU 导致的。建议在不稳定的链路中统一使用 <code>1280</code>。</p><hr><h2 id="五、-使用建议与工作流"><a href="#五、-使用建议与工作流" class="headerlink" title="五、 使用建议与工作流"></a>五、 使用建议与工作流</h2><ol><li><strong>服务端先行</strong>：运行服务端脚本初始化网关，生成服务端公钥。</li><li><strong>客户端入网</strong>：根据环境选择常规版或 PM2 优化版。运行脚本生成客户端公钥后，在服务端执行 <code>add</code> 操作。</li><li><strong>持久化验证</strong>：重启机器或 PM2 任务，验证隧道是否能自动拉起并恢复握手。</li></ol><hr><blockquote><p><strong>结语</strong>：WireGuard 的强大在于其简洁，而部署的难点在于环境的多样性。通过理解 <code>systemd</code> 与 <code>PM2</code> 的托管差异，以及容器对网络配置的特殊限制，我们才能构建出真正“全场景通用”的自动化组网方案。</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;在现代网络架构中，WireGuard 凭借其极简的代码实现和现代加密算法，已成为高效组建虚拟局域网（VLAN）的首选方案。但在实际部署中，无论是跨境链路的 MTU 陷阱，还是 K8s 容器环境下缺失 &lt;code&gt;systemd&lt;/code&gt; 与 &lt;code&gt;resolvconf&lt;/code&gt; 的限制，都让初学者颇为头疼。&lt;/p&gt;</summary>
    
    
    
    
    <category term="WireGuard" scheme="https://szxiot.com/tags/WireGuard/"/>
    
    <category term="Kubernetes" scheme="https://szxiot.com/tags/Kubernetes/"/>
    
    <category term="Networking" scheme="https://szxiot.com/tags/Networking/"/>
    
  </entry>
  
  <entry>
    <title>ComfyUI 多卡多实例部署指南：基于 PM2 与 Caddy 的自动化实践</title>
    <link href="https://szxiot.com/2026/05/05/comfyui-with-caddy-lb/"/>
    <id>https://szxiot.com/2026/05/05/comfyui-with-caddy-lb/</id>
    <published>2026-05-05T08:30:00.000Z</published>
    <updated>2026-07-07T14:06:47.264Z</updated>
    
    <content type="html"><![CDATA[<p>在高性能 AI 推理场景中，单实例 ComfyUI 往往难以充分利用多显卡（如 RTX 3090）的算力，且面临长耗时任务导致服务假死的风险。本文将分享一套成熟的方案：通过 <strong>PM2</strong> 实现多实例守护与 HTTP 假死监测，并利用 <strong>Caddy</strong> 构建具备“最少连接优先”策略的负载均衡网关。</p><span id="more"></span><h2 id="方案核心优势"><a href="#方案核心优势" class="headerlink" title="方案核心优势"></a>方案核心优势</h2><ol><li><p><strong>自动化集群管理</strong>：一键分发实例到不同 GPU，自动配置 CUDA 环境。  </p></li><li><p><strong>双重可靠性守护</strong>：结合 PM2 进程守护与自定义 HTTP Watchdog，解决 ComfyUI 进程在位但服务假死的顽疾。  </p></li><li><p><strong>推理性能优化</strong>：针对 3090 显卡深度定制，注入 <code>bf16</code>、<code>highvram</code> 及跨注意力优化参数。  </p></li><li><p><strong>智能网关分发</strong>：Caddy 自动实现负载均衡，并针对 AI 生成任务的超长连接进行超时优化。</p></li></ol><hr><h2 id="第一部分：ComfyUI-集群服务部署"><a href="#第一部分：ComfyUI-集群服务部署" class="headerlink" title="第一部分：ComfyUI 集群服务部署"></a>第一部分：ComfyUI 集群服务部署</h2><p>该脚本负责初始化 Python 虚拟环境调用、生成 PM2 配置文件（<code>ecosystem.config.js</code>）以及启动 HTTP 存活监测。</p><h3 id="脚本-1：comfy-pm2-manager-sh"><a href="#脚本-1：comfy-pm2-manager-sh" class="headerlink" title="脚本 1：comfy_pm2_manager.sh"></a>脚本 1：<code>comfy_pm2_manager.sh</code></h3><p>Bash</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line">#!/bin/bash</span><br><span class="line"># ============================================================</span><br><span class="line"># ComfyUI PM2 Cluster Manager (v2.6)</span><br><span class="line"># ============================================================</span><br><span class="line">set -e</span><br><span class="line"></span><br><span class="line">do_install() &#123;</span><br><span class="line">    echo -e &quot;&gt;&gt;&gt; 开始配置 ComfyUI 集群服务...&quot;</span><br><span class="line">    </span><br><span class="line">    # 路径与环境配置</span><br><span class="line">    read -p &quot;1. ComfyUI 目录路径: &quot; WORKSPACE</span><br><span class="line">    WORKSPACE=$&#123;WORKSPACE:-/ai/mnt/comfyui&#125;</span><br><span class="line">    read -p &quot;2. pyenv 虚拟环境名称: &quot; PYENV_NAME</span><br><span class="line">    PYENV_NAME=$&#123;PYENV_NAME:-comfyui&#125;</span><br><span class="line">    </span><br><span class="line">    PYTHON_EXE=&quot;$(eval echo &quot;~$USER&quot;)/.pyenv/versions/$PYENV_NAME/bin/python&quot;</span><br><span class="line">    MAIN_PY=&quot;$WORKSPACE/main.py&quot;</span><br><span class="line"></span><br><span class="line">    read -p &quot;3. 实例总数: &quot; INSTANCE_COUNT</span><br><span class="line"></span><br><span class="line">    # 1. 生成 PM2 配置文件</span><br><span class="line">    CONFIG_FILE=&quot;$WORKSPACE/ecosystem.config.js&quot;</span><br><span class="line">    echo &quot;module.exports = &#123; apps: [&quot; &gt; $CONFIG_FILE</span><br><span class="line">    declare -a PORTS</span><br><span class="line">    for ((i=1; i&lt;=INSTANCE_COUNT; i++)); do</span><br><span class="line">        read -p &quot;实例 #$i 端口: &quot; PORT</span><br><span class="line">        read -p &quot;实例 #$i 显卡 ID: &quot; GPU_ID</span><br><span class="line">        PORTS+=($PORT)</span><br><span class="line">        cat &lt;&lt;EOF &gt;&gt; $CONFIG_FILE</span><br><span class="line">    &#123;</span><br><span class="line">      name: &quot;comfy-$PORT&quot;,</span><br><span class="line">      cwd: &quot;$WORKSPACE&quot;,</span><br><span class="line">      script: &quot;$MAIN_PY&quot;,</span><br><span class="line">      interpreter: &quot;$PYTHON_EXE&quot;,</span><br><span class="line">      args: &quot;--port $PORT --highvram --bf16-unet --use-pytorch-cross-attention --listen 0.0.0.0&quot;,</span><br><span class="line">      env: &#123; CUDA_VISIBLE_DEVICES: &quot;$GPU_ID&quot;, PYTHONUNBUFFERED: &quot;1&quot; &#125;,</span><br><span class="line">      autorestart: true,</span><br><span class="line">      max_memory_restart: &#x27;22G&#x27;</span><br><span class="line">    &#125;,</span><br><span class="line">EOF</span><br><span class="line">    done</span><br><span class="line">    echo &quot;  ] &#125;;&quot; &gt;&gt; $CONFIG_FILE</span><br><span class="line"></span><br><span class="line">    # 2. 生成 Watchdog 监测脚本 (处理假死)</span><br><span class="line">    WATCHDOG_PATH=&quot;$WORKSPACE/comfy_watchdog.sh&quot;</span><br><span class="line">    cat &lt;&lt;EOF &gt; $WATCHDOG_PATH</span><br><span class="line">#!/bin/bash</span><br><span class="line">PORTS=($&#123;PORTS[@]&#125;)</span><br><span class="line">while true; do</span><br><span class="line">  for PORT in &quot;\$&#123;PORTS[@]&#125;&quot;; do</span><br><span class="line">    HTTP_CODE=\$(curl -s -o /dev/null -w &quot;%&#123;http_code&#125;&quot; --max-time 15 http://127.0.0.1:\$PORT/)</span><br><span class="line">    if [ &quot;\$HTTP_CODE&quot; -ne 200 ]; then</span><br><span class="line">        pm2 restart &quot;comfy-\$PORT&quot;</span><br><span class="line">    fi</span><br><span class="line">  done</span><br><span class="line">  sleep 60</span><br><span class="line">done</span><br><span class="line">EOF</span><br><span class="line">    chmod +x $WATCHDOG_PATH</span><br><span class="line"></span><br><span class="line">    # 3. 启动</span><br><span class="line">    pm2 delete /comfy-.*/ 2&gt;/dev/null || true</span><br><span class="line">    pm2 start $CONFIG_FILE</span><br><span class="line">    pm2 start $WATCHDOG_PATH --name &quot;comfy-monitor&quot;</span><br><span class="line">    pm2 save</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">case &quot;$1&quot; in</span><br><span class="line">    install) do_install ;;</span><br><span class="line">    uninstall) pm2 delete /comfy-.*/ 2&gt;/dev/null || true ;;</span><br><span class="line">    *) echo &quot;Usage: $0 &#123;install|uninstall&#125;&quot; ;;</span><br><span class="line">esac</span><br></pre></td></tr></table></figure><hr><h2 id="第二部分：Caddy-负载均衡网关"><a href="#第二部分：Caddy-负载均衡网关" class="headerlink" title="第二部分：Caddy 负载均衡网关"></a>第二部分：Caddy 负载均衡网关</h2><p>在多实例运行后，需要一个统一入口。Caddy 相比 Nginx 的优势在于配置极其简洁，且天然支持 HTTP&#x2F;3。  </p><h3 id="脚本-2：caddy-pm2-setup-sh"><a href="#脚本-2：caddy-pm2-setup-sh" class="headerlink" title="脚本 2：caddy_pm2_setup.sh"></a>脚本 2：<code>caddy_pm2_setup.sh</code></h3><p>此脚本会自动处理端口格式，确保 Caddy 不会将纯数字误认为域名。  </p><p>Bash</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">#!/bin/bash</span><br><span class="line"># ============================================================</span><br><span class="line"># Caddy PM2 自动化部署脚本 (v1.5)</span><br><span class="line"># ============================================================</span><br><span class="line">set -e</span><br><span class="line"></span><br><span class="line"># 1. 自动下载 (支持国内镜像加速)</span><br><span class="line">install_caddy() &#123;</span><br><span class="line">    if ! command -v caddy &gt;/dev/null 2&gt;&amp;1; then</span><br><span class="line">        URL=&quot;https://mirror.ghproxy.com/https://github.com/caddyserver/caddy/releases/download/v2.7.6/caddy_2.7.6_linux_amd64.tar.gz&quot;</span><br><span class="line">        curl -L &quot;$URL&quot; -o caddy.tar.gz</span><br><span class="line">        tar -zxvf caddy.tar.gz caddy</span><br><span class="line">        mv caddy /usr/bin/ &amp;&amp; chmod +x /usr/bin/caddy</span><br><span class="line">        rm caddy.tar.gz</span><br><span class="line">    fi</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"># 2. 生成 Caddyfile 并启动</span><br><span class="line">configure_and_run() &#123;</span><br><span class="line">    read -p &quot;监听端口 (默认 80): &quot; SITE_PORT</span><br><span class="line">    SITE_PORT=$&#123;SITE_PORT:-80&#125;</span><br><span class="line">    [[ $SITE_PORT != :* ]] &amp;&amp; LISTEN_ADDR=&quot;:$SITE_PORT&quot; || LISTEN_ADDR=&quot;$SITE_PORT&quot;</span><br><span class="line">    </span><br><span class="line">    read -p &quot;后端 ComfyUI 端口 (空格分隔): &quot; PORTS</span><br><span class="line">    BACKENDS=&quot;&quot;</span><br><span class="line">    for p in $PORTS; do</span><br><span class="line">        clean_p=$&#123;p#:&#125;</span><br><span class="line">        BACKENDS=&quot;$BACKENDS 127.0.0.1:$clean_p&quot;</span><br><span class="line">    done</span><br><span class="line"></span><br><span class="line">    cat &lt;&lt;EOF &gt; Caddyfile</span><br><span class="line">$LISTEN_ADDR &#123;</span><br><span class="line">    encode gzip</span><br><span class="line">    reverse_proxy &#123;</span><br><span class="line">        to $BACKENDS</span><br><span class="line">        lb_policy least_conn</span><br><span class="line">        health_uri /</span><br><span class="line">        health_interval 10s</span><br><span class="line">        transport http &#123;</span><br><span class="line">            read_timeout 600s</span><br><span class="line">            write_timeout 600s</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    request_body &#123; max_size 1GB &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line">    pm2 delete caddy 2&gt;/dev/null || true</span><br><span class="line">    pm2 start $(which caddy) --name &quot;caddy&quot; -- run --config ./Caddyfile --adapter caddyfile</span><br><span class="line">    pm2 save</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">install_caddy</span><br><span class="line">configure_and_run</span><br></pre></td></tr></table></figure><hr><h2 id="运维管理手册"><a href="#运维管理手册" class="headerlink" title="运维管理手册"></a>运维管理手册</h2><h3 id="1-常用指令"><a href="#1-常用指令" class="headerlink" title="1. 常用指令"></a>1. 常用指令</h3><ul><li><p><strong>查看集群状态</strong>：<code>pm2 list</code></p></li><li><p><strong>查看网关日志</strong>（排查连接问题）：<code>pm2 logs caddy</code></p></li><li><p><strong>查看 ComfyUI 日志</strong>：<code>pm2 logs comfy-8188</code></p></li><li><p><strong>重启整个集群</strong>：<code>pm2 restart all</code></p></li></ul><h3 id="2-关键配置解析"><a href="#2-关键配置解析" class="headerlink" title="2. 关键配置解析"></a>2. 关键配置解析</h3><ul><li><p>**<code>lb_policy least_conn</code>**：最少连接数优先。这对于 AI 推理至关重要，因为有的请求（如视频生成）耗时极长，该策略能确保新请求发往空闲实例。  </p></li><li><p>**<code>read_timeout 600s</code>**：将超时阈值提升至 10 分钟。默认网关通常在 60s 后断开，会导致长耗时工作流前端报错。</p></li><li><p>**<code>CUDA_VISIBLE_DEVICES</code>**：通过环境变量精确锁定每个进程可见的 GPU，避免多实例竞抢同一张卡的显存。</p></li></ul><hr><h2 id="卸载与清理"><a href="#卸载与清理" class="headerlink" title="卸载与清理"></a>卸载与清理</h2><p>如需移除服务，可运行 <code>pm2 delete caddy /comfy-.*/</code>。本方案在清理时采用正则匹配，<strong>绝不会</strong>误伤服务器上的其他关键服务。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;在高性能 AI 推理场景中，单实例 ComfyUI 往往难以充分利用多显卡（如 RTX 3090）的算力，且面临长耗时任务导致服务假死的风险。本文将分享一套成熟的方案：通过 &lt;strong&gt;PM2&lt;/strong&gt; 实现多实例守护与 HTTP 假死监测，并利用 &lt;strong&gt;Caddy&lt;/strong&gt; 构建具备“最少连接优先”策略的负载均衡网关。&lt;/p&gt;</summary>
    
    
    
    
    <category term="ComfyUI" scheme="https://szxiot.com/tags/ComfyUI/"/>
    
    <category term="GPU" scheme="https://szxiot.com/tags/GPU/"/>
    
    <category term="Caddy" scheme="https://szxiot.com/tags/Caddy/"/>
    
    <category term="PM2" scheme="https://szxiot.com/tags/PM2/"/>
    
  </entry>
  
  <entry>
    <title>Home Assistant接入OpenClaw</title>
    <link href="https://szxiot.com/2026/04/13/openclaw-homeassistant/"/>
    <id>https://szxiot.com/2026/04/13/openclaw-homeassistant/</id>
    <published>2026-04-13T03:09:55.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p>OpenClaw通过接入 Home Assistant (HA)，化身为你的全能管家。</p><p>本文将带你快速完成 OpenClaw 与 Home Assistant 的联动配置。</p><span id="more"></span><h2 id="1-准备工作"><a href="#1-准备工作" class="headerlink" title="1. 准备工作"></a>1. 准备工作</h2><ul><li>成功部署了OpenClaw</li><li>拥有一个可内网或外网访问的Home Assistant</li></ul><h2 id="2-在-Home-Assistant-中生成令牌"><a href="#2-在-Home-Assistant-中生成令牌" class="headerlink" title="2. 在 Home Assistant 中生成令牌"></a>2. 在 Home Assistant 中生成令牌</h2><p>为了让 OpenClaw 有权操作你的设备(建议新建一个用户,不要设为管理员,也不要用你的管理员账户生成token)，需要生成一个 **长期访问令牌 (Long-Lived Access Token) **：</p><ol><li>登录你的 Home Assistant 面板。</li><li>点击左下角的 <strong>个人头像</strong>（用户资料）。</li><li>滚动到底部，找到 <strong>长期访问令牌</strong> 栏目。</li><li>点击 <strong>创建令牌</strong>，命名为 <code>OpenClaw</code>。</li><li><strong>复制并保存</strong> 弹出的字符串（注意：关闭后将无法再次查看）。</li></ol><h2 id="3-OpenClaw-端配置"><a href="#3-OpenClaw-端配置" class="headerlink" title="3. OpenClaw 端配置"></a>3. OpenClaw 端配置</h2><h3 id="安装技能"><a href="#安装技能" class="headerlink" title="安装技能"></a>安装技能</h3><p>在OpenClaw的聊天对话框(或其他你已经配置的channel),告诉openclaw:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">帮我安装home assistant skill，也可以根据你的需求进行安装</span><br></pre></td></tr></table></figure><p><img src="https://s.cat.gd/2026/04/7f0bdbad27a18d285d49d1a539a7b64d.png" loading="lazy"></p><h3 id="配置Home-Assistant参数"><a href="#配置Home-Assistant参数" class="headerlink" title="配置Home Assistant参数"></a>配置Home Assistant参数</h3><p>修改<code>config.json</code>,如果没有就复制example来修改,设置url和token,注意url不要设置localhost或127.0.0.1(HA可能跟openclaw不在一个服务器)<br><img src="https://s.cat.gd/2026/04/dd60a52df710b011869dd4afdba41522.png" loading="lazy"><br>这里的参数配置,也可以让openclaw自己来完成.</p><table><thead><tr><th align="left">参数名</th><th align="left">示例值</th><th align="left">说明</th></tr></thead><tbody><tr><td align="left"><code>url</code></td><td align="left"><code>http://192.168.1.100:8123</code></td><td align="left">你的 HA 访问地址</td></tr><tr><td align="left"><code>token</code></td><td align="left"><code>你的长期访问令牌</code></td><td align="left">刚才生成的 Token</td></tr></tbody></table><h2 id="4-常用指令与测试"><a href="#4-常用指令与测试" class="headerlink" title="4. 常用指令与测试"></a>4. 常用指令与测试</h2><p><img src="https://s.cat.gd/2026/04/63a08e496429eaedab758da3d666ccff.png" loading="lazy"><br>配置完成后，你可以尝试通过 OpenClaw（例如在 Telegram 或微信中）向它下达指令：</p><blockquote><p>“帮我打开客厅的灯。”<br>“现在主卧的温度是多少？”<br>“帮我关掉家里所有的电器。”</p></blockquote><p>OpenClaw 会调用 HA 的 API 自动识别实体 ID 并执行操作。</p><p><img src="https://s.cat.gd/2026/04/61d7f807911cb69de548e903a18d3e5f.png" loading="lazy"></p><h2 id="5-常见问题-FAQ"><a href="#5-常见问题-FAQ" class="headerlink" title="5. 常见问题 (FAQ)"></a>5. 常见问题 (FAQ)</h2><ul><li><strong>无法连接？</strong> 检查 HA 是否开启了防火墙，或者 OpenClaw 所在服务器是否能 Ping 通 HA 地址。</li><li><strong>找不到设备？</strong> 请确保在 HA 中为设备设置了易于识别的“别名”（Friendly Name），这样 AI 识别率更高。</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;OpenClaw通过接入 Home Assistant (HA)，化身为你的全能管家。&lt;/p&gt;
&lt;p&gt;本文将带你快速完成 OpenClaw 与 Home Assistant 的联动配置。&lt;/p&gt;</summary>
    
    
    
    
    <category term="教程" scheme="https://szxiot.com/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="OpenClaw" scheme="https://szxiot.com/tags/OpenClaw/"/>
    
    <category term="HA" scheme="https://szxiot.com/tags/HA/"/>
    
    <category term="Home Assistant" scheme="https://szxiot.com/tags/Home-Assistant/"/>
    
  </entry>
  
  <entry>
    <title>OpenClaw 入门部署教程 - 从零开始搭建你的 AI 助手</title>
    <link href="https://szxiot.com/2026/03/21/openclaw-quick-start/"/>
    <id>https://szxiot.com/2026/03/21/openclaw-quick-start/</id>
    <published>2026-03-21T10:20:00.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p>OpenClaw 是一个强大的 AI 助手框架，支持多种消息平台（WhatsApp、Telegram、飞书等）、自定义工具和自动化工作流。本文将带你从零开始，在 10 分钟内完成 OpenClaw 的部署和配置。</p><span id="more"></span><h2 id="什么是-OpenClaw？"><a href="#什么是-OpenClaw？" class="headerlink" title="什么是 OpenClaw？"></a>什么是 OpenClaw？</h2><p>OpenClaw 是一个开源的 AI 助手运行时，核心特点：</p><ul><li><strong>多平台支持</strong> - WhatsApp、Telegram、飞书、Discord 等</li><li><strong>工具扩展</strong> - 文件操作、网页搜索、浏览器自动化等</li><li><strong>本地部署</strong> - 数据完全掌控，支持私有模型</li><li><strong>技能系统</strong> - 模块化扩展，自定义工作流</li></ul><h2 id="系统要求"><a href="#系统要求" class="headerlink" title="系统要求"></a>系统要求</h2><ul><li><strong>Node.js</strong>: 24+ 推荐（22 LTS 也支持）</li><li><strong>系统</strong>: macOS、Linux 或 Windows（WSL2）</li><li><strong>内存</strong>: 最低 1GB，推荐 2GB+</li><li><strong>存储</strong>: 约 500MB（不含模型）</li></ul><p>检查 Node 版本：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">node --version</span><br><span class="line"><span class="comment"># 应显示 v22.16+ 或 v24+</span></span><br></pre></td></tr></table></figure><h2 id="快速安装"><a href="#快速安装" class="headerlink" title="快速安装"></a>快速安装</h2><h3 id="方式一：安装脚本（推荐）"><a href="#方式一：安装脚本（推荐）" class="headerlink" title="方式一：安装脚本（推荐）"></a>方式一：安装脚本（推荐）</h3><p><strong>macOS &#x2F; Linux</strong>:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -fsSL https://openclaw.ai/install.sh | bash</span><br></pre></td></tr></table></figure><p><strong>Windows (PowerShell)</strong>:</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">iwr</span> <span class="literal">-useb</span> https://openclaw.ai/install.ps1 | <span class="built_in">iex</span></span><br></pre></td></tr></table></figure><p>安装脚本会自动：</p><ol><li>检测并安装合适的 Node.js 版本</li><li>安装 OpenClaw CLI</li><li>启动配置向导</li></ol><h3 id="方式二：npm-手动安装"><a href="#方式二：npm-手动安装" class="headerlink" title="方式二：npm 手动安装"></a>方式二：npm 手动安装</h3><p>如果已管理 Node.js 环境：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install -g openclaw@latest</span><br><span class="line">openclaw onboard --install-daemon</span><br></pre></td></tr></table></figure><blockquote><p><strong>注意</strong>: 如果遇到 <code>sharp</code> 构建错误（macOS 常见），使用：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest</span><br><span class="line">```bash</span><br><span class="line"></span><br><span class="line"><span class="comment">### 方式三：Docker 部署</span></span><br><span class="line"></span><br><span class="line">适合服务器或隔离环境：</span><br><span class="line"></span><br><span class="line">```bash</span><br><span class="line">docker run -d \</span><br><span class="line"> --name openclaw \</span><br><span class="line"> -p 18789:18789 \</span><br><span class="line"> -v openclaw-data:/root/.openclaw \</span><br><span class="line"> openclaw/openclaw:latest</span><br></pre></td></tr></table></figure></blockquote><p>访问 <code>http://localhost:18789</code> 查看控制面板。</p><h2 id="初始化配置"><a href="#初始化配置" class="headerlink" title="初始化配置"></a>初始化配置</h2><p>安装完成后，运行配置向导：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">openclaw onboard --install-daemon</span><br></pre></td></tr></table></figure><p>向导会引导你完成：</p><ol><li><strong>选择 AI 模型</strong> - 支持 OpenAI、Anthropic、智谱、通义千问等</li><li><strong>配置认证</strong> - 输入 API Key</li><li><strong>选择渠道</strong> - WhatsApp、Telegram、飞书等（可跳过）</li><li><strong>安装服务</strong> - 将 Gateway 注册为系统服务</li></ol><h3 id="模型推荐"><a href="#模型推荐" class="headerlink" title="模型推荐"></a>模型推荐</h3><table><thead><tr><th>提供商</th><th>模型</th><th>特点</th></tr></thead><tbody><tr><td>智谱 AI</td><td>glm-4</td><td>中文优秀，性价比高</td></tr><tr><td>通义千问</td><td>qwen-plus</td><td>长文本处理好</td></tr><tr><td>OpenAI</td><td>gpt-4o</td><td>综合能力最强</td></tr><tr><td>Anthropic</td><td>claude-3.5</td><td>代码能力强</td></tr></tbody></table><h2 id="启动和验证"><a href="#启动和验证" class="headerlink" title="启动和验证"></a>启动和验证</h2><h3 id="检查服务状态"><a href="#检查服务状态" class="headerlink" title="检查服务状态"></a>检查服务状态</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">openclaw gateway status</span><br></pre></td></tr></table></figure><p>正常输出应显示服务运行中。</p><h3 id="打开控制面板"><a href="#打开控制面板" class="headerlink" title="打开控制面板"></a>打开控制面板</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">openclaw dashboard</span><br></pre></td></tr></table></figure><p>或访问 <code>http://127.0.0.1:18789/</code></p><p>在控制面板中，你可以：</p><ul><li>直接对话测试</li><li>查看会话历史</li><li>配置模型和渠道</li><li>管理技能和工具</li></ul><h3 id="发送测试消息"><a href="#发送测试消息" class="headerlink" title="发送测试消息"></a>发送测试消息</h3><p>如果配置了渠道（如飞书）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">openclaw message send \</span><br><span class="line">  --target <span class="string">&quot;用户 ID&quot;</span> \</span><br><span class="line">  --message <span class="string">&quot;Hello from OpenClaw&quot;</span></span><br></pre></td></tr></table></figure><h2 id="配置渠道（可选）"><a href="#配置渠道（可选）" class="headerlink" title="配置渠道（可选）"></a>配置渠道（可选）</h2><h3 id="飞书（Feishu）"><a href="#飞书（Feishu）" class="headerlink" title="飞书（Feishu）"></a>飞书（Feishu）</h3><ol><li>创建飞书应用：<a href="https://open.feishu.cn/app">https://open.feishu.cn/app</a></li><li>获取 App ID 和 App Secret</li><li>配置回调 URL：<code>https://你的域名/openclaw/feishu</code></li><li>添加到配置文件：</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">openclaw config edit</span><br></pre></td></tr></table></figure><p>添加配置：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">channels:</span></span><br><span class="line">  <span class="attr">feishu:</span></span><br><span class="line">    <span class="attr">appId:</span> <span class="string">cli_xxxxxxxxxxxxx</span></span><br><span class="line">    <span class="attr">appSecret:</span> <span class="string">xxxxxxxxxxxxxxx</span></span><br></pre></td></tr></table></figure><h3 id="WhatsApp"><a href="#WhatsApp" class="headerlink" title="WhatsApp"></a>WhatsApp</h3><ol><li>运行：<code>openclaw channels whatsapp setup</code></li><li>扫描二维码绑定</li><li>完成配置</li></ol><h3 id="Telegram"><a href="#Telegram" class="headerlink" title="Telegram"></a>Telegram</h3><ol><li>联系 @BotFather 创建机器人</li><li>获取 Token</li><li>配置：<code>openclaw channels telegram add &lt;token&gt;</code></li></ol><h2 id="使用技能"><a href="#使用技能" class="headerlink" title="使用技能"></a>使用技能</h2><p>OpenClaw 支持技能扩展，例如：</p><h3 id="查看可用技能"><a href="#查看可用技能" class="headerlink" title="查看可用技能"></a>查看可用技能</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">ls</span> ~/.openclaw/workspace/skills/</span><br></pre></td></tr></table></figure><h3 id="使用技能对话"><a href="#使用技能对话" class="headerlink" title="使用技能对话"></a>使用技能对话</h3><p>直接在聊天中说明需求：</p><ul><li>“帮我写一篇技术博客” → 使用 <code>hexo-blogger</code> 技能</li><li>“检查天气” → 使用 <code>weather</code> 技能</li><li>“搜索 GitHub issues” → 使用 <code>gh-issues</code> 技能</li></ul><h3 id="创建自定义技能"><a href="#创建自定义技能" class="headerlink" title="创建自定义技能"></a>创建自定义技能</h3><p>参考官方文档：<a href="/skills/creating">技能创建指南</a></p><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看状态</span></span><br><span class="line">openclaw status</span><br><span class="line">openclaw gateway status</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启服务</span></span><br><span class="line">openclaw gateway restart</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看日志</span></span><br><span class="line">openclaw gateway logs</span><br><span class="line"></span><br><span class="line"><span class="comment"># 更新版本</span></span><br><span class="line">openclaw update</span><br><span class="line"></span><br><span class="line"><span class="comment"># 打开配置</span></span><br><span class="line">openclaw config edit</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看帮助</span></span><br><span class="line">openclaw --<span class="built_in">help</span></span><br></pre></td></tr></table></figure><h2 id="故障排查"><a href="#故障排查" class="headerlink" title="故障排查"></a>故障排查</h2><h3 id="Gateway-无法启动"><a href="#Gateway-无法启动" class="headerlink" title="Gateway 无法启动"></a>Gateway 无法启动</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看详细日志</span></span><br><span class="line">openclaw gateway logs --follow</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查端口占用</span></span><br><span class="line">lsof -i :18789</span><br><span class="line"></span><br><span class="line"><span class="comment"># 手动前台运行测试</span></span><br><span class="line">openclaw gateway --port 18789</span><br></pre></td></tr></table></figure><h3 id="模型调用失败"><a href="#模型调用失败" class="headerlink" title="模型调用失败"></a>模型调用失败</h3><ol><li>检查 API Key 是否正确</li><li>验证网络连接</li><li>查看配额限制</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 测试模型连接</span></span><br><span class="line">openclaw models <span class="built_in">test</span> &lt;model-name&gt;</span><br></pre></td></tr></table></figure><h3 id="渠道消息不响应"><a href="#渠道消息不响应" class="headerlink" title="渠道消息不响应"></a>渠道消息不响应</h3><ol><li>检查渠道是否启用</li><li>验证回调 URL 配置</li><li>查看渠道日志</li></ol><h2 id="进阶配置"><a href="#进阶配置" class="headerlink" title="进阶配置"></a>进阶配置</h2><h3 id="自定义工作目录"><a href="#自定义工作目录" class="headerlink" title="自定义工作目录"></a>自定义工作目录</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> OPENCLAW_HOME=/path/to/your/workspace</span><br></pre></td></tr></table></figure><h3 id="配置文件位置"><a href="#配置文件位置" class="headerlink" title="配置文件位置"></a>配置文件位置</h3><ul><li><strong>配置</strong>: <code>~/.openclaw/config.json</code></li><li><strong>工作区</strong>: <code>~/.openclaw/workspace/</code></li><li><strong>日志</strong>: <code>~/.openclaw/logs/</code></li></ul><h3 id="环境变量"><a href="#环境变量" class="headerlink" title="环境变量"></a>环境变量</h3><table><thead><tr><th>变量</th><th>说明</th></tr></thead><tbody><tr><td><code>OPENCLAW_HOME</code></td><td>自定义根目录</td></tr><tr><td><code>OPENCLAW_STATE_DIR</code></td><td>状态目录</td></tr><tr><td><code>OPENCLAW_CONFIG_PATH</code></td><td>配置文件路径</td></tr></tbody></table><h2 id="下一步"><a href="#下一步" class="headerlink" title="下一步"></a>下一步</h2><ul><li>📚 <a href="https://docs.openclaw.ai/">官方文档</a></li><li>💬 <a href="https://discord.com/invite/clawd">Discord 社区</a></li><li>🛠️ <a href="https://clawhub.com/">技能中心</a></li><li>🔧 <a href="/tools/custom">自定义工具开发</a></li></ul><hr><p><strong>参考信息</strong>:</p><ul><li>当前版本：OpenClaw 2026.3.13</li><li>Node.js 版本：v24.10.0</li><li>文档更新日期：2026-03-21</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;OpenClaw 是一个强大的 AI 助手框架，支持多种消息平台（WhatsApp、Telegram、飞书等）、自定义工具和自动化工作流。本文将带你从零开始，在 10 分钟内完成 OpenClaw 的部署和配置。&lt;/p&gt;</summary>
    
    
    
    
    <category term="OpenClaw" scheme="https://szxiot.com/tags/OpenClaw/"/>
    
    <category term="AI 助手，教程，Docker" scheme="https://szxiot.com/tags/AI-%E5%8A%A9%E6%89%8B%EF%BC%8C%E6%95%99%E7%A8%8B%EF%BC%8CDocker/"/>
    
    <category term="Node.js" scheme="https://szxiot.com/tags/Node-js/"/>
    
  </entry>
  
  <entry>
    <title>Ollama 完全使用指南</title>
    <link href="https://szxiot.com/2025/12/01/ollama-tutorial/"/>
    <id>https://szxiot.com/2025/12/01/ollama-tutorial/</id>
    <published>2025-12-01T06:17:14.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p><strong>面向大模型入门用户</strong> – 从零安装、环境变量配置到模型管理与 API 调用，一站式搞定。</p><span id="more"></span><h2 id="1️⃣-多平台快速安装"><a href="#1️⃣-多平台快速安装" class="headerlink" title="1️⃣ 多平台快速安装"></a>1️⃣ 多平台快速安装</h2><table><thead><tr><th>平台</th><th>安装方式</th></tr></thead><tbody><tr><td><strong>macOS</strong></td><td>访问官方页面直接下载<a href="https://ollama.com/download/Ollama-darwin.zip">桌面版</a></td></tr><tr><td><strong>Windows</strong></td><td>访问官方页面下载 <a href="https://ollama.com/download/OllamaSetup.exe"><code>OllamaSetup.exe</code></a></td></tr><tr><td><strong>Linux</strong></td><td>运行一条 <code>curl</code> 脚本即可完成&#96;curl -fsSL <a href="https://ollama.com/install.sh">https://ollama.com/install.sh</a></td></tr><tr><td><strong>Docker</strong></td><td>拉取官方镜像 <code>docker run -p 11434:11434 ollama/ollama</code></td></tr></tbody></table><blockquote><p><strong>提示</strong>：Linux 版的脚本会自动把 <code>ollama</code> 二进制放到系统路径下，并创建 <code>ollama</code> 系统服务，后续可以用 <code>systemctl</code> 管理。</p></blockquote><hr><h2 id="2️⃣-环境变量-amp-服务配置"><a href="#2️⃣-环境变量-amp-服务配置" class="headerlink" title="2️⃣ 环境变量 &amp; 服务配置"></a>2️⃣ 环境变量 &amp; 服务配置</h2><p>Ollama 通过环境变量控制监听地址、模型存储路径、并发数等。不同系统的配置方式略有差异。</p><h3 id="2-1-常用环境变量（跨平台）"><a href="#2-1-常用环境变量（跨平台）" class="headerlink" title="2.1 常用环境变量（跨平台）"></a>2.1 常用环境变量（跨平台）</h3><table><thead><tr><th>变量</th><th>功能</th><th>示例</th></tr></thead><tbody><tr><td><code>OLLAMA_HOST</code></td><td>绑定的 IP（默认 <code>127.0.0.1</code>）</td><td><code>OLLAMA_HOST=0.0.0.0</code> 让外网可访问</td></tr><tr><td><code>OLLAMA_MODELS</code></td><td>模型存放目录（默认见下表）</td><td><code>OLLAMA_MODELS=/mnt/ollama/models</code></td></tr><tr><td><code>OLLAMA_KEEP_ALIVE</code></td><td>模型在内存中保活时长，<code>1h</code> 表示 1 小时</td><td></td></tr><tr><td><code>OLLAMA_PORT</code></td><td>HTTP 服务端口，默认 <code>11434</code></td><td></td></tr><tr><td><code>OLLAMA_NUM_PARALLEL</code></td><td>同时处理的请求数，默认随硬件自动调节</td><td></td></tr><tr><td><code>OLLAMA_MAX_LOADED_MODELS</code></td><td>同时加载模型的上限，防止显存&#x2F;内存被占满</td><td></td></tr></tbody></table><h4 id="2-2-默认模型存放路径"><a href="#2-2-默认模型存放路径" class="headerlink" title="2.2 默认模型存放路径"></a>2.2 默认模型存放路径</h4><table><thead><tr><th>系统</th><th>默认目录</th></tr></thead><tbody><tr><td>macOS</td><td><code>~/.ollama/models</code></td></tr><tr><td>Linux</td><td><code>/usr/share/ollama/.ollama/models</code></td></tr><tr><td>Windows</td><td><code>C:\Users\&lt;username&gt;\.ollama\models</code></td></tr></tbody></table><h4 id="2-3-OS‑Specific-设置方法"><a href="#2-3-OS‑Specific-设置方法" class="headerlink" title="2.3 OS‑Specific 设置方法"></a>2.3 OS‑Specific 设置方法</h4><table><thead><tr><th>系统</th><th>关键步骤</th></tr></thead><tbody><tr><td><strong>macOS</strong></td><td>使用 <code>launchctl setenv</code> 为每个变量设置，然后重启 Ollama 应用</td></tr><tr><td><strong>Linux</strong></td><td>编辑 <code>ollama.service</code>（<code>systemctl edit ollama.service</code>），在 <code>[Service]</code> 下添加 <code>Environment=&quot;VAR=VALUE&quot;</code>，最后 <code>systemctl daemon-reload &amp;&amp; systemctl restart ollama</code></td></tr><tr><td><strong>Windows</strong></td><td>在「系统属性 → 环境变量」中新建变量，如 <code>OLLAMA_HOST</code>、<code>OLLAMA_MODELS</code>，退出 Ollama 并重新启动以生效</td></tr></tbody></table><blockquote><p><strong>小技巧</strong>：修改完变量后，务必 <strong>重启</strong> Ollama（或重新加载 systemd）让新配置生效。</p></blockquote><hr><h2 id="3️⃣-核心-CLI-命令一览"><a href="#3️⃣-核心-CLI-命令一览" class="headerlink" title="3️⃣ 核心 CLI 命令一览"></a>3️⃣ 核心 CLI 命令一览</h2><p>下面列出常用的 <code>ollama</code> 子命令，配合 <code>--help</code> 可查看完整参数说明。</p><table><thead><tr><th>命令</th><th>说明</th></tr></thead><tbody><tr><td><code>ollama serve</code></td><td>启动后台服务（不打开桌面 UI）</td></tr><tr><td><code>ollama pull &lt;model&gt;</code></td><td>拉取模型（等价于第一次 <code>ollama run</code>）</td></tr><tr><td><code>ollama run &lt;model&gt;</code></td><td>交互式对话或一次性生成（首次会自动 <code>pull</code>）</td></tr><tr><td><code>ollama list</code></td><td>列出本机已下载的模型</td></tr><tr><td><code>ollama ps</code></td><td>查看当前已加载到内存（CPU&#x2F;GPU）的模型</td></tr><tr><td><code>ollama show &lt;model&gt;</code></td><td>查看模型元信息</td></tr><tr><td><code>ollama create &lt;name&gt; -f Modelfile</code></td><td>基于自定义 <code>Modelfile</code> 构建新模型</td></tr><tr><td><code>ollama rm &lt;model&gt;</code></td><td>删除本地模型</td></tr><tr><td><code>ollama cp &lt;src&gt; &lt;dst&gt;</code></td><td>复制模型（用于迁移或备份）</td></tr></tbody></table><blockquote><p><strong>实战</strong>：想把 <code>qwen3:30b</code> 直接拉取并对话，只需一行 <code>ollama run qwen3:30b</code>。</p></blockquote><hr><h2 id="4️⃣-常用模型快速上手"><a href="#4️⃣-常用模型快速上手" class="headerlink" title="4️⃣ 常用模型快速上手"></a>4️⃣ 常用模型快速上手</h2><p>Ollama 官方库提供了多种模型，下面列出常见几款及对应的拉取命令（模型大小在括号，单位 GB）【6†L51-L65】。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ollama run qwen3:235b        <span class="comment"># 23bB, 142GB</span></span><br><span class="line">ollama run qwen3:30b         <span class="comment"># 30B, 18GB</span></span><br><span class="line">ollama run deepseek-r1:32b  <span class="comment"># 32B, 19GB </span></span><br><span class="line">ollama run qwen3-vl:8b      <span class="comment"># 8B, 6.1GB (Vision)</span></span><br></pre></td></tr></table></figure><blockquote><p><strong>内存要求</strong>：  </p><ul><li>8 GB RAM 可运行 7B 模型；  </li><li>16 GB RAM 推荐运行 13B 以上模型；  </li><li>32 GB+ RAM 可流畅运行 33 B+ 大模型。</li></ul></blockquote><hr><h2 id="5️⃣-自定义模型（Modelfile）"><a href="#5️⃣-自定义模型（Modelfile）" class="headerlink" title="5️⃣ 自定义模型（Modelfile）"></a>5️⃣ 自定义模型（Modelfile）</h2><h3 id="5-1-Modelfile-基本语法"><a href="#5-1-Modelfile-基本语法" class="headerlink" title="5.1 Modelfile 基本语法"></a>5.1 Modelfile 基本语法</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># comment</span><br><span class="line">INSTRUCTION arguments</span><br></pre></td></tr></table></figure><p>常用指令包括：</p><table><thead><tr><th>指令</th><th>作用</th></tr></thead><tbody><tr><td><code>FROM</code></td><td>指定基模型（必填）</td></tr><tr><td><code>PARAMETER</code></td><td>设置推理参数（temperature、num_ctx 等）</td></tr><tr><td><code>SYSTEM</code></td><td>自定义系统提示</td></tr><tr><td><code>ADAPTER</code></td><td>加载 LoRA &#x2F; QLoRA 适配器</td></tr><tr><td><code>LICENSE</code></td><td>声明模型版权</td></tr><tr><td><code>MESSAGE</code></td><td>固定对话历史</td></tr></tbody></table><blockquote><p>示例（基于 <code>llama3.2</code>，温度 1、上下文 4096、系统提示）：</p></blockquote><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">FROM llama3.2</span><br><span class="line">PARAMETER temperature 1</span><br><span class="line">PARAMETER num_ctx 4096</span><br><span class="line">SYSTEM You are Mario from Super Mario Bros, answering as Mario.</span><br></pre></td></tr></table></figure><h3 id="5-2-创建-amp-运行自定义模型"><a href="#5-2-创建-amp-运行自定义模型" class="headerlink" title="5.2 创建 &amp; 运行自定义模型"></a>5.2 创建 &amp; 运行自定义模型</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1️⃣ 保存为 Modelfile</span></span><br><span class="line"><span class="built_in">cat</span> &gt; Modelfile &lt;&lt;<span class="string">EOF</span></span><br><span class="line"><span class="string">FROM llama3.2</span></span><br><span class="line"><span class="string">PARAMETER temperature 1</span></span><br><span class="line"><span class="string">SYSTEM You are Mario...</span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2️⃣ 构建模型</span></span><br><span class="line">ollama create mario -f Modelfile   </span><br><span class="line"></span><br><span class="line"><span class="comment"># 3️⃣ 使用模型</span></span><br><span class="line">ollama run mario</span><br></pre></td></tr></table></figure><blockquote><p><strong>温度 &#x2F; 上下文</strong>：在交互式会话里也可以随时通过 <code>/set parameter</code> 调整，例如 <code>/set parameter num_ctx 4096</code>。</p></blockquote><hr><h2 id="6️⃣-GPU-加速与并发控制"><a href="#6️⃣-GPU-加速与并发控制" class="headerlink" title="6️⃣ GPU 加速与并发控制"></a>6️⃣ GPU 加速与并发控制</h2><h3 id="6-1-GPU-兼容性"><a href="#6-1-GPU-兼容性" class="headerlink" title="6.1 GPU 兼容性"></a>6.1 GPU 兼容性</h3><p>官方文档提供 GPU 兼容列表（NVIDIA、AMD ROCm 等）。  </p><ul><li>Linux 上使用 <code>curl</code> 安装的版本会自动检测并使用 CUDA。  </li><li>Windows 需要 WSL2 + NVIDIA 驱动或直接在本地（自 0.1.33 起原生支持）。</li></ul><h3 id="6-2-查看模型是否在-GPU-上运行"><a href="#6-2-查看模型是否在-GPU-上运行" class="headerlink" title="6.2 查看模型是否在 GPU 上运行"></a>6.2 查看模型是否在 GPU 上运行</h3><p><code>ollama ps</code> 会显示每个模型的 <code>Processor</code> 列，<code>100% GPU</code> 表示已完全加载到显存。</p><h3 id="6-3-并发请求-amp-资源限制"><a href="#6-3-并发请求-amp-资源限制" class="headerlink" title="6.3 并发请求 &amp; 资源限制"></a>6.3 并发请求 &amp; 资源限制</h3><table><thead><tr><th>环境变量</th><th>作用</th></tr></thead><tbody><tr><td><code>OLLAMA_NUM_PARALLEL</code></td><td>单模型最大并发请求数，默认随显存自动选择 1 或 4</td></tr><tr><td><code>OLLAMA_MAX_LOADED_MODELS</code></td><td>同时在内存&#x2F;显存中保留的模型数量上限</td></tr><tr><td><code>OLLAMA_KEEP_ALIVE</code></td><td>模型空闲后保留时长，避免频繁加载&#x2F;卸载</td></tr></tbody></table><blockquote><p><strong>调优思路</strong>：显存足够时，可适当提升 <code>OLLAMA_NUM_PARALLEL</code>；若出现 OOM，需要降低 <code>OLLAMA_MAX_LOADED_MODELS</code> 或 <code>NUM_PARALLEL</code>。</p></blockquote><hr><h2 id="7️⃣-REST-API-与-SDK-示例"><a href="#7️⃣-REST-API-与-SDK-示例" class="headerlink" title="7️⃣ REST API 与 SDK 示例"></a>7️⃣ REST API 与 SDK 示例</h2><p>Ollama 提供标准的 HTTP 接口，适配所有语言。下面展示最常用的 <code>generate</code> 与 <code>chat</code> 两个端点。</p><h3 id="7-1-单轮生成（-api-generate）"><a href="#7-1-单轮生成（-api-generate）" class="headerlink" title="7.1 单轮生成（/api/generate）"></a>7.1 单轮生成（<code>/api/generate</code>）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">curl http://localhost:11434/api/generate -d <span class="string">&#x27;&#123;</span></span><br><span class="line"><span class="string">  &quot;model&quot;: &quot;llama3.2&quot;,</span></span><br><span class="line"><span class="string">  &quot;prompt&quot;: &quot;Why is the sky blue?&quot;,</span></span><br><span class="line"><span class="string">  &quot;options&quot;: &#123; &quot;num_ctx&quot;: 4096 &#125;</span></span><br><span class="line"><span class="string">&#125;&#x27;</span></span><br></pre></td></tr></table></figure><blockquote><p><code>num_ctx</code> 用于扩大上下文窗口。</p></blockquote><h3 id="7-2-多轮对话（-api-chat）"><a href="#7-2-多轮对话（-api-chat）" class="headerlink" title="7.2 多轮对话（/api/chat）"></a>7.2 多轮对话（<code>/api/chat</code>）</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">curl http://localhost:11434/api/chat -d <span class="string">&#x27;&#123;</span></span><br><span class="line"><span class="string">  &quot;model&quot;: &quot;llama3.2&quot;,</span></span><br><span class="line"><span class="string">  &quot;messages&quot;: [</span></span><br><span class="line"><span class="string">    &#123;&quot;role&quot;:&quot;user&quot;,&quot;content&quot;:&quot;What is the meaning of life?&quot;&#125;,</span></span><br><span class="line"><span class="string">    &#123;&quot;role&quot;:&quot;assistant&quot;,&quot;content&quot;:&quot;42&quot;&#125;</span></span><br><span class="line"><span class="string">  ]</span></span><br><span class="line"><span class="string">&#125;&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="7-3-Python-SDK（简要示例）"><a href="#7-3-Python-SDK（简要示例）" class="headerlink" title="7.3 Python SDK（简要示例）"></a>7.3 Python SDK（简要示例）</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> ollama <span class="keyword">import</span> Client</span><br><span class="line"></span><br><span class="line">client = Client(host=<span class="string">&quot;http://localhost:11434&quot;</span>)</span><br><span class="line">resp = client.generate(</span><br><span class="line">    model=<span class="string">&quot;phi3&quot;</span>,</span><br><span class="line">    prompt=<span class="string">&quot;写一段 Python 的冒泡排序代码&quot;</span>,</span><br><span class="line">    options=&#123;<span class="string">&quot;temperature&quot;</span>: <span class="number">0.7</span>&#125;</span><br><span class="line">)</span><br><span class="line"><span class="built_in">print</span>(resp[<span class="string">&quot;response&quot;</span>])</span><br></pre></td></tr></table></figure><blockquote><p>官方 Python SDK 与 JS SDK 均已发布，可在 GitHub 上获取。</p></blockquote><hr><h2 id="8️⃣-常见问题-amp-调试技巧"><a href="#8️⃣-常见问题-amp-调试技巧" class="headerlink" title="8️⃣ 常见问题 &amp; 调试技巧"></a>8️⃣ 常见问题 &amp; 调试技巧</h2><table><thead><tr><th>场景</th><th>解决方案</th></tr></thead><tbody><tr><td><strong>升级</strong></td><td>macOS&#x2F;Windows 自动检测更新；Linux 重新运行安装脚本 &#96;curl …</td></tr><tr><td><strong>日志查看</strong></td><td>参考官方「故障排除」章节（<code>ollama logs</code>）</td></tr><tr><td><strong>代理环境</strong></td><td>设置 <code>HTTPS_PROXY</code>（仅 HTTPS）并确保系统证书已安装</td></tr><tr><td><strong>对外暴露</strong></td><td>通过 <code>OLLAMA_HOST=0.0.0.0</code> 或使用 Nginx&#x2F;Ngrok 反向代理</td></tr><tr><td><strong>端口冲突</strong></td><td>修改 <code>OLLAMA_PORT</code> 环境变量后重启即可</td></tr><tr><td><strong>模型未加载</strong></td><td>检查 <code>ollama ps</code>，确认 GPU&#x2F;CPU 状态；若显存不足，考虑 <code>OLLAMA_KEEP_ALIVE</code> 或减小并发数</td></tr></tbody></table><hr><h2 id="9️⃣-社区-UI-与生态集成"><a href="#9️⃣-社区-UI-与生态集成" class="headerlink" title="9️⃣ 社区 UI 与生态集成"></a>9️⃣ 社区 UI 与生态集成</h2><table><thead><tr><th>项目</th><th>特色</th></tr></thead><tbody><tr><td><strong>Open WebUI</strong></td><td>多用户 Web UI，支持 Ollama、OpenAI、Claude 等后端</td></tr><tr><td><strong>CherryStudio</strong></td><td>完整的知识库、绘画、翻译等“一站式” AI 助手</td></tr><tr><td><strong>Page Assist</strong></td><td>浏览器插件，随时在网页上调出本地模型</td></tr><tr><td><strong>Ollama Python &#x2F; JS SDK</strong></td><td>直接在代码中调用，适配 FastAPI、Next.js 等框架</td></tr></tbody></table><blockquote><p>选用 UI 取决于使用场景：如果仅在终端玩模型，CLI 足矣；若需要多人协作或可视化对话，推荐 <strong>Open WebUI</strong>。</p></blockquote><hr><h1 id="🎉-小结"><a href="#🎉-小结" class="headerlink" title="🎉 小结"></a>🎉 小结</h1><ul><li><strong>一步到位</strong>：<code>curl … | sh</code> → <code>ollama run llama3.2</code>。  </li><li><strong>灵活配置</strong>：环境变量让你随意搬迁模型、暴露端口、调节并发。  </li><li><strong>GPU 与并发</strong>：<code>ollama ps</code> 检查显卡加载，<code>OLLAMA_NUM_PARALLEL</code> &#x2F; <code>OLLAMA_MAX_LOADED_MODELS</code> 控制资源。  </li><li><strong>自定义</strong>：通过 <code>Modelfile</code> 定制系统提示、参数、LoRA 适配器。  </li><li><strong>API &amp; SDK</strong>：REST 与官方 SDK 让模型轻松嵌入任意应用。</li></ul><p>现在，你已经拥有从 <strong>安装</strong>、<strong>配置</strong>、<strong>模型管理</strong> 到 <strong>API 调用</strong> 的完整知识链，快去本地跑通你的第一个大模型吧！ 🚀</p><hr><p><em>本文所有命令均已在最新的 Ollama 0.1.43（截至 2025‑11‑18）上测试通过，若有版本差异，请参考官方文档。</em></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;strong&gt;面向大模型入门用户&lt;/strong&gt; – 从零安装、环境变量配置到模型管理与 API 调用，一站式搞定。&lt;/p&gt;</summary>
    
    
    
    
    <category term="AI" scheme="https://szxiot.com/tags/AI/"/>
    
    <category term="AIGC" scheme="https://szxiot.com/tags/AIGC/"/>
    
    <category term="Ollama" scheme="https://szxiot.com/tags/Ollama/"/>
    
    <category term="LLMs" scheme="https://szxiot.com/tags/LLMs/"/>
    
  </entry>
  
  <entry>
    <title>告别无效提问：精选Prompt框架，让你的AI输出专业级成果</title>
    <link href="https://szxiot.com/2025/10/28/mastering-prompt-frameworks/"/>
    <id>https://szxiot.com/2025/10/28/mastering-prompt-frameworks/</id>
    <published>2025-10-28T02:48:29.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>还在为AI生成的内容空洞、跑题或完全不符合预期而烦恼吗？你不是一个人。与AI有效沟通的关键，在于掌握“提问的艺术”。而Prompt框架，正是将这门艺术系统化、科学化的终极武器。</p></blockquote><span id="more"></span><h2 id="0x00-为什么你需要Prompt框架？"><a href="#0x00-为什么你需要Prompt框架？" class="headerlink" title="0x00 为什么你需要Prompt框架？"></a>0x00 为什么你需要Prompt框架？</h2><p>想象一下，你是一位项目经理，需要AI帮你写一份项目计划书。如果你只是说：“写一份项目计划书”，AI可能会给你一份泛泛而谈、毫无用处的模板。</p><p>但如果你能清晰地告诉AI：</p><ul><li><strong>角色：</strong> 扮演一位资深的IT项目经理。</li><li><strong>目标：</strong> 为一款新的移动应用制定一个3个月的上市计划。</li><li><strong>背景：</strong> 团队有5人，预算有限，需要突出敏捷开发方法。</li><li><strong>要求：</strong> 包含目标、里程碑、风险分析和预算概算，以Markdown表格形式呈现。</li></ul><p>结果会如何？AI的输出将瞬间变得具体、专业且可直接使用。</p><p>这个例子背后，就隐含了一个简单的框架。<strong>Prompt框架是一套结构化的模板，它指导你如何组织指令，确保向AI传递完整、清晰且无歧义的信息。</strong> 它的核心价值在于：</p><ol><li><strong>提升效率：</strong> 减少来回修改和迭代的次数，一次生成高质量内容。</li><li><strong>确保完整性：</strong> 框架像一张清单，提醒你覆盖所有关键要素，避免遗漏。</li><li><strong>降低门槛：</strong> 即使你不是领域专家，也能通过框架引导AI产出专家级内容。</li><li><strong>结果可预测：</strong> 结构化的输入带来稳定、可预期的输出。</li></ol><p>接下来，我们将深入探讨几个备受推崇的精选Prompt框架，助你从AI新手秒变Prompt高手。</p><hr><h2 id="0x01-四大精选Prompt框架详解"><a href="#0x01-四大精选Prompt框架详解" class="headerlink" title="0x01 四大精选Prompt框架详解"></a>0x01 四大精选Prompt框架详解</h2><h3 id="框架一：CRISPE——全能型选手，最受推崇的框架之一"><a href="#框架一：CRISPE——全能型选手，最受推崇的框架之一" class="headerlink" title="框架一：CRISPE——全能型选手，最受推崇的框架之一"></a>框架一：CRISPE——全能型选手，最受推崇的框架之一</h3><p>CRISPE框架非常全面，尤其适合处理复杂任务。它由六个核心维度构成：</p><ul><li><strong>C - Capacity and Role (能力与角色)：</strong> 你希望AI扮演什么角色？（例如：一位资深的数据科学家、一位风趣的营销文案写手、一位严格的语法老师）</li><li><strong>R - Result (结果)：</strong> 你希望最终达成什么目标？请具体描述理想的输出。（例如：生成一份包含5个要点的清单、写一篇1000字的博文、输出一段可运行的Python代码）</li><li><strong>I - Intent (意图)：</strong> 你为什么需要这个结果？你的深层目的是什么？（例如：是为了教育小白用户、是为了做一个市场分析报告、是为了调试一段程序）</li><li><strong>S - Steps (步骤)：</strong> 为实现结果，需要遵循哪些具体的步骤？（这一步是可选的，但对于复杂任务至关重要）</li><li><strong>P - Personalization (个性化)：</strong> 你希望输出的风格、语调或格式是怎样的？（例如：正式、幽默、简洁；以Markdown格式输出；使用比喻和例子）</li><li><strong>E - Experiment (实验)：</strong> 如果对初次结果不满意，如何改进？邀请AI提供变体或征求反馈。</li></ul><p><strong>CRISPE实战示例：</strong></p><blockquote><p><strong>【角色】</strong> 你是一名经验丰富的健康营养师。<br><strong>【结果】</strong> 为我制定一份为期一周的、适合素食者的减脂午餐食谱清单。<br><strong>【意图】</strong> 这份食谱需要简单易做，食材容易购买，目标是帮助忙碌的上班族健康瘦身。<br><strong>【步骤】</strong> 请按以下步骤提供：1. 列出7天的午餐食谱名称。2. 为每一道菜提供详细的食材清单和烹饪步骤。3. 标注每餐的预估卡路里。<br><strong>【个性化】</strong> 语言风格请保持鼓励和亲切，最后用一句励志名言结尾。<br><strong>【实验】</strong> 如果你能同时提供一些替换食材的建议，以备不时之需，那将非常棒。</p></blockquote><h3 id="框架二：BROKE——谈判专家与需求澄清利器"><a href="#框架二：BROKE——谈判专家与需求澄清利器" class="headerlink" title="框架二：BROKE——谈判专家与需求澄清利器"></a>框架二：BROKE——谈判专家与需求澄清利器</h3><p>BROKE框架模拟了一种“谈判”或“需求确认”的过程，非常适合在项目开始前与AI对齐目标，确保双方理解一致。</p><ul><li><strong>B - Background (背景)：</strong> 提供所有相关的背景信息。发生了什么事？现状如何？</li><li><strong>R - Request (请求)：</strong> 清晰、直接地提出你的核心要求。</li><li><strong>O - Outcome (成果)：</strong> 描述你期望的最终成果是什么样子。成功的标准是什么？</li><li><strong>K - Key Information (关键信息)：</strong> 列出任何限制条件、必须包含的要素或需要避免的坑。</li><li><strong>E - Evaluation (评估)：</strong> 询问AI是否理解任务，或者让它提出改进建议。</li></ul><p><strong>BROKE实战示例：</strong></p><blockquote><p><strong>【背景】</strong> 我们团队正在开发一个面向Z世代的社交APP，主打“兴趣社交”。目前产品即将进入市场推广阶段。<br><strong>【请求】</strong> 为我们构思3个核心营销口号。<br><strong>【成果】</strong> 口号需要朗朗上口，能瞬间抓住Z世代的注意力，并能传达“找到同好”的核心价值。<br><strong>【关键信息】</strong> 口号长度不超过10个字，避免使用过时的网络用语。需要考虑到不同性别和文化背景的包容性。<br><strong>【评估】</strong> 请根据以上信息，确认你是否理解任务，并在给出口号后，简要解释每个口号的创意出发点。</p></blockquote><h3 id="框架三：RTF——简洁高效的指令核心"><a href="#框架三：RTF——简洁高效的指令核心" class="headerlink" title="框架三：RTF——简洁高效的指令核心"></a>框架三：RTF——简洁高效的指令核心</h3><p>如果你追求速度和简洁，RTF框架是最佳选择。它抓住了有效Prompt最核心的三个要素。</p><ul><li><strong>R - Role (角色)：</strong> 指定AI扮演的角色。</li><li><strong>T - Task (任务)：</strong> 明确需要完成的具体任务。</li><li><strong>F - Format (格式)：</strong> 明确要求输出的格式。</li></ul><p><strong>RTF实战示例：</strong></p><blockquote><p><strong>【角色】</strong> 你是一位金融分析师。<br><strong>【任务】</strong> 总结特斯拉(TSLA)在2023年第二季度最主要的三个财务亮点和两个潜在风险。<br><strong>【格式】</strong> 用项目符号列表呈现，最后附上一个简单的SWOT分析表格。</p></blockquote><h3 id="框架四：TAG——内容创作的黄金圈法则"><a href="#框架四：TAG——内容创作的黄金圈法则" class="headerlink" title="框架四：TAG——内容创作的黄金圈法则"></a>框架四：TAG——内容创作的黄金圈法则</h3><p>TAG框架源于经典的“黄金圈”理论，从内到外（Why -&gt; How -&gt; What）思考，特别适合内容创作、故事编写和战略规划。</p><ul><li><strong>T - Task (任务)：</strong> 最终要交付的具体产出是什么？（例如：写一个故事、设计一个方案）</li><li><strong>A - Action (行动)：</strong> 为了实现任务，需要采取哪些关键行动或步骤？（例如：先构思人物，再设计冲突，最后写结局）</li><li><strong>G - Goal (目标)：</strong> 你最终想达成的深层目标或影响是什么？（例如：让读者感受到希望、说服客户购买产品）</li></ul><p><strong>TAG实战示例：</strong></p><blockquote><p><strong>【目标】</strong> 创作一个能激发小学生对天文学兴趣的短篇科幻故事。<br><strong>【行动】</strong> 故事需要：1. 以一个孩子的好奇心为起点。2. 包含一个关于黑洞的奇妙想象。3. 结尾要温暖并留有悬念。<br><strong>【任务】</strong> 写一篇800字左右的短篇故事。</p></blockquote><hr><h2 id="0x02-如何选择与组合使用这些框架？"><a href="#0x02-如何选择与组合使用这些框架？" class="headerlink" title="0x02 如何选择与组合使用这些框架？"></a>0x02 如何选择与组合使用这些框架？</h2><p>没有哪个框架是万能的。聪明的做法是根据任务类型灵活选择和组合。</p><ul><li><strong>日常简单任务：</strong> 使用 <strong>RTF</strong>，快速直接。</li><li><strong>内容创作与复杂任务：</strong> 使用 <strong>CRISPE</strong> 或 <strong>TAG</strong>，确保深度和创意。</li><li><strong>项目启动与需求对齐：</strong> 使用 <strong>BROKE</strong>，像与合作伙伴一样与AI沟通。</li><li><strong>组合使用：</strong> 你可以用 <strong>BROKE</strong> 来确认需求，然后用 <strong>CRISPE</strong> 来执行具体的创作任务。例如，先和AI用BROKE框架“开个会”，明确需求后，再说：“好的，现在请按照CRISPE框架，以[角色]的身份，开始[任务]…”</li></ul><h2 id="0x03-实战演练：用CRISPE框架写一篇博文"><a href="#0x03-实战演练：用CRISPE框架写一篇博文" class="headerlink" title="0x03 实战演练：用CRISPE框架写一篇博文"></a>0x03 实战演练：用CRISPE框架写一篇博文</h2><p><strong>任务：</strong> 使用AI为一家新开的精品咖啡店写一篇微信公众号推广文章。</p><p><strong>完整Prompt如下：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">【Capacity and Role】 请你扮演一位资深美食博主和咖啡爱好者，文笔细腻且富有感染力。</span><br><span class="line"></span><br><span class="line">【Result】 输出一篇约1200字的微信公众号文章，旨在推广一家新开的名为“隅间咖啡”的精品咖啡店。文章需要有一个吸引人的标题和3个小标题，内容要能引发读者的共鸣和探店欲望。</span><br><span class="line"></span><br><span class="line">【Intent】 这篇文章的目的是为新店引流，建立品牌初期的好感和知名度，而不仅仅是提供信息。</span><br><span class="line"></span><br><span class="line">【Steps】</span><br><span class="line">1.  首先，从一个具体的生活场景或感受切入，引出对一家“理想咖啡店”的渴望。</span><br><span class="line">2.  然后，自然地引入“隅间咖啡”，介绍它的地理位置和外观氛围。</span><br><span class="line">3.  重点描述店内的特色：例如，店主对咖啡豆的严选、独特的手冲工艺、一款招牌产品（如“桂花拿铁”）。</span><br><span class="line">4.  分享一个关于店主开店初心的小故事，增加人情味。</span><br><span class="line">5.  最后，给出店铺的详细信息（地址、营业时间）并以一个温暖的邀请结尾。</span><br><span class="line"></span><br><span class="line">【Personalization】 语言风格要求温暖、治愈、有画面感，像在和朋友分享一个秘密基地。避免使用过于商业化的词汇。在文章适当位置，提示可以插入图片（用[图：描述]表示）。</span><br><span class="line"></span><br><span class="line">【Experiment】 请为这篇文章提供两个不同风格的标题备选。</span><br></pre></td></tr></table></figure><p>通过这个结构化的指令，AI生成的文章会远超一句简单的“写一篇推广隅间咖啡店的公众号文章”。</p><h2 id="0x04-总结与进阶技巧"><a href="#0x04-总结与进阶技巧" class="headerlink" title="0x04 总结与进阶技巧"></a>0x04 总结与进阶技巧</h2><p>掌握Prompt框架，意味着你从“随机提问”进入了“结构化沟通”的新阶段。记住这几个核心心法：</p><ol><li><strong>先模仿，后创造：</strong> 熟练掌握1-2个框架，内化成你的思维习惯。</li><li><strong>迭代优化：</strong> 没有一个Prompt是完美的。如果结果不理想，分析是框架中哪个环节没到位，然后修改再试。</li><li><strong>提供上下文：</strong> 背景和信息越多，AI的理解越深，输出质量越高。</li><li><strong>善用“继续”：</strong> 对于长文生成，如果AI中途停止，简单地输入“继续”或“请完成它”即可。</li></ol><p>现在，就打开你的AI工具，选择一个你感兴趣的任务，尝试用上面的任何一个框架来重新构建你的Prompt吧。你会发现，一个精心设计的提问，带来的回报是惊人的。</p>]]></content>
    
    
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;还在为AI生成的内容空洞、跑题或完全不符合预期而烦恼吗？你不是一个人。与AI有效沟通的关键，在于掌握“提问的艺术”。而Prompt框架，正是将这门艺术系统化、科学化的终极武器。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    
    <category term="Prompt" scheme="https://szxiot.com/tags/Prompt/"/>
    
    <category term="AI" scheme="https://szxiot.com/tags/AI/"/>
    
    <category term="AIGC" scheme="https://szxiot.com/tags/AIGC/"/>
    
  </entry>
  
  <entry>
    <title>媒体库方案指南(MediaSync+Media302简明教程)</title>
    <link href="https://szxiot.com/2024/10/25/media320-mediasync/"/>
    <id>https://szxiot.com/2024/10/25/media320-mediasync/</id>
    <published>2024-10-25T01:45:13.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p>伴随MediaSync新版本的发布和逐步稳定,抽时间补充一下文档,方便需要的用户作为参考,内容相对简单,但是把核心配置的地方都讲到了.</p><span id="more"></span><h2 id="0x00-相关镜像"><a href="#0x00-相关镜像" class="headerlink" title="0x00 相关镜像"></a>0x00 相关镜像</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ilovn/media_sync</span><br><span class="line">ilovn/media302</span><br><span class="line">ilovn/115upload # 非必需,主要用来在远端上传资源用,可以用其他工具替代(实时性降低)</span><br></pre></td></tr></table></figure><p>不管你部署在哪里,首先确保你能随时获取到这几个镜像的更新.</p><h2 id="0x01-授权问题"><a href="#0x01-授权问题" class="headerlink" title="0x01 授权问题"></a>0x01 授权问题</h2><p>因之前media302被小黄鱼上商家滥用,目前3个镜像均需要获取授权后才能正常使用,谢谢合作.授权获取: <a href="https://t.me/MediaLicenseBot">https://t.me/MediaLicenseBot</a></p><h2 id="0x02-部署"><a href="#0x02-部署" class="headerlink" title="0x02 部署"></a>0x02 部署</h2><h3 id="0x021-部署MediaSync"><a href="#0x021-部署MediaSync" class="headerlink" title="0x021 部署MediaSync"></a>0x021 部署MediaSync</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p /data/mediasync &amp;&amp; \</span><br><span class="line">docker pull ilovn/media_sync:latest &amp;&amp; \</span><br><span class="line">docker run -d -t --restart always \</span><br><span class="line">-v /data/mediasync:/usr/src/app/config \</span><br><span class="line">-v /mnt:/mnt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e PUID=1000 \</span><br><span class="line">-e PGID=1000 \</span><br><span class="line">-e License=&quot;从授权机器人处获取的MediaSync授权密钥&quot; \</span><br><span class="line">-p 8100:8100 \</span><br><span class="line">--name mediasync \</span><br><span class="line">ilovn/media_sync:latest</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">docker logs -f --tail 200 mediasync</span><br></pre></td></tr></table></figure><h3 id="0x022-部署Media302"><a href="#0x022-部署Media302" class="headerlink" title="0x022 部署Media302"></a>0x022 部署Media302</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media302:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">-e EMBY_TOKEN=&quot;d8c8a307cb7*******a3a6941f4c3&quot; \</span><br><span class="line">-e UPSTREAM_115_SERVER=&quot;http://172.17.0.1:8100/115&quot; \</span><br><span class="line">-e REPLACE_PATH_1=&quot;/mnt/strm/Media&quot; \</span><br><span class="line">-e REPLACE_PATH_2=&quot;/Media&quot; \</span><br><span class="line">-e License=&quot;从授权机器人处获取的Media302授权密钥&quot; \</span><br><span class="line">--name media302 \</span><br><span class="line">-p 8090:8090 \</span><br><span class="line">ilovn/media302:latest</span><br><span class="line"></span><br><span class="line">docker logs -f --tail 200 media302</span><br></pre></td></tr></table></figure><h3 id="0x023-部署115Upload"><a href="#0x023-部署115Upload" class="headerlink" title="0x023 部署115Upload"></a>0x023 部署115Upload</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/115upload:latest &amp;&amp; \</span><br><span class="line">docker run -d -t --restart always \</span><br><span class="line">-v /home/cat/115-cat-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /mnt:/mnt \</span><br><span class="line">-e SRC_PATH=&quot;/mnt/AutoLink&quot; \</span><br><span class="line">-e DST_PATH=&quot;/Media&quot; \</span><br><span class="line">-e MAX_WORKERS=4 \</span><br><span class="line">-e INTERVAL=60 \</span><br><span class="line">-e USE_API=&quot;true&quot; \</span><br><span class="line">-e API_SERVER=&quot;http://172.17.0.1:8100/api/receive&quot; \</span><br><span class="line">-e Access_Token=&quot;xxx-xxx-xxx&quot; \</span><br><span class="line">-e License=&quot;从授权机器人处获取的115Upload授权密钥&quot; \</span><br><span class="line">--dns=223.5.5.5 \</span><br><span class="line">--log-driver=local \</span><br><span class="line">--name 115upload \</span><br><span class="line">ilovn/115upload:latest</span><br><span class="line"></span><br><span class="line">docker logs -f --tail 200 115upload</span><br></pre></td></tr></table></figure><h2 id="0x03-简单配置说明"><a href="#0x03-简单配置说明" class="headerlink" title="0x03 简单配置说明"></a>0x03 简单配置说明</h2><p><strong>MediaSync</strong>是有配置界面的,部署成功后,访问IP:8100登录即可,默认用户名admin,默认密码root</p><p>首次进入会要求完成初始化配置,请按照界面要求完成即可,完成后可以手动执行strm生成或在设置中设置定时任务.</p><p>MediaSync配置完成,并切正常生成strm后,建议重启一次MediaSync.</p><p>将你的emby媒体库指向MediaSync生成的文件目录,扫描并确认emby可以播放后,准备配置Media302.</p><p><strong>Media302</strong>常规使用的话,请不要配置emby_token参数,如需图片302,可使用MediaSync的302服务<code>IP:8100/115</code></p><h2 id="0x04-后话"><a href="#0x04-后话" class="headerlink" title="0x04 后话"></a>0x04 后话</h2><p>当前方案不涉及Clouddrive(cd2)以及alist等工具,目前正常使用也不会有类似扫库429问题,如果动手能力弱,可以在获取授权后联系我,支持收费协助部署.</p><h2 id="0x05效果图"><a href="#0x05效果图" class="headerlink" title="0x05效果图"></a>0x05效果图</h2><video src="https://s.cat.gd/2024/10/2f1bdd9da20bad0ebadc5250129f9039.MP4" autoplay="autoplay" loop="loop"/>]]></content>
    
    
    <summary type="html">&lt;p&gt;伴随MediaSync新版本的发布和逐步稳定,抽时间补充一下文档,方便需要的用户作为参考,内容相对简单,但是把核心配置的地方都讲到了.&lt;/p&gt;</summary>
    
    
    
    
    <category term="Alist" scheme="https://szxiot.com/tags/Alist/"/>
    
    <category term="emby" scheme="https://szxiot.com/tags/emby/"/>
    
    <category term="115" scheme="https://szxiot.com/tags/115/"/>
    
    <category term="302" scheme="https://szxiot.com/tags/302/"/>
    
    <category term="Clouddrive" scheme="https://szxiot.com/tags/Clouddrive/"/>
    
  </entry>
  
  <entry>
    <title>MediaSync新版本</title>
    <link href="https://szxiot.com/2024/10/12/media-sync/"/>
    <id>https://szxiot.com/2024/10/12/media-sync/</id>
    <published>2024-10-12T09:28:52.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p>新版本带了建议界面,方便配置和修改,降低使用门槛,搭配之前的media302和115Upload,基本上就不需要cd2,alist等工具了.</p><span id="more"></span><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>docker安装</p><ul><li><code>-v /data/mediasync:/usr/src/app/config</code>用于设置配置目录映射</li><li><code>/mnt:/mnt</code>主要用于映射strm生成</li><li><code>-v /etc/timezone:/etc/timezone:ro</code> 和<code>-v /etc/localtime:/etc/localtime:ro</code>用于docker和宿主机同步时区,非必需</li><li><code>-e PUID=1000</code>和<code>-e PGID=1000</code>用于设置docker用户</li><li><code>-e License=&quot;Your License&quot;</code>配置你的授权密钥</li><li><code>-p 8100:8100</code>端口映射,如需修改,只需将第一个8100改为你想要的端口即可</li></ul><p>启动后,通过你的ip:8100即可访问,默认登录用户admin密码root</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media_sync:latest &amp;&amp; \</span><br><span class="line"></span><br><span class="line">docker run -d --restart always \</span><br><span class="line">-v /data/mediasync:/usr/src/app/config \</span><br><span class="line">-v /mnt:/mnt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e PUID=1000 \</span><br><span class="line">-e PGID=1000 \</span><br><span class="line">-e License=&quot;Your License&quot; \</span><br><span class="line">-p 8100:8100 \</span><br><span class="line">--name mediasync \</span><br><span class="line">ilovn/media_sync:latest</span><br></pre></td></tr></table></figure><h2 id="初始化设置"><a href="#初始化设置" class="headerlink" title="初始化设置"></a>初始化设置</h2><h3 id="扫码或提供Cookie字符串设置账户"><a href="#扫码或提供Cookie字符串设置账户" class="headerlink" title="扫码或提供Cookie字符串设置账户"></a>扫码或提供Cookie字符串设置账户</h3><p><img src="https://s.cat.gd/2024/10/a29a2a43dadac038e758082585b7db64.png" alt="image-20241012164111980"  / loading="lazy"><img src="https://s.cat.gd/2024/10/881f43e304d3dbd3e5f4286abd0f6d52.png" alt="image-20241012164203774"  / loading="lazy"></p><h3 id="设置同步目录"><a href="#设置同步目录" class="headerlink" title="设置同步目录"></a>设置同步目录</h3><ul><li><p>可以通过点击<code>添加目录</code>增加更多目录,生成strm都会保存到输出目录中.</p></li><li><p>Token是配合115Upload上传使用的,115Upload使用</p><p><code>-e API_SERVER=&quot;http://172.17.0.1:8100/api/receive&quot; \</code></p><p><code>-e Access_Token=&quot;your token&quot; \</code></p></li><li><p>服务地址是strm文件生成的时候的链接地址,搭配media302的后端,可以直接填写对应的地址,比如:<code>http://172.17.0.1:8091</code>注意地址最后不要带<code>/</code></p></li><li><p>输出目录是保存strm的路径,记得把你的路径挂载到docker容器,这里会校验能不能写入目录</p></li><li><p>路径替换是可选项,用于一些定制场景,比如你的网盘路径是<code>/Media/Movies/XXXX</code>,你觉得加上strm保存路径<code>/mnt/strm</code>后的<code>/mnt/strm/Media/Movies/XXXX</code>太长,可以通过<code>/Media/:/</code>替换掉<code>/Media/</code>为<code>/</code>,实际输出路径为<code>/mnt/strm/Movies/XXXX</code>,注意路径替换是基于<code>:</code>分割</p></li></ul><img src="https://s.cat.gd/2024/10/01bfcbb41727bc84ad33579327c12c6c.png" alt="image-20241012164424123"  / loading="lazy"><h3 id="设置strm参数"><a href="#设置strm参数" class="headerlink" title="设置strm参数"></a>设置strm参数</h3><p>根据自己的需要设置即可,</p><p>以上一步设置的服务地址为<code>http://172.17.0.1:8091</code>为例:</p><h4 id="开启短链"><a href="#开启短链" class="headerlink" title="开启短链"></a>开启短链</h4><p>包含pickcode:<code>http://172.17.0.1:8091/一人之下 - S01E01.mkv?pickcode=e0lx8xxxxxxxx</code></p><p>包含sha1: <code>http://172.17.0.1:8091/一人之下 - S01E01.mkv?pickcode=e0lx8xxxxxxxx&amp;sha1=D0BCFFE9E91D0E35B2F67F7646A3EDF6FFDCE80E</code></p><p>包含path:<code>http://172.17.0.1:8091/一人之下 - S01E01.mkv?pickcode=e0lx8&amp;sha1=D0BCFFE9E91D0E35B2F67F7646A3EDF6FFDCE80E&amp;path=/Media/Animes/国漫/一人之下/S01/一人之下 - S01E01.mkv</code></p><h4 id="关闭短链"><a href="#关闭短链" class="headerlink" title="关闭短链"></a>关闭短链</h4><p>包含pickcode:<code>http://172.17.0.1:8091/Media/Animes/国漫/一人之下/S01/一人之下 - S01E01.mkv?pickcode=e0lx8xxxxxxxx</code></p><p>包含sha1: <code>http://172.17.0.1:8091/Media/Animes/国漫/一人之下/S01/一人之下 - S01E01.mkv?pickcode=e0lx8xxxxxxxx&amp;sha1=D0BCFFE9E91D0E35B2F67F7646A3EDF6FFDCE80E</code></p><p>包含path:<code>http://172.17.0.1:8091/Media/Animes/国漫/一人之下/S01/一人之下 - S01E01.mkv?pickcode=e0lx8&amp;sha1=D0BCFFE9E91D0E35B2F67F7646A3EDF6FFDCE80E&amp;path=/Media/Animes/国漫/一人之下/S01/一人之下 - S01E01.mkv</code></p><img src="https://s.cat.gd/2024/10/a85f56126b361a4c3a3c5db9e4c7425e.png" alt="image-20241012165438005"  / loading="lazy"><h3 id="设置emby通知"><a href="#设置emby通知" class="headerlink" title="设置emby通知"></a>设置emby通知</h3><p>设置是否开启emby刷新通知.</p><ul><li>Emby地址:emby的服务地址</li><li>API Token:emby的api token</li><li>路径替换:用于strm本地路径与emby路径不一致的情况,主要是考虑到当前容器的挂载和emby容器挂载路径不一致的情况.路径替换以<code>:</code>分割,路径是容器内路径为基础,不要随便挂乱七八糟的路径,除非你理解自己的动作</li></ul><img src="https://s.cat.gd/2024/10/306718e6dfdfa81aaab351c728ae9925.png" alt="image-20241012170348654"  / loading="lazy"><h2 id="设置定时任务"><a href="#设置定时任务" class="headerlink" title="设置定时任务"></a>设置定时任务</h2><ul><li><p>初始化配置完成后,服务已经能够正常接受115Upload的上传通知实现局部更新了.</p></li><li><p>为了首次使用,可以选择主页的意见生成功能实现初始数据落地,这里耗时可能比较长,请耐心等待或者关注容器日志.</p></li><li><p>定时任务会按照设置,定时刷新初始化设置里面的目录,如果目录数据量极大(单文件夹10万文件内最佳),建议分为多个目录使用,效率提升会很明显</p><p><img src="https://s.cat.gd/2024/10/68f001322340eca85ff0601528869f64.png" alt="image-20241012171024622"  / loading="lazy"><img src="https://s.cat.gd/2024/10/5318dc6e9cef4dc0cc036cae799227e4.png" alt="image-20241012171057746"  / loading="lazy"></p></li></ul><h2 id="首页"><a href="#首页" class="headerlink" title="首页"></a>首页</h2><p>可以手动执行具体的刷新任务.</p><img src="https://s.cat.gd/2024/10/f0f983ea6fdb4c4a6aac2b0ae8562e41.png" alt="image-20241012172623301"  / loading="lazy">]]></content>
    
    
    <summary type="html">&lt;p&gt;新版本带了建议界面,方便配置和修改,降低使用门槛,搭配之前的media302和115Upload,基本上就不需要cd2,alist等工具了.&lt;/p&gt;</summary>
    
    
    
    
    <category term="115" scheme="https://szxiot.com/tags/115/"/>
    
    <category term="strm" scheme="https://szxiot.com/tags/strm/"/>
    
    <category term="302" scheme="https://szxiot.com/tags/302/"/>
    
    <category term="media302" scheme="https://szxiot.com/tags/media302/"/>
    
    <category term="python-115" scheme="https://szxiot.com/tags/python-115/"/>
    
    <category term="alist" scheme="https://szxiot.com/tags/alist/"/>
    
    <category term="cd2" scheme="https://szxiot.com/tags/cd2/"/>
    
  </entry>
  
  <entry>
    <title>家庭媒体库方案:方案整理汇总(更新时间:2024-08-23)</title>
    <link href="https://szxiot.com/2024/08/23/strm-media-302-emby-3/"/>
    <id>https://szxiot.com/2024/08/23/strm-media-302-emby-3/</id>
    <published>2024-08-23T01:12:03.000Z</published>
    <updated>2026-07-07T14:06:47.266Z</updated>
    
    <content type="html"><![CDATA[<p>这是一篇水文?其实不是,上传+115生活日志监控实现增量入库这个事情,有朋友测试后发现,还是会有遗漏,痛定思痛,我决定把上传通知做了.</p><span id="more"></span><h2 id="0x00-现状"><a href="#0x00-现状" class="headerlink" title="0x00 现状"></a>0x00 现状</h2><p>目前构建了3个docker镜像,分别对应文件上传、生成strm、302播放(含图片302):</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ilovn/115upload</span><br><span class="line">ilovn/media_library_sync</span><br><span class="line">ilovn/media302</span><br></pre></td></tr></table></figure><h2 id="0x01-建议方案"><a href="#0x01-建议方案" class="headerlink" title="0x01 建议方案"></a>0x01 建议方案</h2><p>之所以会有所谓的建议方案,主要是很多人其实不理解到底要做什么?如果你仅仅需要一个工具,把你现在已经是alist后端,生成了strm的emby在302上发挥作用,那么下面这几行命令就是你需要的:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media302:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">--name media302 \</span><br><span class="line">-p 8090:8090 \</span><br><span class="line">ilovn/media302:latest</span><br></pre></td></tr></table></figure><p>其中,<code>UPSTREAM_HOST</code>是你的emby服务器,确保media302所在的环境能访问到即可,然后在你的客户端、网页用media302所在的ip和8090端口访问,你的302就可用了.</p><p>注意,cd2本身不支持302访问,所以你的strm里面的地址,请认真检查是http&#x2F;https开头,并确保是类似alist这种支持302的服务提供的.</p><p>总有些人在啥都不懂的情况下,看了后面的方案开始BB,要cookie、要配置很多,拜托,你的需求是什么自己想清楚了就瞎BB,爱用不用.</p><h2 id="0x02-media302完整方案"><a href="#0x02-media302完整方案" class="headerlink" title="0x02 media302完整方案"></a>0x02 media302完整方案</h2><p>之前有网友联系,即使是小白,其实也可以很快配置出来,而且,提供cookie后,media302能给你提供一个直接可用的302服务端,这也是为什么说可以抛弃alist的原因.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media302:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-v /data/115/115-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">-e EMBY_TOKEN=&quot;emby token&quot; \</span><br><span class="line">-e UPSTREAM_115_SERVER=&quot;http://127.0.0.1:8091&quot; \</span><br><span class="line">-e REPLACE_PATH_1=&quot;/mnt/strm&quot; \</span><br><span class="line">-e REPLACE_PATH_2=&quot;/Media&quot; \</span><br><span class="line">--name media302 \</span><br><span class="line">-p 8090:8090 \</span><br><span class="line">-p 8091:8091 \</span><br><span class="line">ilovn/media302:latest</span><br></pre></td></tr></table></figure><p>详细使用,可以参考<a href="/2024/07/27/clouddrive2-alist-strm-302-emby-6/" title="家庭媒体库方案(六):302方案(图片302优化方案,含后端)">家庭媒体库方案(六):302方案(图片302优化方案,含后端)</a></p><p>同时有了这个服务端,可以通过caddy这类工具,把这个服务暴露出来:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">xxx.xxx.xxx &#123;</span><br><span class="line">  handle_path /d/115/* &#123;</span><br><span class="line">        reverse_proxy http://127.0.0.1:8091</span><br><span class="line">  &#125;</span><br><span class="line">  handle_path /static/* &#123;</span><br><span class="line">        reverse_proxy http://127.0.0.1:8091</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="0x03-文件上传"><a href="#0x03-文件上传" class="headerlink" title="0x03 文件上传"></a>0x03 文件上传</h2><p>这个镜像很简单,就是纯粹的上传,上传并发、上传后删除文件等,都是可配置的:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/115upload:latest &amp;&amp; \</span><br><span class="line">docker run -d -t --restart always \</span><br><span class="line">-v /home/cat/115-cat-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-v /mnt:/mnt \</span><br><span class="line">-e SRC_PATH=&quot;/mnt/AutoLink&quot; \</span><br><span class="line">-e DST_PATH=&quot;/Media&quot; \</span><br><span class="line">-e MAX_WORKERS=3 \</span><br><span class="line">-e INTERVAL=60 \</span><br><span class="line">-e USE_API=&quot;true&quot; \</span><br><span class="line">-e API_SERVER=&quot;http://xxx.xxx.xxx:8092/api/receive&quot; \</span><br><span class="line">-e Access_Token=&quot;your token haha&quot; \</span><br><span class="line">--log-driver=syslog \</span><br><span class="line">--name 115upload \</span><br><span class="line">ilovn/115upload:latest</span><br></pre></td></tr></table></figure><p>补充说明一下,-t参数,才能让你在docker的log看到上传进度. <code>API_SERVER</code>指向下一步的生成strm的容器,后面的<code>/api/receive</code>不能修改,记得自定义一个<code>Access_Token</code>,两个容器要一样才能工作.</p><h2 id="0x04-生成strm"><a href="#0x04-生成strm" class="headerlink" title="0x04 生成strm"></a>0x04 生成strm</h2><p>这个方案目前基本稳定,我自己在用,有问题也会处理. 详细可参考:<a href="/2024/08/01/strm-media-302-emby/" title="家庭媒体库方案(七):媒体库管理和更新方案">家庭媒体库方案(七):媒体库管理和更新方案</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">sudo docker pull ilovn/media_library_sync:latest &amp;&amp; \</span><br><span class="line">sudo docker run -d --restart always \</span><br><span class="line">-v /data/medialibsync/115-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /data/medialibsync/db:/usr/src/app/db \</span><br><span class="line">-v /mnt:/mnt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e PUID=1000 \</span><br><span class="line">-e PGID=1000 \</span><br><span class="line">-e FILE_SITE=&quot;https://xxx.xxx.xxx/static&quot; \</span><br><span class="line">-e EMBY_SITE=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">-e EMBY_TOKEN=&quot;emby token&quot; \</span><br><span class="line">-e STRM_DIR=&quot;/mnt/strm&quot; \</span><br><span class="line">-e REPLACE_STRM_PATH=&quot;/Media&quot; \</span><br><span class="line">-e OVERWRITE=&quot;false&quot; \</span><br><span class="line">-e NEED_NFO=&quot;true&quot; \</span><br><span class="line">-e NEED_IMAGE=&quot;false&quot; \</span><br><span class="line">-e JOB_INTERVAL=&quot;5&quot; \</span><br><span class="line">-e INIT_QUICK_SCAN=&quot;true&quot; \</span><br><span class="line">-e SCAN_DIRS=&quot;/Media/Animes|/Media/Movies|/Media/TVShows&quot; \</span><br><span class="line">-e Access_Token=&quot;your token haha&quot; \</span><br><span class="line">-p 8092:8092 \</span><br><span class="line">--name medialibsync \</span><br><span class="line">ilovn/media_library_sync:latest</span><br></pre></td></tr></table></figure><p>增加了端口映射,作为上传的通知服务端.记得设置<code>Access_Token</code>,两个容器要一样才能工作.</p><h2 id="0x05-答疑"><a href="#0x05-答疑" class="headerlink" title="0x05 答疑"></a>0x05 答疑</h2><ol><li><p>为什么不整理成一个镜像?<br>  很简单, 专业的工具做专业的事情,同时也利于大家分散部署,比如你的PT下载可能是在欧洲,emby可能在国内或者香港、新加坡等,分散部署可以让工具聚焦自己的主力工作,上传的就专业做上传就行.同理,302可以部署在国内,提升302请求的响应速度.</p></li><li><p>media302用域名的时候,infuse不支持图片302<br>这是infuse的bug</p></li><li><p>media302支持strm和本地混合吗?<br>不支持,我没这诉求</p></li><li><p>media302会支持plex、jellyfin吗?<br>不搞了,没意思</p></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;这是一篇水文?其实不是,上传+115生活日志监控实现增量入库这个事情,有朋友测试后发现,还是会有遗漏,痛定思痛,我决定把上传通知做了.&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>家庭媒体库方案(八):媒体库方案整理汇总</title>
    <link href="https://szxiot.com/2024/08/20/strm-media-302-emby-2/"/>
    <id>https://szxiot.com/2024/08/20/strm-media-302-emby-2/</id>
    <published>2024-08-20T07:25:15.000Z</published>
    <updated>2026-07-07T14:06:47.266Z</updated>
    
    <content type="html"><![CDATA[<p>关于媒体库方案的内容,整理到现在,我觉得可以稍微总结一下了,也针对部分网友使用过程中遇到的问题,我也一并说明一下.</p><span id="more"></span><h2 id="0x00-现状"><a href="#0x00-现状" class="headerlink" title="0x00 现状"></a>0x00 现状</h2><p>目前构建了3个docker镜像,分别对应文件上传、生成strm、302播放(含图片302):</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ilovn/115upload</span><br><span class="line">ilovn/media_library_sync</span><br><span class="line">ilovn/media302</span><br></pre></td></tr></table></figure><h2 id="0x01-建议方案"><a href="#0x01-建议方案" class="headerlink" title="0x01 建议方案"></a>0x01 建议方案</h2><p>之所以会有所谓的建议方案,主要是很多人其实不理解到底要做什么?如果你仅仅需要一个工具,把你现在已经是alist后端,生成了strm的emby在302上发挥作用,那么下面这几行命令就是你需要的:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media302:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">--name media302 \</span><br><span class="line">-p 8090:8090 \</span><br><span class="line">ilovn/media302:latest</span><br></pre></td></tr></table></figure><p>其中,<code>UPSTREAM_HOST</code>是你的emby服务器,确保media302所在的环境能访问到即可,然后在你的客户端、网页用media302所在的ip和8090端口访问,你的302就可用了.</p><p>注意,cd2本身不支持302访问,所以你的strm里面的地址,请认真检查是http&#x2F;https开头,并确保是类似alist这种支持302的服务提供的.</p><p>总有些人在啥都不懂的情况下,看了后面的方案开始BB,要cookie、要配置很多,拜托,你的需求是什么自己想清楚了就瞎BB,爱用不用.</p><h2 id="0x02-media302完整方案"><a href="#0x02-media302完整方案" class="headerlink" title="0x02 media302完整方案"></a>0x02 media302完整方案</h2><p>之前有网友联系,即使是小白,其实也可以很快配置出来,而且,提供cookie后,media302能给你提供一个直接可用的302服务端,这也是为什么说可以抛弃alist的原因.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media302:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-v /data/115/115-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">-e EMBY_TOKEN=&quot;emby token&quot; \</span><br><span class="line">-e UPSTREAM_115_SERVER=&quot;http://127.0.0.1:8091&quot; \</span><br><span class="line">-e REPLACE_PATH_1=&quot;/mnt/strm&quot; \</span><br><span class="line">-e REPLACE_PATH_2=&quot;/Media&quot; \</span><br><span class="line">--name media302 \</span><br><span class="line">-p 8090:8090 \</span><br><span class="line">-p 8091:8091 \</span><br><span class="line">ilovn/media302:latest</span><br></pre></td></tr></table></figure><p>详细使用,可以参考<a href="/2024/07/27/clouddrive2-alist-strm-302-emby-6/" title="家庭媒体库方案(六):302方案(图片302优化方案,含后端)">家庭媒体库方案(六):302方案(图片302优化方案,含后端)</a></p><p>同时有了这个服务端,可以通过caddy这类工具,把这个服务暴露出来:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">xxx.xxx.xxx &#123;</span><br><span class="line">  handle_path /d/115/* &#123;</span><br><span class="line">        reverse_proxy http://127.0.0.1:8091</span><br><span class="line">  &#125;</span><br><span class="line">  handle_path /static/* &#123;</span><br><span class="line">        reverse_proxy http://127.0.0.1:8091</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="0x03-文件上传"><a href="#0x03-文件上传" class="headerlink" title="0x03 文件上传"></a>0x03 文件上传</h2><p>这个镜像很简单,就是纯粹的上传,上传并发、上传后删除文件等,都是可配置的:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/115upload:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-v /home/cat/115-cat-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-v /mnt:/mnt \</span><br><span class="line">-e SRC_PATH=&quot;/mnt/AutoLink&quot; \</span><br><span class="line">-e DST_PATH=&quot;/Media&quot; \</span><br><span class="line">-e MAX_WORKERS=3 \</span><br><span class="line">-e MAX_RETRIES=5 \</span><br><span class="line">-e INTERVAL=60 \</span><br><span class="line">-e REMOVE_DONE=&quot;true&quot; \</span><br><span class="line">--log-driver=syslog \</span><br><span class="line">--name 115upload \</span><br><span class="line">ilovn/115upload:latest</span><br></pre></td></tr></table></figure><h2 id="0x04-生成strm"><a href="#0x04-生成strm" class="headerlink" title="0x04 生成strm"></a>0x04 生成strm</h2><p>这个方案目前基本稳定,我自己在用,有问题也会处理. 详细可参考:<a href="/2024/08/01/strm-media-302-emby/" title="家庭媒体库方案(七):媒体库管理和更新方案">家庭媒体库方案(七):媒体库管理和更新方案</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">sudo docker pull ilovn/media_library_sync:latest &amp;&amp; \</span><br><span class="line">sudo docker run -d --restart always \</span><br><span class="line">-v /data/medialibsync/115-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /data/medialibsync/db:/usr/src/app/db \</span><br><span class="line">-v /mnt:/mnt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e PUID=1000 \</span><br><span class="line">-e PGID=1000 \</span><br><span class="line">-e FILE_SITE=&quot;https://xxx.xxx.xxx/static&quot; \</span><br><span class="line">-e EMBY_SITE=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">-e EMBY_TOKEN=&quot;emby token&quot; \</span><br><span class="line">-e STRM_DIR=&quot;/mnt/strm&quot; \</span><br><span class="line">-e REPLACE_STRM_PATH=&quot;/Media&quot; \</span><br><span class="line">-e OVERWRITE=&quot;false&quot; \</span><br><span class="line">-e NEED_NFO=&quot;true&quot; \</span><br><span class="line">-e NEED_IMAGE=&quot;false&quot; \</span><br><span class="line">-e JOB_INTERVAL=&quot;5&quot; \</span><br><span class="line">-e INIT_QUICK_SCAN=&quot;true&quot; \</span><br><span class="line">-e SCAN_DIRS=&quot;/Media/Animes|/Media/Movies|/Media/TVShows&quot; \</span><br><span class="line">--name medialibsync \</span><br><span class="line">ilovn/media_library_sync:latest</span><br></pre></td></tr></table></figure><h2 id="0x05-答疑"><a href="#0x05-答疑" class="headerlink" title="0x05 答疑"></a>0x05 答疑</h2><ol><li><p>为什么不整理成一个镜像?<br>  很简单, 专业的工具做专业的事情,同时也利于大家分散部署,比如你的PT下载可能是在欧洲,emby可能在国内或者香港、新加坡等,分散部署可以让工具聚焦自己的主力工作,上传的就专业做上传就行.同理,302可以部署在国内,提升302请求的响应速度.</p></li><li><p>media302用域名的时候,infuse不支持图片302<br>这是infuse的bug</p></li><li><p>media302支持strm和本地混合吗?<br>不支持,我没这诉求</p></li><li><p>media302会支持plex、jellyfin吗?<br>不搞了,没意思</p></li></ol>]]></content>
    
    
    <summary type="html">&lt;p&gt;关于媒体库方案的内容,整理到现在,我觉得可以稍微总结一下了,也针对部分网友使用过程中遇到的问题,我也一并说明一下.&lt;/p&gt;</summary>
    
    
    
    
    <category term="Alist" scheme="https://szxiot.com/tags/Alist/"/>
    
    <category term="WebDav" scheme="https://szxiot.com/tags/WebDav/"/>
    
    <category term="infuse" scheme="https://szxiot.com/tags/infuse/"/>
    
    <category term="emby" scheme="https://szxiot.com/tags/emby/"/>
    
    <category term="115" scheme="https://szxiot.com/tags/115/"/>
    
    <category term="阿里云盘" scheme="https://szxiot.com/tags/%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98/"/>
    
    <category term="strm" scheme="https://szxiot.com/tags/strm/"/>
    
    <category term="CloudDrive2" scheme="https://szxiot.com/tags/CloudDrive2/"/>
    
    <category term="302" scheme="https://szxiot.com/tags/302/"/>
    
    <category term="media302" scheme="https://szxiot.com/tags/media302/"/>
    
  </entry>
  
  <entry>
    <title>通过ssh远程切换Macos的屏幕共享</title>
    <link href="https://szxiot.com/2024/08/09/toggle-screen-sharing-for-macos-with-ssh/"/>
    <id>https://szxiot.com/2024/08/09/toggle-screen-sharing-for-macos-with-ssh/</id>
    <published>2024-08-09T07:54:35.000Z</published>
    <updated>2026-07-07T14:06:47.266Z</updated>
    
    <content type="html"><![CDATA[<p>家里的MacMini长期开机,跑了一些服务,通过远程桌面管理,近期发现有时候无法远程连接,但是ssh服务正常,尝试通过ssh来重启远程桌面服务,简单记录一下.</p><span id="more"></span><h2 id="执行命令"><a href="#执行命令" class="headerlink" title="执行命令"></a>执行命令</h2><p>通过ssh登录macos后,执行以下命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Enable Screen Sharing</span></span><br><span class="line">sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.screensharing.plist</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Disable Screen Sharing</span></span><br><span class="line">sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.screensharing.plist</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;家里的MacMini长期开机,跑了一些服务,通过远程桌面管理,近期发现有时候无法远程连接,但是ssh服务正常,尝试通过ssh来重启远程桌面服务,简单记录一下.&lt;/p&gt;</summary>
    
    
    
    
    <category term="ssh" scheme="https://szxiot.com/tags/ssh/"/>
    
    <category term="屏幕共享" scheme="https://szxiot.com/tags/%E5%B1%8F%E5%B9%95%E5%85%B1%E4%BA%AB/"/>
    
  </entry>
  
  <entry>
    <title>家庭媒体库方案(七):媒体库管理和更新方案</title>
    <link href="https://szxiot.com/2024/08/01/strm-media-302-emby/"/>
    <id>https://szxiot.com/2024/08/01/strm-media-302-emby/</id>
    <published>2024-08-01T12:39:15.000Z</published>
    <updated>2026-07-07T14:06:47.266Z</updated>
    
    <content type="html"><![CDATA[<p>严格来说,这不是之前方案的后续,考虑过很多种管理媒体资源的办法,都差强人意,要么节点多,依赖服务多,要么效果不太行.</p><span id="more"></span><h2 id="方案思路"><a href="#方案思路" class="headerlink" title="方案思路"></a>方案思路</h2><p>1、通过遍历媒体库资源,全部整理进入数据库;<br>2、监听115生活事件日志,实现增量数据入库;<br>3、通过数据库数据快速生成strm和元数据;</p><h2 id="特定依赖"><a href="#特定依赖" class="headerlink" title="特定依赖"></a>特定依赖</h2><p>之所以没把这个服务打包到media302,主要还是考虑302就专业做302该干的活,数据库的媒体库管理单独开来,这样能实现两个docker应用+emby,实现完整的管理和使用.所以,请把前一篇文章看完.<a href="/2024/07/27/clouddrive2-alist-strm-302-emby-6/" title="家庭媒体库方案(六):302方案(图片302优化方案,含后端)">家庭媒体库方案(六):302方案(图片302优化方案,含后端)</a></p><h2 id="动手部署"><a href="#动手部署" class="headerlink" title="动手部署"></a>动手部署</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media_library_sync:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-v /data/medialibsync/115-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /data/medialibsync/db:/usr/src/app/db \</span><br><span class="line">-v /mnt:/mnt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e PUID=1000 \</span><br><span class="line">-e PGID=1000 \</span><br><span class="line">-e FILE_SITE=&quot;生成strm的链接服务地址&quot; \</span><br><span class="line">-e EMBY_SITE=&quot;emby服务地址,用于通知strm生成,局部扫库&quot; \</span><br><span class="line">-e EMBY_TOKEN=&quot;emby token&quot; \</span><br><span class="line">-e STRM_DIR=&quot;strm生成的挂载地址&quot; \</span><br><span class="line">-e REPLACE_STRM_PATH=&quot;/Media(替换路径)&quot; \</span><br><span class="line">-e OVERWRITE=&quot;true是否覆盖已存在的文件&quot; \</span><br><span class="line">-e NEED_NFO=&quot;true是否生成nfo&quot; \</span><br><span class="line">-e NEED_IMAGE=&quot;false是否生成图片数据&quot; \</span><br><span class="line">-e JOB_INTERVAL=&quot;5 任务间隔时间,分钟&quot; \</span><br><span class="line">-e SCAN_DIRS=&quot;/Media/Animes|/Media/Movies  预期扫描的路径,|分割&quot; \</span><br><span class="line">--name medialibsync \</span><br><span class="line">ilovn/media_library_sync:latest</span><br></pre></td></tr></table></figure><h2 id="问题交流"><a href="#问题交流" class="headerlink" title="问题交流"></a>问题交流</h2><p>目前已经基本可用,bug肯定会有,留个联系频道吧,如果有需要的话,戳<a href="https://t.me/media_302">这里</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;严格来说,这不是之前方案的后续,考虑过很多种管理媒体资源的办法,都差强人意,要么节点多,依赖服务多,要么效果不太行.&lt;/p&gt;</summary>
    
    
    
    
    <category term="infuse" scheme="https://szxiot.com/tags/infuse/"/>
    
    <category term="emby" scheme="https://szxiot.com/tags/emby/"/>
    
    <category term="115" scheme="https://szxiot.com/tags/115/"/>
    
    <category term="302" scheme="https://szxiot.com/tags/302/"/>
    
    <category term="media302" scheme="https://szxiot.com/tags/media302/"/>
    
    <category term="medialibsync" scheme="https://szxiot.com/tags/medialibsync/"/>
    
  </entry>
  
  <entry>
    <title>家庭媒体库方案(六):302方案(图片302优化方案,含后端)</title>
    <link href="https://szxiot.com/2024/07/27/clouddrive2-alist-strm-302-emby-6/"/>
    <id>https://szxiot.com/2024/07/27/clouddrive2-alist-strm-302-emby-6/</id>
    <published>2024-07-27T05:24:10.000Z</published>
    <updated>2026-07-07T14:06:47.264Z</updated>
    
    <content type="html"><![CDATA[<p>我又又又更新了,不为别的,之前有朋友在用我构建的docker镜像,觉得还是有难度,希望把图片302的服务端整合一下.</p><span id="more"></span><p>这次就就直接说明一下更新内容和如何使用吧.</p><h2 id="更新内容"><a href="#更新内容" class="headerlink" title="更新内容"></a>更新内容</h2><ul><li>增加图片302后端服务,但需要提供115网盘的cookie,格式是<code> UID=...; CID=...; SEID=...</code>,如不提供,也可以指向你自己的后端服务.</li><li>已重新支持Infuse客户端</li><li>其他问题优化</li></ul><h2 id="参数说明"><a href="#参数说明" class="headerlink" title="参数说明"></a>参数说明</h2><p>和之前用法差不多.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot;</span><br><span class="line">-e UPSTREAM_115_SERVER=&quot;http://127.0.0.1:8091&quot;</span><br><span class="line">-e EMBY_TOKEN=&quot;your emby api token&quot;</span><br><span class="line">-e REPLACE_PATH_1=&quot;/mnt/strm&quot;</span><br><span class="line">-e REPLACE_PATH_2=&quot;/Media&quot;</span><br><span class="line"></span><br><span class="line">-v /data/115/115-cookies.txt:/usr/src/app/115-cookies.txt</span><br></pre></td></tr></table></figure><p>简单解释一下,分别是:<br>1、emby服务地址<br>2、图片302服务地址,如果你提供了115网盘的cookie,这里保持不变<code>http://127.0.0.1:8091</code>,注意8091端口你可以直接使用,这已经是一个完整的支持302的后端了.<br>3、emby服务器的api token<br>4和5、用于图片路径替换的,简单说一下:<br>假如你的图片原来路径是:<br><code>/mnt/strm/Animes/国漫/一念永恒 (2020) &#123;tmdb-107371&#125;/poster.jpg</code><br>这个图片在网盘的真实路径是:<br><code>/Media/Animes/国漫/一念永恒 (2020) &#123;tmdb-107371&#125;/poster.jpg</code><br>图片浏览的路径是:<br><code>http://127.0.0.1:8091/Media/Animes/国漫/一念永恒 (2020) &#123;tmdb-107371&#125;/poster.jpg</code><br>明白了吧,docker会把你的<code>/mnt/strm</code>替换为<code>/Media</code>,并拼接第二参数你提供的图片服务地址,使用的使用请检查最终能否访问到.<br>6、把你的115 cookie挂载到docker里.</p><h2 id="命令"><a href="#命令" class="headerlink" title="命令"></a>命令</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media302:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-v /data/115/115-cookies.txt:/usr/src/app/115-cookies.txt \</span><br><span class="line">-v /etc/timezone:/etc/timezone:ro \</span><br><span class="line">-v /etc/localtime:/etc/localtime:ro  \</span><br><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">-e EMBY_TOKEN=&quot;your emby api token&quot; \</span><br><span class="line">-e UPSTREAM_115_SERVER=&quot;http://127.0.0.1:8091&quot; \</span><br><span class="line">-e REPLACE_PATH_1=&quot;/mnt/strm&quot; \</span><br><span class="line">-e REPLACE_PATH_2=&quot;/Media&quot; \</span><br><span class="line">--name media302 \</span><br><span class="line">-p 8090:8090 \</span><br><span class="line">-p 8091:8091 \</span><br><span class="line">ilovn/media302:latest</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;我又又又更新了,不为别的,之前有朋友在用我构建的docker镜像,觉得还是有难度,希望把图片302的服务端整合一下.&lt;/p&gt;</summary>
    
    
    
    
    <category term="Alist" scheme="https://szxiot.com/tags/Alist/"/>
    
    <category term="WebDav" scheme="https://szxiot.com/tags/WebDav/"/>
    
    <category term="infuse" scheme="https://szxiot.com/tags/infuse/"/>
    
    <category term="emby" scheme="https://szxiot.com/tags/emby/"/>
    
    <category term="115" scheme="https://szxiot.com/tags/115/"/>
    
    <category term="阿里云盘" scheme="https://szxiot.com/tags/%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98/"/>
    
    <category term="strm" scheme="https://szxiot.com/tags/strm/"/>
    
    <category term="CloudDrive2" scheme="https://szxiot.com/tags/CloudDrive2/"/>
    
    <category term="302" scheme="https://szxiot.com/tags/302/"/>
    
    <category term="media302" scheme="https://szxiot.com/tags/media302/"/>
    
  </entry>
  
  <entry>
    <title>家庭媒体库方案(五):302方案(图片302优化方案)</title>
    <link href="https://szxiot.com/2024/07/25/clouddrive2-alist-strm-302-emby-5/"/>
    <id>https://szxiot.com/2024/07/25/clouddrive2-alist-strm-302-emby-5/</id>
    <published>2024-07-25T02:23:06.000Z</published>
    <updated>2026-07-07T14:06:47.264Z</updated>
    
    <content type="html"><![CDATA[<p>想不到吧,这个方案又更新了,为什么会更新呢,主要是我的vps空间快满了.</p><span id="more"></span><h2 id="为啥更新"><a href="#为啥更新" class="headerlink" title="为啥更新"></a>为啥更新</h2><p>虽然strm方案没有挂载和缓存的问题,但是媒体库刮削或者已刮削好的资源还是很占用空间,所以你懂的,我现在媒体库规模大概是:<br><img src="https://s.cat.gd/2024/07/7fdce8fa3f3b7ae51404877f14b25883.png" loading="lazy"></p><p>不使用emby刮削,媒体元数据主要包含nfo和海报、分集预览,占用空间24G<br><img src="https://s.cat.gd/2024/07/5da4fb767e3809e703f4066f0cfc6699.png" loading="lazy"></p><p>使用新的方案后,我只需要保留strm和nfo文件,依旧不使用emby刮削,空间占用:<br><img src="https://s.cat.gd/2024/07/4fc854346672547956d3f36e7721e615.png" loading="lazy"></p><h2 id="如何使用"><a href="#如何使用" class="headerlink" title="如何使用"></a>如何使用</h2><h3 id="简单解释一下变化"><a href="#简单解释一下变化" class="headerlink" title="简单解释一下变化"></a>简单解释一下变化</h3><p>和之前用法差不多,但是因为增加了逻辑处理,需要提供更多参数配置, 参数234任意一个不配置,均不会启用图片302.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot;</span><br><span class="line">-e UPSTREAM_115_SERVER=&quot;http://172.17.0.1&quot;</span><br><span class="line">-e EMBY_TOKEN=&quot;your emby api token&quot;</span><br><span class="line">-e REPLACE_PATH_1=&quot;/mnt/strm&quot;</span><br><span class="line">-e REPLACE_PATH_2=&quot;/Media&quot;</span><br></pre></td></tr></table></figure><p>简单解释一下,分别是:<br>1、emby服务地址<br>2、图片302服务地址,这里用alist或者之前<a href="/2024/07/18/media-library-with-python-alist-and-115/" title="家庭媒体库方案(四):虚拟strm及元数据302优化版(待优化)">家庭媒体库方案(四):虚拟strm及元数据302优化版(待优化)</a>提到的方案<br>3、emby服务器的api token<br>4和5、用于图片路径替换的,简单说一下:<br>假如你的图片原来路径是:<br><code>/mnt/strm/Animes/国漫/一念永恒 (2020) &#123;tmdb-107371&#125;/poster.jpg</code><br>这个图片在网盘的真实路径是:<br><code>/Media/Animes/国漫/一念永恒 (2020) &#123;tmdb-107371&#125;/poster.jpg</code><br>图片浏览的路径是:<br><code>http://172.17.0.1/Media/Animes/国漫/一念永恒 (2020) &#123;tmdb-107371&#125;/poster.jpg</code><br>明白了吧,docker会把你的<code>/mnt/strm</code>替换为<code>/Media</code>,并拼接第二参数你提供的图片服务地址,使用的使用请检查最终能否访问到.</p><h3 id="补充说明"><a href="#补充说明" class="headerlink" title="补充说明"></a>补充说明</h3><p>针对我个人使用的场景,实际上我的图片全部都不在服务器上存储了,对于图片的命名要求,目前请遵循mp的命名即可,如果有特别的情况,请给我反馈(不一定有精力去复现和修正,我遇到的问题我都会尽快处理掉).</p><h3 id="命令"><a href="#命令" class="headerlink" title="命令"></a>命令</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">docker pull ilovn/media302:latest &amp;&amp; \</span><br><span class="line">docker run -d \</span><br><span class="line">--restart always \</span><br><span class="line">-e UPSTREAM_HOST=&quot;http://172.17.0.1:8096&quot; \</span><br><span class="line">-e EMBY_TOKEN=&quot;换成你的emby api token&quot; \</span><br><span class="line">-e UPSTREAM_115_SERVER=&quot;图片服务器地址&quot; \</span><br><span class="line">-e REPLACE_PATH_1=&quot;本地路径待替换地址,比如/mnt/strm&quot; \</span><br><span class="line">-e REPLACE_PATH_2=&quot;网盘被替换地址,比如/Media&quot; \</span><br><span class="line">--name media302 \</span><br><span class="line">-p 8090:8090 \</span><br><span class="line">ilovn/media302:latest</span><br></pre></td></tr></table></figure><h3 id="看看效果"><a href="#看看效果" class="headerlink" title="看看效果"></a>看看效果</h3><p><img src="https://s.cat.gd/2024/07/b76f1d972a5c23d5205b2bd4db311868.png" loading="lazy"></p><h3 id="存在的问题"><a href="#存在的问题" class="headerlink" title="存在的问题"></a>存在的问题</h3><p>1、infuse不支持,分析了infuse接口,不清楚客户端逻辑,无法触发本身没有图片的情况下调用获取图片资源;<br>2、图片裁剪功能失效,特别是emby客户端展示可能不太美观;vidhub、senplayer、fileball等客户端没问题;</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;想不到吧,这个方案又更新了,为什么会更新呢,主要是我的vps空间快满了.&lt;/p&gt;</summary>
    
    
    
    
    <category term="Alist" scheme="https://szxiot.com/tags/Alist/"/>
    
    <category term="WebDav" scheme="https://szxiot.com/tags/WebDav/"/>
    
    <category term="infuse" scheme="https://szxiot.com/tags/infuse/"/>
    
    <category term="emby" scheme="https://szxiot.com/tags/emby/"/>
    
    <category term="115" scheme="https://szxiot.com/tags/115/"/>
    
    <category term="阿里云盘" scheme="https://szxiot.com/tags/%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98/"/>
    
    <category term="strm" scheme="https://szxiot.com/tags/strm/"/>
    
    <category term="CloudDrive2" scheme="https://szxiot.com/tags/CloudDrive2/"/>
    
    <category term="302" scheme="https://szxiot.com/tags/302/"/>
    
    <category term="media302" scheme="https://szxiot.com/tags/media302/"/>
    
  </entry>
  
  <entry>
    <title>家庭媒体库方案(四):虚拟strm及元数据302优化版(待优化)</title>
    <link href="https://szxiot.com/2024/07/18/media-library-with-python-alist-and-115/"/>
    <id>https://szxiot.com/2024/07/18/media-library-with-python-alist-and-115/</id>
    <published>2024-07-18T06:18:30.000Z</published>
    <updated>2026-07-07T14:06:47.265Z</updated>
    
    <content type="html"><![CDATA[<p>​    这是我家庭媒体库的支线任务,毕竟我的数据库方案也已经七七八八了,之所以搞这个方案和验证,主要是开发的大佬描述的能力太强了,相对原来的cd2&#x2F;alist+AutoSymlink+Media302方案,省去了AutoSymlink,同时对文件挂载有难度的人来说,门槛降低了许多,我会尽量把我折腾并最终顺利跑起来的步骤记录,按照操作肯定没啥难度的.</p><span id="more"></span><h2 id="0x00-说明"><a href="#0x00-说明" class="headerlink" title="0x00 说明"></a>0x00 说明</h2><p>​    本次实验并不是从零开始的,相反,很多环节都是原来就存在的节点,我们只是把strm生成这个步骤简化了,还可以跟你原来的emby、media302等方案无缝衔接.</p><h2 id="0x01-必要准备"><a href="#0x01-必要准备" class="headerlink" title="0x01 必要准备"></a>0x01 必要准备</h2><p>​    很多人之前可能并没有使用<code>python-115</code>,那么我个人建议,你可以通过学习和了解<a href="https://github.com/ChenyangGao/web-mount-packs/tree/main/python-115-client">python-115</a>来快速知道,我们接下来要做的事情.</p><h3 id="部署web-302-115-simple"><a href="#部署web-302-115-simple" class="headerlink" title="部署web-302-115-simple"></a>部署web-302-115-simple</h3><p>这是开发大佬的高性能简化版302后端,python文件可以在<a href="https://raw.githubusercontent.com/ChenyangGao/web-mount-packs/main/python-115-client/examples/web_115_302_simple.py">这里</a>找到,拿到这个文件后,可以在你的本地执行验证一下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 web_115_302_simple.py</span><br></pre></td></tr></table></figure><p>你还可以指定服务在那个端口上启动:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python3 web_115_302_simple.py -p 8998</span><br></pre></td></tr></table></figure><p>建议在同目录放置115的cookie文件,名字设置为<code>115-cookies.txt</code>就行,里面是字符串格式的Cookie.这样就能在遇到需要验证的时候,自动完成切换.</p><h2 id="0x02-部署python-alist"><a href="#0x02-部署python-alist" class="headerlink" title="0x02 部署python-alist"></a>0x02 部署python-alist</h2><p>相较于前面的web-302-115-simple的极简部署,python-alist可能更加简单,但是因为依赖的东西可能比较多,我整理成一个脚本,让你看起来只要每次启动这个脚本就行,看起来清爽很多.</p><p>先安装一下python-alist:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip3 install -U python-alist</span><br></pre></td></tr></table></figure><p>再安装一下fuse相关的应用和依赖:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install libfuse2</span><br><span class="line">pip3 install fusepy</span><br></pre></td></tr></table></figure><p>如果是非root用户在跑这些应用,可能还需要修改<code>/etc/fuse.conf</code>,把<code>user_allow_other</code>前的<code>#</code>删掉并保存.</p><p>然后,整理一下几个参数备用:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">alist 服务的地址</span></span><br><span class="line">ALIST_HOST=http://10.0.0.1:5244</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">用户名</span></span><br><span class="line">ALIST_USERNAME=alist的用户名</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">密码</span></span><br><span class="line">ALIST_PASSWORD=alist的密码</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">302的后端服务地址 也就是前面配置的web-302-115-simple的服务地址</span></span><br></pre></td></tr></table></figure><h2 id="0x03-写个简单的脚本"><a href="#0x03-写个简单的脚本" class="headerlink" title="0x03 写个简单的脚本"></a>0x03 写个简单的脚本</h2><p>脚本就叫<code>alist-fise.sh</code>,把你准备好的参数,放到我下面的脚本内容中,并保存到<code>alist-fise.sh</code>:</p><p>注意:</p><ul><li>–base-dir 是你在alist里面挂载的115的路径,不一定是&#x2F;115,根据需要修改;</li><li>–strm-make 前面配置的web-302-115-simple的服务地址</li><li>–open-file 前面配置的web-302-115-simple的服务地址</li><li>最后一行的–不要删,后面跟着的是你要挂载的目标目录,目录必须存在并且文件夹内是空的</li></ul><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">alist 服务的地址</span></span><br><span class="line">ALIST_HOST=http://10.0.8.3:5244</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">用户名</span></span><br><span class="line">ALIST_USERNAME=alist的用户名</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">密码</span></span><br><span class="line">ALIST_PASSWORD=alist的密码</span><br><span class="line"></span><br><span class="line">python-alist fuse \</span><br><span class="line">    --origin &quot;$ALIST_HOST&quot; \</span><br><span class="line">    --username &quot;$ALIST_USERNAME&quot; \</span><br><span class="line">    --password &quot;$ALIST_PASSWORD&quot; \</span><br><span class="line">    --base-dir &#x27;/115&#x27; \</span><br><span class="line">    --refresh \</span><br><span class="line">    --strm-predicate-type expr \</span><br><span class="line">    --strm-predicate &#x27;(</span><br><span class="line">        path.media_type.startswith((&quot;video/&quot;, &quot;audio/&quot;)) and </span><br><span class="line">        path.suffix.lower() != &quot;.ass&quot;</span><br><span class="line">    )&#x27; \</span><br><span class="line">    --predicate-type expr \</span><br><span class="line">    --predicate &#x27;(</span><br><span class="line">        path.is_dir() or </span><br><span class="line">        path.media_type.startswith(&quot;image/&quot;) or </span><br><span class="line">        path.suffix.lower() in (&quot;.nfo&quot;, &quot;.ass&quot;, &quot;.ssa&quot;, &quot;.srt&quot;, &quot;.idx&quot;, &quot;.sub&quot;, &quot;.txt&quot;, &quot;.vtt&quot;, &quot;.smi&quot;)</span><br><span class="line">        )&#x27; \</span><br><span class="line">    --strm-make-type fstring \</span><br><span class="line">    --strm-make &#x27;前面配置的web-302-115-simple的服务地址/&#123;path.relative_to(&quot;/115&quot;)&#125;&#x27; \</span><br><span class="line">    --open-file-type fstring \</span><br><span class="line">    --open-file &#x27;前面配置的web-302-115-simple的服务地址/&#123;path.relative_to(&quot;/115&quot;)&#125;&#x27; \</span><br><span class="line">    -- /mnt/alist</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>然后跑起来吧:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh alist-fuse.sh</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ubuntu@VM-0-6-ubuntu:~$ sh alist-fise.sh </span><br><span class="line"></span><br><span class="line">        👋 Welcome to use alist fuse 👏</span><br><span class="line"></span><br><span class="line">    mounted at: &#x27;/mnt/alist&#x27;</span><br><span class="line">    FUSE options: &#123;&#x27;mountpoint&#x27;: &#x27;/mnt/alist&#x27;, &#x27;allow_other&#x27;: True, &#x27;foreground&#x27;: True, &#x27;max_readahead&#x27;: 0, &#x27;noauto_cache&#x27;: True, &#x27;ro&#x27;: True&#125;</span><br></pre></td></tr></table></figure><p>检查一下你的挂载目录,是不是文件都来了,是不是媒体文件都变成了同名的strm文件,剩下的就是去emby里面添加对应的媒体库,指向这些目录吧,如果原来你是同结构的strm,那么还可以清空原目录,直接挂载过去,emby都不需要重新设置.</p><h2 id="0x04-问题待优化"><a href="#0x04-问题待优化" class="headerlink" title="0x04 问题待优化"></a>0x04 问题待优化</h2><p>​    目前媒体元数据的图片这些也是走302连接,但是因为fuse2的问题,可能存在图片显示不完整问题,开发大佬表示已经在优化了,后面解决了如果部署步骤有更新我会说明.</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;​    这是我家庭媒体库的支线任务,毕竟我的数据库方案也已经七七八八了,之所以搞这个方案和验证,主要是开发的大佬描述的能力太强了,相对原来的cd2&amp;#x2F;alist+AutoSymlink+Media302方案,省去了AutoSymlink,同时对文件挂载有难度的人来说,门槛降低了许多,我会尽量把我折腾并最终顺利跑起来的步骤记录,按照操作肯定没啥难度的.&lt;/p&gt;</summary>
    
    
    
    
    <category term="emby" scheme="https://szxiot.com/tags/emby/"/>
    
    <category term="strm" scheme="https://szxiot.com/tags/strm/"/>
    
    <category term="302" scheme="https://szxiot.com/tags/302/"/>
    
    <category term="python-alist" scheme="https://szxiot.com/tags/python-alist/"/>
    
    <category term="python-115" scheme="https://szxiot.com/tags/python-115/"/>
    
    <category term="alist" scheme="https://szxiot.com/tags/alist/"/>
    
    <category term="MediaLibrary" scheme="https://szxiot.com/tags/MediaLibrary/"/>
    
  </entry>
  
</feed>
