<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Charles</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <icon>https://dev.net.cn/images/apple-touch-icon-next.png</icon>
  <id>https://dev.net.cn/</id>
  <link href="https://dev.net.cn/" rel="alternate"/>
  <link href="https://dev.net.cn/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Charles</rights>
  <subtitle>Mind And Hand</subtitle>
  <title>码农笔记</title>
  <updated>2026-04-01T02:00:00.000Z</updated>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Go" scheme="https://dev.net.cn/categories/Go/"/>
    <category term="Go" scheme="https://dev.net.cn/tags/Go/"/>
    <content>
      <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>2017年，简单的学习了一下Go语言，但苦于当时的工作没有办法实践，而我又刚换了工作，每天都要加班到最后一班地铁，没多久，学习的内容就基本上忘光光了，今年得空，可以在学习下Go语言，手头上也有两个项目有时间去重构，那就重新学习一次吧。本次学习使用<code>go 1.26</code>版本。</p><h2 id="Go语言介绍"><a href="#Go语言介绍" class="headerlink" title="Go语言介绍"></a>Go语言介绍</h2><p>Go语言由Google开发，对于程序开发效率、并发、云原生等有非常好的支持。对于<code>Java</code>程序员来说，学习起来非常容易。</p><ul><li><strong>核心特性</strong>：天然并发（Goroutine）、强类型、编译速度极快、垃圾回收（GC）、静态链接成单个可执行二进制文件。</li><li><strong>适用场景</strong>：云原生开发（Docker&#x2F;K8s 均由 Go 编写）、微服务、系统工具、高性能网络服务。</li></ul><h2 id="GOROOT和GOPATH"><a href="#GOROOT和GOPATH" class="headerlink" title="GOROOT和GOPATH"></a>GOROOT和GOPATH</h2><p>对于Go新手还是有必要明确下这两个环境变量的含义，不然很容易纯靠字面意思搞错。</p><p><code>GOROOT</code>，就是<code>Go SDK</code>的安装路径，不是go语言的项目路径，对于<code>Java</code>程序员来说，就是<code>JDK</code>的路径。</p><p><code>GOPATH</code>，工作区路径，类似于<code>Eclipse+maven</code>的组合，将<code>workspace和.m2合并在一个目录</code>。最开始用起来老别扭了，不过从<code>Go 1.11</code>以后，就进入<code>Go Modules</code>时代。将<code>GOPATH</code>理解为<code>maven</code>的仓库，里面存放了不项目的不同依赖（以及同一个库的多个版本），<code>Go Modules</code>则负责隔离，每个项目可以存放在任意目录，并且根目录下有一个<code>go.mod</code>文件，记录该项目具体以来那个版本的库。</p><h2 id="安装配置Go"><a href="#安装配置Go" class="headerlink" title="安装配置Go"></a>安装配置Go</h2><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">Windows</button><button type="button" class="tab">macOS</button><button type="button" class="tab">Debian</button></div><div class="tab-contents"><div class="tab-item-content active"><p>对于<code>Windows</code>，推荐使用<code>Scoop</code>来安装管理</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">scoop isntall go</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><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"><span class="comment"># 对于使用brew的用户</span></span><br><span class="line">brew install go</span><br><span class="line"><span class="comment"># 对于使用port的用户</span></span><br><span class="line">port install go</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><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">wget https://go.dev/dl/go1.26.1.linux-amd64.tar.gz</span><br><span class="line">tar -C /usr/local -xzf go1.26.1.linux-amd64.tar.gz</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>安装完成后，执行<code>go version</code>，如果能正确输出go版本号，那就说明安装成功（以上三种方式都不需要单独设置环境变量，其他方式请自行配置）。下面配置<code>Go env</code>，以Windows为例：</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">GOROOT=D:\Scoop\apps\go\current</span><br><span class="line">GOPATH=D:\devtools\go</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启用go module</span></span><br><span class="line">go <span class="built_in">env</span> -w GO111MODULE=on</span><br><span class="line">go <span class="built_in">env</span> -w GOPROXY=https://goproxy.cn,direct</span><br></pre></td></tr></table></figure><div class="note warning modern"><p>除非你有特殊的目录洁癖，否则保持 <code>GOBIN</code> 为空，只需确保将 <code>$(go env GOPATH)/bin</code> 加入系统 <code>PATH</code> 即可。</p></div><p>对于新手最容易混淆的地方：</p><ul><li><strong><code>go build</code></strong>：在<strong>当前目录</strong>生成二进制文件。它不受 <code>GOBIN</code> 影响。</li><li><strong><code>go install</code></strong>：将二进制文件编译并移动到 <strong><code>GOBIN</code></strong>（或默认的 <code>bin</code>）目录下。</li></ul><p>配置完成后，执行<code>go env</code>查看是否正确。</p><h2 id="编辑器选择"><a href="#编辑器选择" class="headerlink" title="编辑器选择"></a>编辑器选择</h2><h3 id="VS-Code"><a href="#VS-Code" class="headerlink" title="VS Code"></a>VS Code</h3><p>对于喜欢轻量级的开发者来说，<code>VS Code</code>是最佳选择，使用<code>VS Code</code>开发Go，只需要安装<code>go</code>插件即可。安装完成后<code>Ctrl + Shift + P</code>，输入<code>Go: Install/Update Tools</code>，全选并安装，它会提供<code>自动补全</code>、<code>调试</code>等功能。按下<code>F5</code>即可调试程序，或者安装<code>Code Runner</code>插件，亦或者是在命令行中执行<code>go run .</code>。</p><h3 id="GoLand（推荐）"><a href="#GoLand（推荐）" class="headerlink" title="GoLand（推荐）"></a>GoLand（推荐）</h3><p>由于我是<code>Jetbrains</code>的全家桶套餐订阅者，所以我更偏向于<code>Goland</code>，用起来更顺手。</p>]]>
    </content>
    <id>https://dev.net.cn/learning-go-01/</id>
    <link href="https://dev.net.cn/learning-go-01/"/>
    <published>2026-04-01T02:00:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>2017年，简单的学习了一下Go语言，但苦于当时的工作没有办法实践，而我又刚换了工作，每天都要加班到最后一班地铁，没多久，学习的内容就基本上]]>
    </summary>
    <title>Go语言学习笔记（一）</title>
    <updated>2026-04-01T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Rust" scheme="https://dev.net.cn/categories/Rust/"/>
    <category term="Rust" scheme="https://dev.net.cn/tags/Rust/"/>
    <content>
      <![CDATA[<p>从2024年简单的学习了下Rust后，就再也没怎么使用过，最近得闲，准备好好学习下<code>rust</code>。看了下之前记录的Rust笔记略显过时，倒不如从头再来，再学一遍！</p><span id="more"></span><h2 id="安装Rust"><a href="#安装Rust" class="headerlink" title="安装Rust"></a>安装Rust</h2><h3 id="下载rustup"><a href="#下载rustup" class="headerlink" title="下载rustup"></a>下载rustup</h3><p>和其他编程语言不同，安装<code>Rust</code>需要安装的是<code>rustup</code>，然后再利用<code>rustup</code>来安装<code>Rust</code>。这里就推荐使用官网的下载器来安装，我之前使用Scoop安装了rust，但是实际上它不过是个二进制的程序而已，并不满足rust开发。</p><p>打开官方文档<a href="https://rust-lang.org/zh-CN/tools/install/">安装 Rust - Rust 程序设计语言</a>，在这里下载<code>rustup-init.exe</code>，下载后先不着急安装，配置项环境变量。</p><h3 id="配置环境变量"><a href="#配置环境变量" class="headerlink" title="配置环境变量"></a>配置环境变量</h3><p>这一步需要配置四个变量，分别是<code>rustup</code>和<code>cargo</code>安装的路径，以及加速器地址。打开<code>设置</code> -&gt; <code>高级系统设置</code> -&gt; <code>环境变量</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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装路径，cargo类似于pypi，rustup类似于rust安装器</span></span><br><span class="line">CARGO_HOME=D:\devtools\rust\cargo</span><br><span class="line">RUSTUP_HOME=D:\devtools\rust\rustup</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>配置字节加速器，不然慢的要死</strong></p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">中科大源(推荐)</button><button type="button" class="tab">清华大学源</button><button type="button" class="tab">字节跳动源</button></div><div class="tab-contents"><div class="tab-item-content active"><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">RUSTUP_DIST_SERVER=<span class="string">&quot;https://mirrors.ustc.edu.cn/rust-static&quot;</span></span><br><span class="line">RUSTUP_UPDATE_ROOT=<span class="string">&quot;https://mirrors.ustc.edu.cn/rust-static/rustup&quot;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><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">RUSTUP_DIST_SERVER=<span class="string">&quot;https://mirrors.tuna.tsinghua.edu.cn/rustup&quot;</span></span><br><span class="line">RUSTUP_UPDATE_ROOT=<span class="string">&quot;https://mirrors.tuna.tsinghua.edu.cn/rustup/rustup&quot;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><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">RUSTUP_DIST_SERVER=<span class="string">&quot;https://rsproxy.cn&quot;</span></span><br><span class="line">RUSTUP_UPDATE_ROOT=<span class="string">&quot;https://rsproxy.cn/rustup&quot;</span></span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>双击<code>rustup-init.exe</code>，会给你三个选项，<code> Proceed with standard installation</code>，<code>输入1</code>，然后安装即可。期间可能会弹出下载<code>vs buildtools</code>的界面。因为我以前就安装了，所以基本上都是在命令行中完成安装。</p><h3 id="配置源"><a href="#配置源" class="headerlink" title="配置源"></a>配置源</h3><p>安装完成后，还需要配置<code>crates-io</code>源。创建配置文件： <code>~/.cargo/config.toml</code>，然后填入如下内容：</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">中科大源(推荐)</button><button type="button" class="tab">清华大学源</button><button type="button" class="tab">字节跳动源</button></div><div class="tab-contents"><div class="tab-item-content active"><figure class="highlight toml"><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="section">[source.crates-io]</span></span><br><span class="line"><span class="attr">replace-with</span> = <span class="string">&#x27;ustc&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[source.ustc]</span></span><br><span class="line"><span class="attr">registry</span> = <span class="string">&quot;sparse+https://mirrors.ustc.edu.cn/crates.io-index/&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[registries.ustc]</span></span><br><span class="line"><span class="attr">index</span> = <span class="string">&quot;sparse+https://mirrors.ustc.edu.cn/crates.io-index/&quot;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><figure class="highlight toml"><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="section">[source.crates-io]</span></span><br><span class="line"><span class="attr">replace-with</span> = <span class="string">&#x27;tuna&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[source.tuna]</span></span><br><span class="line"><span class="attr">registry</span> = <span class="string">&quot;sparse+https://mirrors.tuna.tsinghua.edu.cn/rust-lang/crates.io-index/&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[registries.tuna]</span></span><br><span class="line"><span class="comment"># 注意：确保这里的 URL 与上面的完全一致，且包含完整的稀疏协议前缀</span></span><br><span class="line"><span class="attr">index</span> = <span class="string">&quot;sparse+https://mirrors.tuna.tsinghua.edu.cn/rust-lang/crates.io-index/&quot;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><figure class="highlight toml"><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></pre></td><td class="code"><pre><span class="line"><span class="section">[source.crates-io]</span></span><br><span class="line"><span class="attr">replace-with</span> = <span class="string">&#x27;rsproxy-sparse&#x27;</span></span><br><span class="line"><span class="section">[source.rsproxy]</span></span><br><span class="line"><span class="attr">registry</span> = <span class="string">&quot;https://rsproxy.cn/crates.io-index&quot;</span></span><br><span class="line"><span class="section">[source.rsproxy-sparse]</span></span><br><span class="line"><span class="attr">registry</span> = <span class="string">&quot;sparse+https://rsproxy.cn/index/&quot;</span></span><br><span class="line"><span class="section">[registries.rsproxy]</span></span><br><span class="line"><span class="attr">index</span> = <span class="string">&quot;https://rsproxy.cn/crates.io-index&quot;</span></span><br><span class="line"><span class="section">[net]</span></span><br><span class="line"><span class="attr">git-fetch-with-cli</span> = <span class="literal">true</span></span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><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">cargo search serde --registry ustc（tuna） </span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://dev.net.cn/learning-rust-01/</id>
    <link href="https://dev.net.cn/learning-rust-01/"/>
    <published>2026-03-26T02:00:00.000Z</published>
    <summary>
      <![CDATA[<p>从2024年简单的学习了下Rust后，就再也没怎么使用过，最近得闲，准备好好学习下<code>rust</code>。看了下之前记录的Rust笔记略显过时，倒不如从头再来，再学一遍！</p>]]>
    </summary>
    <title>Rust学习笔记</title>
    <updated>2026-03-26T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="NodeJS" scheme="https://dev.net.cn/categories/NodeJS/"/>
    <category term="NodeJS" scheme="https://dev.net.cn/tags/NodeJS/"/>
    <category term="NVM" scheme="https://dev.net.cn/tags/NVM/"/>
    <category term="FNM" scheme="https://dev.net.cn/tags/FNM/"/>
    <content>
      <![CDATA[<p> 今天用Claude调试以前的前端项目时，我需要使用<code>nodejs14</code>，按照往常的习惯直接使用<code>nvm install 14</code>，并且切换过去即可。但这次出问题了，我是用<code>nvm use 14</code>，虽然显示切换成功了，但使用<code>node -v</code>依旧显示的时<code>nodejs 24</code>的版本。后续折腾一番环境变量，终于可以切换了，但安装<code>nodejs 14</code>的时候又出幺蛾子了（实测nodejs 18就没问题），<code>npm</code>死活装不上，虽然可以通过手动下载等方式将其配置好，但也略嫌麻烦，于是就萌生了更换工具的想法。</p><span id="more"></span><p>对于<code>Nodejs</code>的版本管理工具，还有另外一个使用<code>Rust</code>实现的<code>fnm</code>。具体请查看<a href="https://github.com/Schniz/fnm">Schniz&#x2F;fnm: 🚀 Fast and simple Node.js version manager, built in Rust</a>。我目前使用scoop来管理这些开发软件，所以安装也是极其方便。（别忘了先卸载nvm）</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">scoop install fnm</span><br></pre></td></tr></table></figure><p>安装完成后，其命令几乎和<code>nvm</code>一样一样的。</p><figure class="highlight powershell"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装node</span></span><br><span class="line">fnm install <span class="number">24</span></span><br><span class="line">fnm install <span class="number">14</span></span><br><span class="line"><span class="comment"># 切换版本</span></span><br><span class="line">fnm use <span class="number">14</span></span><br><span class="line"><span class="comment"># 查看安装了那些</span></span><br><span class="line">fnm list</span><br><span class="line"><span class="comment"># 设置为默认版本</span></span><br><span class="line">fnm default <span class="number">24</span></span><br><span class="line"><span class="comment"># 卸载</span></span><br><span class="line">fnm uninstall <span class="number">18</span></span><br><span class="line"><span class="comment"># 查看当前使用的</span></span><br><span class="line">fnm current</span><br><span class="line"><span class="comment"># 设置别名</span></span><br><span class="line">fnm alias <span class="number">14.21</span>.<span class="number">3</span> project_name</span><br><span class="line"><span class="comment"># 使用别名</span></span><br><span class="line">fnm use project_name</span><br><span class="line"><span class="comment"># 删除别名</span></span><br><span class="line">fnm unalias project_name</span><br></pre></td></tr></table></figure><div class="note warning modern"><p>和nvm替换全局不同，fnm仅仅对当前session有效。</p></div><p>所以，安装完成后，一般会有一段提示，让你再powershell的<code>$PROFILE</code>末尾配置如下：</p><figure class="highlight powershell"><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"># 配置 fnm 环境变量</span></span><br><span class="line">fnm env <span class="literal">--use-on-cd</span> | <span class="built_in">Out-String</span> | <span class="built_in">Invoke-Expression</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果是bash/zsh</span></span><br><span class="line">eval <span class="string">&quot;<span class="variable">$</span>(fnm env --use-on-cd)&quot;</span></span><br></pre></td></tr></table></figure><p>这个命令的作用就是进入目录后，如果当前目录存在<code>.node-version</code>（或者<code>.nvmrc</code>），并且里面是版本号时，就会自动切换到这个node版本，简直是健忘症的福音啊。所以我在每个前端的项目中，都创建了这个文件，并且指定版本：</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"><span class="comment"># 在前端项目的根目录，请千万注意，不要把文件名搞成.node_version，我因为这个问题和AI讨论了一下午，AI都开始怀疑是PWS的问题了。</span></span><br><span class="line">nvim .node-version</span><br><span class="line"><span class="comment"># 填入一个版本号，例如：</span></span><br><span class="line">14</span><br></pre></td></tr></table></figure><p>这样，打开不同的前端项目就会自动的切换到指定版本。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/fnm_terminal.webp" alt="效果"></p><p>它的检测顺序是：</p><ol><li><code>.node-version</code>文件</li><li><code>.nvmrc</code>文件</li><li><code>package.json</code>中的<code>engines.node</code>字段（需启用<code>--resolve-engines</code>）</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">fnm <span class="built_in">exec</span> --using=14 node index.js</span><br></pre></td></tr></table></figure><p>这是 <code>fnm</code> 和 <code>nvm-windows</code> 最大的技术区别：</p><ul><li><strong>nvm</strong>：通过修改系统的全局 <code>Path</code> 和创建硬链接来工作，容易被其他软件抢占优先级。</li><li><strong>fnm</strong>：当你执行 <code>fnm use</code> 时，它只在当前的 PowerShell 会话（窗口）里临时修改 <code>Path</code>。</li><li><strong>意义</strong>：这意味着你可以在窗口 A 开着 Node 14 跑老代码，窗口 B 开着 Node 24 跑新代码，<strong>互不干扰</strong>。</li></ul>]]>
    </content>
    <id>https://dev.net.cn/switching-from-nvm-to-fnm-for-node-management/</id>
    <link href="https://dev.net.cn/switching-from-nvm-to-fnm-for-node-management/"/>
    <published>2026-03-21T02:00:00.000Z</published>
    <summary>
      <![CDATA[<p> 今天用Claude调试以前的前端项目时，我需要使用<code>nodejs14</code>，按照往常的习惯直接使用<code>nvm install 14</code>，并且切换过去即可。但这次出问题了，我是用<code>nvm use 14</code>，虽然显示切换成功了，但使用<code>node -v</code>依旧显示的时<code>nodejs 24</code>的版本。后续折腾一番环境变量，终于可以切换了，但安装<code>nodejs 14</code>的时候又出幺蛾子了（实测nodejs 18就没问题），<code>npm</code>死活装不上，虽然可以通过手动下载等方式将其配置好，但也略嫌麻烦，于是就萌生了更换工具的想法。</p>]]>
    </summary>
    <title>放弃nvm改换fnm</title>
    <updated>2026-03-21T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="WSL" scheme="https://dev.net.cn/categories/WSL/"/>
    <category term="Linux" scheme="https://dev.net.cn/tags/Linux/"/>
    <category term="Arch" scheme="https://dev.net.cn/tags/Arch/"/>
    <category term="Fedroa" scheme="https://dev.net.cn/tags/Fedroa/"/>
    <content>
      <![CDATA[<p>中午无聊，打算装两个Linux玩玩，我选择了<code>Fedora42</code>和<code>Arch</code>，这两个系统在<code>WSL</code>中式支持的，但默认安装在C盘，还得再导出导入一次才能换到其他盘，那何必多此一举，直接导入到其他盘即可。下面介绍下本次安装的过程。</p><span id="more"></span><h2 id="系统包准备"><a href="#系统包准备" class="headerlink" title="系统包准备"></a>系统包准备</h2><ul><li><p>Fedora42 ，<a href="https://dl.fedoraproject.org/pub/fedora/linux/releases/42/Container/x86_64/images/">Fedroa42 下载地址</a></p></li><li><p>ArchLinux，<a href="https://mirrors.edge.kernel.org/archlinux/iso/latest/">ArchLinux下载地址</a></p></li></ul><p>打开Fedora下载地址，<code>Fedora</code>官方支持WSL的镜像，所以只需要下载<code>Fedora-WSL-Base-42-1.1.x86_64.tar.xz</code>即可。</p><p>打开ArchLinux下载地址，Arch官方没有WSL的镜像，我们下载<code>archlinux-bootstrap-x86_64.tar.zst</code>，然后在任意一个Linux中使用<code>zstd</code>命令将其转换为<code>tar</code>包。以Ubuntu为例</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"><span class="built_in">sudo</span> apt install zstd</span><br><span class="line"><span class="comment"># 解压 zst 并打包为 tar</span></span><br><span class="line">zstd -d archlinux-bootstrap-x86_64.tar.zst</span><br></pre></td></tr></table></figure><div class="note warning modern"><p>ArchLinux默认会比其他发行版多一层目录<code>root.x86_64</code>，所以这个包还需要再处理下才行，不能直接导入。</p></div><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建临时目录</span></span><br><span class="line"><span class="built_in">mkdir</span> temp_arch</span><br><span class="line"><span class="comment"># 解压到该目录</span></span><br><span class="line"><span class="built_in">sudo</span> tar -xvf archlinux-bootstrap-x86_64.tar -C temp_arch</span><br><span class="line"><span class="comment"># 重新打包</span></span><br><span class="line"><span class="built_in">cd</span> temp_arch/root.x86_64</span><br><span class="line"><span class="built_in">sudo</span> tar -cvf ../../arch_fixed.tar .</span><br><span class="line"></span><br><span class="line"><span class="comment"># 清理临时文件</span></span><br><span class="line"><span class="built_in">cd</span> ../..</span><br><span class="line"><span class="built_in">rm</span> -rf temp_arch</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将其拷贝到Window硬盘中</span></span><br><span class="line"><span class="built_in">cp</span> arch_fixed.tar /mnt/e/Downloads</span><br></pre></td></tr></table></figure><h2 id="导入Linux系统"><a href="#导入Linux系统" class="headerlink" title="导入Linux系统"></a>导入Linux系统</h2><p>分别创建两个目录<code>E:\WSL\Fedora42</code>和<code>E:\WSL\Arch</code>，在PowerShell中执行如下：</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"><span class="built_in">mkdir</span> e:\WSL\Fedora42</span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> e:\WSL\Arch</span><br></pre></td></tr></table></figure><p>导入系统</p><figure class="highlight powershell"><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"># 导入Fedora42</span></span><br><span class="line">wsl <span class="literal">--import</span> Fedora42 E:\WSL\Fedora42 E:\Downloads\Fedora<span class="literal">-WSL-Base-42-1</span>.<span class="number">1</span>.x86_64.tar.xz</span><br><span class="line"></span><br><span class="line"><span class="comment"># 导入ArchLinux</span></span><br><span class="line">wsl <span class="literal">--import</span> Arch E:\WSL\Arch E:\Downloads\arch_fixed.tar</span><br></pre></td></tr></table></figure><h2 id="启动系统"><a href="#启动系统" class="headerlink" title="启动系统"></a>启动系统</h2><p>使用wsl命令启动这两个系统，后面的参数就是wsl系统的名称，也就是上一步<code>--import</code>后面的那个名字。</p><figure class="highlight powershell"><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">wsl <span class="literal">-d</span> Fedora42</span><br><span class="line"></span><br><span class="line">wsl <span class="literal">-d</span> Arch</span><br></pre></td></tr></table></figure><p>默认是<code>root</code>启动，还需要再次配置。</p><h2 id="配置WSL系统"><a href="#配置WSL系统" class="headerlink" title="配置WSL系统"></a>配置WSL系统</h2><p>接着就是对系统的初始化配置了</p><h3 id="配置Fedora42"><a href="#配置Fedora42" class="headerlink" title="配置Fedora42"></a>配置Fedora42</h3><p>1.安装基础工具</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">dnf install -y <span class="built_in">sudo</span> passwd ncurses findutils</span><br></pre></td></tr></table></figure><p>2.创建普通用户</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">useradd -m -G wheel yourusername</span><br><span class="line">passwd yourusername</span><br></pre></td></tr></table></figure><p>3.配置wsl默认使用新建的用户登录</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></pre></td><td class="code"><pre><span class="line"><span class="built_in">cat</span> &lt;&lt;<span class="string">EOF &gt; /etc/wsl.conf</span></span><br><span class="line"><span class="string">[boot]</span></span><br><span class="line"><span class="string">systemd=true</span></span><br><span class="line"><span class="string">[user]</span></span><br><span class="line"><span class="string">default=yourusername </span></span><br><span class="line"><span class="string">[network]</span></span><br><span class="line"><span class="string">generateHosts = true</span></span><br><span class="line"><span class="string">generateResolvConf = true</span></span><br><span class="line"><span class="string">EOF</span></span><br></pre></td></tr></table></figure><p>4.检查dnf状态</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">dnf --version</span><br></pre></td></tr></table></figure><p>5.设置源</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"><span class="built_in">sudo</span> sed -e <span class="string">&#x27;s|^metalink=|#metalink=|g&#x27;</span> \</span><br><span class="line">         -e <span class="string">&#x27;s|^#baseurl=http://download.example/pub/fedora/linux|baseurl=https://mirrors.tuna.tsinghua.edu.cn/fedora|g&#x27;</span> \</span><br><span class="line">         -i.bak /etc/yum.repos.d/fedora*.repo</span><br></pre></td></tr></table></figure><p>6.更新缓存</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">dnf makecache</span><br></pre></td></tr></table></figure><p>7.设置并发下载</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">echo</span> <span class="string">&quot;max_parallel_downloads=10&quot;</span> | <span class="built_in">tee</span> -a /etc/dnf/dnf.conf</span><br></pre></td></tr></table></figure><p>8.关闭防火墙</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">systemctl stop firewalld</span><br><span class="line">systemctl <span class="built_in">disable</span> firewalld</span><br></pre></td></tr></table></figure><p>9.安装字体</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">dnf install -y google-noto-fonts-common</span><br></pre></td></tr></table></figure><p>如果把它当centos使用，可以安装开发工具包</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">dnf groupinstall <span class="string">&quot;Development Tools&quot;</span> -y &amp;&amp; \</span><br><span class="line">dnf install -y golang java-latest-openjdk-devel nodejs git neofetch htop</span><br></pre></td></tr></table></figure><p>为了避免新创建的用户无法使用sudo命令，可以用<code>root</code>执行<code>visudo</code>。找到下面的配置</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">%wheel  ALL=(ALL)       ALL</span><br></pre></td></tr></table></figure><p>确认是没备注是的，它可以允许所有属于wheel组的用户执行任何命令。</p><p>然后退出<code>Fedroa42</code>，执行<code>wsl --shutdown</code>，再次打开就可以使用刚才配置的用户登陆了。</p><p>10.安装fastfetch</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"><span class="built_in">sudo</span> dnf install -y fastfetch</span><br><span class="line"><span class="comment"># 如果你想每次登录都显示，那就加进去。</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;fastfetch&quot;</span> &gt;&gt; ~/.bashrc</span><br></pre></td></tr></table></figure><p>过程中可能会遇到一个错误<code>No valid source (baseurl, mirrorlist or metalink) found for repository &quot;fedora-cisco-openh264&quot;</code></p><p>这个需要编辑<code>/etc/yum.repos.d/fedora-cisco-openh264.repo</code></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">sudo</span> vi /etc/yum.repos.d/fedora-cisco-openh264.repo</span><br></pre></td></tr></table></figure><p> 将里面的 <code>enable=1</code>全部修改为<code>enable=0</code>，然后保存退出</p><h3 id="配置Arch"><a href="#配置Arch" class="headerlink" title="配置Arch"></a>配置Arch</h3><p>大致和<code>Fedroa42</code>类似，但也有特殊的地方。注意，此时登陆的用户是<code>root</code></p><p>1.初始化<code>pacman-key</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></pre></td><td class="code"><pre><span class="line">pacman-key --init</span><br><span class="line">pacman-key --populate archlinux</span><br><span class="line">pacman -Syu</span><br></pre></td></tr></table></figure><p>2.配置源</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">echo</span> <span class="string">&quot;Server = https://mirrors.tuna.tsinghua.edu.cn/archlinux/\$repo/os/\$arch&quot;</span> | <span class="built_in">tee</span> /etc/pacman.d/mirrorlist</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">pacman-key --init</span><br><span class="line">pacman-key --populate archlinux</span><br></pre></td></tr></table></figure><p>3.安装基础工具包</p><p>archlinux，默认连vi、sudo都没装</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">pacman -S base-devel git vim go</span><br></pre></td></tr></table></figure><p>4.创建用户</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">useradd -m -G wheel yourusername</span><br><span class="line">passwd yourusername</span><br></pre></td></tr></table></figure><p>注意：archlinux的<code>wheel</code>组不能直接执行sudo。</p><p>5.配置wsl</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"><span class="built_in">cat</span> &lt;&lt;<span class="string">EOF &gt; /etc/wsl.conf</span></span><br><span class="line"><span class="string">[boot]</span></span><br><span class="line"><span class="string">systemd=true</span></span><br><span class="line"><span class="string">[user]</span></span><br><span class="line"><span class="string">default=yourusername </span></span><br><span class="line"><span class="string">EOF</span></span><br></pre></td></tr></table></figure><p>6.配置sudo</p><p>使用当前用户<code>root</code>，执行<code>visudo</code>，找到<code>%wheel ALL=(ALL:ALL) ALL</code>，将前面的<code>#</code>删掉。</p><p>如果忘记执行这一步就重启使用新用户登录，就会提示<code>yourusername is not in the sudoers file.</code>可以在powershell中执行<code>wsl -u root -d Arch</code>，使用root用户登录，然后用root用户修改即可。</p><p>7.确认id</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">id</span> -u yourusername</span><br></pre></td></tr></table></figure><p>8.设置语言</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></pre></td><td class="code"><pre><span class="line">vi /etc/locale.gen</span><br><span class="line"></span><br><span class="line"># 将下面的注释放开</span><br><span class="line">en_US.UTF-8 UTF-8</span><br><span class="line">zh_CN.UTF-8 UTF-8</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></pre></td><td class="code"><pre><span class="line">locale-gen</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></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;LANG=en_US.UTF-8&quot;</span> &gt; /etc/locale.conf  <span class="comment"># 多年经验，还是英文好点</span></span><br></pre></td></tr></table></figure><p>9.安装其他工具包</p><p>ArchLinux是高度定制化的，啥都要自己装</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">pacman -S base-devel <span class="built_in">sudo</span> git wget curl bash-completion net-tools iputils</span><br><span class="line"></span><br><span class="line"><span class="comment"># 显示系统信息</span></span><br><span class="line">pacman -S fastfetch</span><br></pre></td></tr></table></figure><p>然后退出系统，再重新登录，就是刚才新建的用户了。</p><h2 id="配置PowerShell及配色"><a href="#配置PowerShell及配色" class="headerlink" title="配置PowerShell及配色"></a>配置PowerShell及配色</h2><p>一般Windows会自动识别，然后自动创建<code>PowerShell</code>的配置，但也是有延迟的，我都是配置完了才识别出来。由于我已经配好了<code>Debian</code>和<code>Ubuntu</code>，那就直接复制就行，然后改一下名称、图标、启动命令。</p><p>按<code>ctrl+,</code>打开设置，找到左侧菜单中的配置文件，点击<code>+ 添加新配置文件</code>，然后选择复制，复制一个你配置好的即可。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/powershell-new-config.webp" alt="powershell-new-config"></p><p>复制后，点击刚才复制的配置，修改一下。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/powershell-new-config-02.webp" alt="powershell-new-config-02"></p><p>系统默认会识别出来的，其中<code>Fedroa</code>系统会有自己的图标，ArchLinux没有，使用的默认WSL的图标。再命令行那里，系统识别出来的是<code>C:\WINDOWS\system32\wsl.exe --distribution-id &#123;897ed9c5-dc17-4a23-a17a-45719d59c52b&#125; --cd ~</code>，但其实我更推荐使用<code>-d 系统名称</code>，这样即使删掉在创建，只要名字一样，这个配置就会一直有用。注意这个名字是 <code>--import </code>后面的这个名字。</p><p>不同系统都会有自己独特的配色，例如Ubuntu有个茄子配色，<code>Fedroa</code>是蓝色的，<code>suse</code>是绿色的，下面分享一下我得配色。在PowerShell中，按下快捷键<code>Ctrl + Shift + ,</code>打开Windows Terminal 的 <code>settings.json</code>，在 <code>&quot;schemes&quot;</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></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;background&quot;</span>: <span class="string">&quot;#002B36&quot;</span>,</span><br><span class="line">    <span class="string">&quot;black&quot;</span>: <span class="string">&quot;#073642&quot;</span>,</span><br><span class="line">    <span class="string">&quot;blue&quot;</span>: <span class="string">&quot;#268BD2&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightBlack&quot;</span>: <span class="string">&quot;#002B36&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightBlue&quot;</span>: <span class="string">&quot;#839496&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightCyan&quot;</span>: <span class="string">&quot;#93A1A1&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightGreen&quot;</span>: <span class="string">&quot;#586E75&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightPurple&quot;</span>: <span class="string">&quot;#6C71C4&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightRed&quot;</span>: <span class="string">&quot;#CB4B16&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightWhite&quot;</span>: <span class="string">&quot;#FDF6E3&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightYellow&quot;</span>: <span class="string">&quot;#657B83&quot;</span>,</span><br><span class="line">    <span class="string">&quot;cursorColor&quot;</span>: <span class="string">&quot;#D33682&quot;</span>,</span><br><span class="line">    <span class="string">&quot;cyan&quot;</span>: <span class="string">&quot;#2AA198&quot;</span>,</span><br><span class="line">    <span class="string">&quot;foreground&quot;</span>: <span class="string">&quot;#839496&quot;</span>,</span><br><span class="line">    <span class="string">&quot;green&quot;</span>: <span class="string">&quot;#859900&quot;</span>,</span><br><span class="line">    <span class="string">&quot;name&quot;</span>: <span class="string">&quot;Debian-Official&quot;</span>,</span><br><span class="line">    <span class="string">&quot;purple&quot;</span>: <span class="string">&quot;#D33682&quot;</span>,</span><br><span class="line">    <span class="string">&quot;red&quot;</span>: <span class="string">&quot;#DC322F&quot;</span>,</span><br><span class="line">    <span class="string">&quot;selectionBackground&quot;</span>: <span class="string">&quot;#073642&quot;</span>,</span><br><span class="line">    <span class="string">&quot;white&quot;</span>: <span class="string">&quot;#EEE8D5&quot;</span>,</span><br><span class="line">    <span class="string">&quot;yellow&quot;</span>: <span class="string">&quot;#B58900&quot;</span></span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;background&quot;</span>: <span class="string">&quot;#0B1D35&quot;</span>,</span><br><span class="line">    <span class="string">&quot;black&quot;</span>: <span class="string">&quot;#000000&quot;</span>,</span><br><span class="line">    <span class="string">&quot;blue&quot;</span>: <span class="string">&quot;#294172&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightBlack&quot;</span>: <span class="string">&quot;#676767&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightBlue&quot;</span>: <span class="string">&quot;#31609A&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightCyan&quot;</span>: <span class="string">&quot;#51A2DA&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightGreen&quot;</span>: <span class="string">&quot;#49A62A&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightPurple&quot;</span>: <span class="string">&quot;#A181BC&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightRed&quot;</span>: <span class="string">&quot;#F66151&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightWhite&quot;</span>: <span class="string">&quot;#FFFFFF&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightYellow&quot;</span>: <span class="string">&quot;#D6BAAD&quot;</span>,</span><br><span class="line">    <span class="string">&quot;cursorColor&quot;</span>: <span class="string">&quot;#51A2DA&quot;</span>,</span><br><span class="line">    <span class="string">&quot;cyan&quot;</span>: <span class="string">&quot;#226A9C&quot;</span>,</span><br><span class="line">    <span class="string">&quot;foreground&quot;</span>: <span class="string">&quot;#D1D1D1&quot;</span>,</span><br><span class="line">    <span class="string">&quot;green&quot;</span>: <span class="string">&quot;#3E7B28&quot;</span>,</span><br><span class="line">    <span class="string">&quot;name&quot;</span>: <span class="string">&quot;Fedora-DeepBlue&quot;</span>,</span><br><span class="line">    <span class="string">&quot;purple&quot;</span>: <span class="string">&quot;#75507B&quot;</span>,</span><br><span class="line">    <span class="string">&quot;red&quot;</span>: <span class="string">&quot;#C01C28&quot;</span>,</span><br><span class="line">    <span class="string">&quot;selectionBackground&quot;</span>: <span class="string">&quot;#1B3456&quot;</span>,</span><br><span class="line">    <span class="string">&quot;white&quot;</span>: <span class="string">&quot;#D1D1D1&quot;</span>,</span><br><span class="line">    <span class="string">&quot;yellow&quot;</span>: <span class="string">&quot;#B58900&quot;</span></span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;background&quot;</span>: <span class="string">&quot;#300A24&quot;</span>,</span><br><span class="line">    <span class="string">&quot;black&quot;</span>: <span class="string">&quot;#2E3436&quot;</span>,</span><br><span class="line">    <span class="string">&quot;blue&quot;</span>: <span class="string">&quot;#3465A4&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightBlack&quot;</span>: <span class="string">&quot;#555753&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightBlue&quot;</span>: <span class="string">&quot;#729FCF&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightCyan&quot;</span>: <span class="string">&quot;#34E2E2&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightGreen&quot;</span>: <span class="string">&quot;#8AE234&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightPurple&quot;</span>: <span class="string">&quot;#AD7FA8&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightRed&quot;</span>: <span class="string">&quot;#EF2929&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightWhite&quot;</span>: <span class="string">&quot;#EEEEEC&quot;</span>,</span><br><span class="line">    <span class="string">&quot;brightYellow&quot;</span>: <span class="string">&quot;#FCE94F&quot;</span>,</span><br><span class="line">    <span class="string">&quot;cursorColor&quot;</span>: <span class="string">&quot;#FFFFFF&quot;</span>,</span><br><span class="line">    <span class="string">&quot;cyan&quot;</span>: <span class="string">&quot;#06989A&quot;</span>,</span><br><span class="line">    <span class="string">&quot;foreground&quot;</span>: <span class="string">&quot;#FFFFFF&quot;</span>,</span><br><span class="line">    <span class="string">&quot;green&quot;</span>: <span class="string">&quot;#4E9A06&quot;</span>,</span><br><span class="line">    <span class="string">&quot;name&quot;</span>: <span class="string">&quot;Ubuntu-Official&quot;</span>,</span><br><span class="line">    <span class="string">&quot;purple&quot;</span>: <span class="string">&quot;#75507B&quot;</span>,</span><br><span class="line">    <span class="string">&quot;red&quot;</span>: <span class="string">&quot;#CC0000&quot;</span>,</span><br><span class="line">    <span class="string">&quot;selectionBackground&quot;</span>: <span class="string">&quot;#B6B6B6&quot;</span>,</span><br><span class="line">    <span class="string">&quot;white&quot;</span>: <span class="string">&quot;#D3D7CF&quot;</span>,</span><br><span class="line">    <span class="string">&quot;yellow&quot;</span>: <span class="string">&quot;#C4A000&quot;</span></span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">    <span class="string">&quot;name&quot;</span>: <span class="string">&quot;Arch-Carbon&quot;</span>,</span><br><span class="line">    <span class="string">&quot;background&quot;</span>: <span class="string">&quot;#121212&quot;</span>,</span><br><span class="line">    <span class="string">&quot;black&quot;</span>: <span class="string">&quot;#1C1C1C&quot;</span>,</span><br><span class="line">    <span class="string">&quot;blue&quot;</span>: <span class="string">&quot;#5FAFD7&quot;</span>,</span><br><span class="line">    <span class="string">&quot;cyan&quot;</span>: <span class="string">&quot;#5FAF87&quot;</span>,</span><br><span class="line">    <span class="string">&quot;foreground&quot;</span>: <span class="string">&quot;#D0D0D0&quot;</span>,</span><br><span class="line">    <span class="string">&quot;green&quot;</span>: <span class="string">&quot;#87AF87&quot;</span>,</span><br><span class="line">    <span class="string">&quot;purple&quot;</span>: <span class="string">&quot;#AF87AF&quot;</span>,</span><br><span class="line">    <span class="string">&quot;red&quot;</span>: <span class="string">&quot;#AF5F5F&quot;</span>,</span><br><span class="line">    <span class="string">&quot;white&quot;</span>: <span class="string">&quot;#E4E4E4&quot;</span>,</span><br><span class="line">    <span class="string">&quot;yellow&quot;</span>: <span class="string">&quot;#D7AF5F&quot;</span>,</span><br><span class="line">    <span class="string">&quot;cursorColor&quot;</span>: <span class="string">&quot;#1793D1&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这四个配色，下面就以<code>Fedroa</code>为例看下效果，在PowerShell中，按快捷键<code>Ctrl + ,</code>，打开设置，找到<code>Fedora42</code>的配置文件，在<code>其他设置</code>-&gt;<code>外观</code>中选择刚才添加的配置名称<code>Fedora-DeepBlue</code>，然后再次登录查看效果。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/powershell-new-config-03.webp" alt="powershell-new-config-03"></p><p>后续再给每个系统安装个<code>oh-my-zsh</code>美化下就好了。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/powershell-wsl-oh-my-zsh.webp" alt="powershell-wsl-oh-my-zsh"></p>]]>
    </content>
    <id>https://dev.net.cn/install-linux-with-wsl/</id>
    <link href="https://dev.net.cn/install-linux-with-wsl/"/>
    <published>2026-03-19T06:00:00.000Z</published>
    <summary>
      <![CDATA[<p>中午无聊，打算装两个Linux玩玩，我选择了<code>Fedora42</code>和<code>Arch</code>，这两个系统在<code>WSL</code>中式支持的，但默认安装在C盘，还得再导出导入一次才能换到其他盘，那何必多此一举，直接导入到其他盘即可。下面介绍下本次安装的过程。</p>]]>
    </summary>
    <title>使用wsl安装Linux系统</title>
    <updated>2026-03-19T06:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="CloudFlare" scheme="https://dev.net.cn/categories/CloudFlare/"/>
    <category term="MySQL" scheme="https://dev.net.cn/tags/MySQL/"/>
    <category term="Docker" scheme="https://dev.net.cn/tags/Docker/"/>
    <category term="PostgreSQL" scheme="https://dev.net.cn/tags/PostgreSQL/"/>
    <category term="S3" scheme="https://dev.net.cn/tags/S3/"/>
    <content>
      <![CDATA[<p>接上一篇，将能迁移的服务都迁移到PostgreSQL后，再配置上自动备份脚本，基本上就可以高枕无忧了，本来想备份到阿里云OSS的，想了想本站几乎是<code>ALL IN Cloudflare</code>，那就直接备份到<code>CloudFlare R2</code>吧，正好也快一点。下面就记录下备份的方法。</p><span id="more"></span><h2 id="创建CloudFlare-R2桶"><a href="#创建CloudFlare-R2桶" class="headerlink" title="创建CloudFlare R2桶"></a>创建CloudFlare R2桶</h2><p>在面板首页-&gt;<code>存储和数据库</code> -&gt; <code>R2对象存储</code>中，创建一个桶，我起的名字就是<code>backup</code>。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/image-20260318214208232.webp" alt="创建桶"></p><p>创建完成后发，返回桶列表，点击右下角的<code>Account Deatails</code>下面的<code>Manage</code>，按钮，创建一个Token。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/image-20260318214457248.webp" alt="创建Token"></p><div class="note warning modern"><p>1、权限必须是管理员读和写，选对象读和写执行rclone命令会报权限错误。</p><p>2、因为1，所以最好将客户端IP限制一下，反正VPS都是静态的IP地址，不然要是被泄露了那就完犊子了~</p></div><p>创建好后，给你三个信息，分别是<code>访问密钥 ID（access_key_id）</code>、<code>机密访问密钥（secret_access_key）</code>、<code>为 S3 客户端使用管辖权地特定的终结点(endpoint)</code>。暂时记录下来，下一步要用。</p><h2 id="安装Rclone"><a href="#安装Rclone" class="headerlink" title="安装Rclone"></a>安装Rclone</h2><p>要备份到CloudFlare R2，那就需要Rclone，执行下面的命令安装即可。</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">apt install rclone</span><br></pre></td></tr></table></figure><p>安装完成后，执行<code>rclone config</code>就可以配置了，不过控制台看着乱糟糟的，我直接选创建配置文件的方式了。</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">touch</span> ~/.config/rclone/rclone.conf</span><br></pre></td></tr></table></figure><p>然后在里面填写如下信息：</p><figure class="highlight ini"><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="section">[r2-remote]</span></span><br><span class="line"><span class="attr">type</span> = s3</span><br><span class="line"><span class="attr">provider</span> = Cloudflare</span><br><span class="line"><span class="attr">access_key_id</span> = &lt;你的访问密钥&gt;</span><br><span class="line"><span class="attr">secret_access_key</span> = &lt;你的机密访问密钥&gt;</span><br><span class="line"><span class="comment"># 注意，不要带桶名称</span></span><br><span class="line"><span class="attr">endpoint</span> = https://&lt;Account_ID&gt;.r2.cloudflarestorage.com</span><br><span class="line"><span class="attr">no_check_bucket</span> = <span class="literal">true</span></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><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="comment"># 执行</span></span><br><span class="line">rclone listremotes</span><br><span class="line"><span class="comment"># 输出 </span></span><br><span class="line">r2-remote:</span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行</span></span><br><span class="line">rclone lsd r2-remote: -vv</span><br><span class="line"><span class="comment"># 输出</span></span><br><span class="line"><span class="comment"># 你自己的桶，其中需要包含刚才创建的</span></span><br></pre></td></tr></table></figure><h2 id="配置脚本"><a href="#配置脚本" class="headerlink" title="配置脚本"></a>配置脚本</h2><h3 id="PostgreSQL"><a href="#PostgreSQL" class="headerlink" title="PostgreSQL"></a>PostgreSQL</h3><p>在<code>/data/script/</code>中创建<code>pgsql-to-r2.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></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">CONTAINER_NAME=<span class="string">&quot;postgresql&quot;</span></span><br><span class="line">DB_USER=<span class="string">&quot;postgres&quot;</span></span><br><span class="line">BACKUP_DIR=<span class="string">&quot;/data/backups/pgsql&quot;</span></span><br><span class="line">DATE=$(<span class="built_in">date</span> +%Y%m%d_%H%M%S)</span><br><span class="line">FILE_NAME=<span class="string">&quot;pg_all_backup_<span class="variable">$DATE</span>.sql.gz&quot;</span></span><br><span class="line">R2_BUCKET=<span class="string">&quot;r2-remote:backup&quot;</span> <span class="comment"># rclone 配置名:桶名(backup就是刚才创建的桶)</span></span><br><span class="line">RETENTION_DAYS=7</span><br><span class="line"></span><br><span class="line"><span class="comment"># --- 执行备份 ---</span></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="variable">$BACKUP_DIR</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;开始导出 ...&quot;</span></span><br><span class="line">docker <span class="built_in">exec</span> -t <span class="variable">$CONTAINER_NAME</span> pg_dumpall -c -U <span class="variable">$DB_USER</span> | gzip &gt; <span class="variable">$BACKUP_DIR</span>/<span class="variable">$FILE_NAME</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># --- 上传到 R2 ---</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;正在上传 <span class="variable">$FILE_NAME</span> 到 Cloudflare R2...&quot;</span></span><br><span class="line">rclone copy <span class="variable">$BACKUP_DIR</span>/<span class="variable">$FILE_NAME</span> <span class="variable">$R2_BUCKET</span>/pgsql_daily/</span><br><span class="line"></span><br><span class="line"><span class="comment"># --- 清理旧数据 ---</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;清理 <span class="variable">$RETENTION_DAYS</span> 天前的本地备份...&quot;</span></span><br><span class="line">find <span class="variable">$BACKUP_DIR</span> -mtime +<span class="variable">$RETENTION_DAYS</span> -<span class="built_in">exec</span> <span class="built_in">rm</span> &#123;&#125; \;</span><br><span class="line"></span><br><span class="line"><span class="comment"># --- 可选：清理 R2 上的旧备份 (需要 R2 支持 lifecycle 或用 rclone delete) ---</span></span><br><span class="line"><span class="comment"># rclone delete $R2_BUCKET --min-age $&#123;RETENTION_DAYS&#125;d --dry-run</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;备份任务完成！&quot;</span></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></pre></td><td class="code"><pre><span class="line">bash pgsql-to-r2.sh</span><br></pre></td></tr></table></figure><h3 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h3><p>在<code>/data/script/</code>中创建<code>mysql-to-r2.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></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"># --- 1. 配置区 ---</span></span><br><span class="line">CONTAINER_NAME=<span class="string">&quot;db&quot;</span>  <span class="comment"># 你的 MySQL 容器名</span></span><br><span class="line">DB_USER=<span class="string">&quot;root&quot;</span></span><br><span class="line">DB_PASSWORD=<span class="string">&quot;password&quot;</span>  </span><br><span class="line">BACKUP_DIR=<span class="string">&quot;/data/backups/mysql&quot;</span></span><br><span class="line">DATE=$(<span class="built_in">date</span> +%Y%m%d_%H%M)</span><br><span class="line">R2_REMOTE=<span class="string">&quot;r2-remote:backup&quot;</span> </span><br><span class="line">RETENTION_DAYS=7</span><br><span class="line"></span><br><span class="line"><span class="comment"># 需要备份的数据库列表</span></span><br><span class="line">DATABASES=(<span class="string">&quot;db1&quot;</span> <span class="string">&quot;db2&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># --- 2. 准备工作 ---</span></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="variable">$BACKUP_DIR</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;[<span class="variable">$DATE</span>] 开始执行 MySQL 分库备份...&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># --- 3. 循环备份 ---</span></span><br><span class="line"><span class="keyword">for</span> DB <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$&#123;DATABASES[@]&#125;</span>&quot;</span>; <span class="keyword">do</span></span><br><span class="line">    FILE_NAME=<span class="string">&quot;<span class="variable">$&#123;DB&#125;</span>_<span class="variable">$&#123;DATE&#125;</span>.sql.gz&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;正在备份 MySQL 数据库: <span class="variable">$DB</span>...&quot;</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 使用 mysqldump 并直接 gzip 压缩</span></span><br><span class="line">    <span class="comment"># --single-transaction: 保证备份期间不锁表（针对 InnoDB）</span></span><br><span class="line">    <span class="comment"># --routines: 备份存储过程和函数</span></span><br><span class="line">    docker <span class="built_in">exec</span> <span class="variable">$CONTAINER_NAME</span> mysqldump -u<span class="variable">$DB_USER</span> -p<span class="variable">$DB_PASSWORD</span> \</span><br><span class="line">        --single-transaction --routines --databases <span class="variable">$DB</span> | gzip &gt; <span class="variable">$BACKUP_DIR</span>/<span class="variable">$FILE_NAME</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> [ <span class="variable">$&#123;PIPESTATUS[0]&#125;</span> -eq 0 ]; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;上传 <span class="variable">$FILE_NAME</span> 到 R2...&quot;</span></span><br><span class="line">        rclone copy <span class="variable">$BACKUP_DIR</span>/<span class="variable">$FILE_NAME</span> <span class="variable">$R2_REMOTE</span>/mysql_daily/</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;错误: <span class="variable">$DB</span> 备份失败！&quot;</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># --- 4. 清理 ---</span></span><br><span class="line">find <span class="variable">$BACKUP_DIR</span> -mtime +<span class="variable">$RETENTION_DAYS</span> -<span class="built_in">exec</span> <span class="built_in">rm</span> &#123;&#125; \;</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;MySQL 备份任务完成。&quot;</span></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></pre></td><td class="code"><pre><span class="line">bash mysql-to-r2.sh</span><br></pre></td></tr></table></figure><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">cronteb -e</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><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 凌晨 02:00 备份 PostgreSQL</span></span><br><span class="line">0 2 * * * /bin/bash /data/script/pgsql-to-r2.sh &gt;&gt; /var/log/pg_backup.log 2&gt;&amp;1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 凌晨 03:00 备份 MySQL</span></span><br><span class="line">0 3 * * * /bin/bash /data/script/mysql-to-r2.sh &gt;&gt; /var/log/mysql_backup.log 2&gt;&amp;1</span><br></pre></td></tr></table></figure><h2 id="配置对象生命周期规则"><a href="#配置对象生命周期规则" class="headerlink" title="配置对象生命周期规则"></a>配置对象生命周期规则</h2><p>数据库文件比较小，乐意放几天放几天。我的习惯，30天肯定至少要访问一次的，所以就30天了。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/image-20260318215913289.webp" alt="image-20260318215913289"></p>]]>
    </content>
    <id>https://dev.net.cn/how-to-backup-data-to-cloudflare-r2/</id>
    <link href="https://dev.net.cn/how-to-backup-data-to-cloudflare-r2/"/>
    <published>2026-03-18T12:00:00.000Z</published>
    <summary>
      <![CDATA[<p>接上一篇，将能迁移的服务都迁移到PostgreSQL后，再配置上自动备份脚本，基本上就可以高枕无忧了，本来想备份到阿里云OSS的，想了想本站几乎是<code>ALL IN Cloudflare</code>，那就直接备份到<code>CloudFlare R2</code>吧，正好也快一点。下面就记录下备份的方法。</p>]]>
    </summary>
    <title>使用Rclone备份数据到CloudFlare R2</title>
    <updated>2026-03-18T12:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Umami" scheme="https://dev.net.cn/categories/Umami/"/>
    <category term="MySQL" scheme="https://dev.net.cn/tags/MySQL/"/>
    <category term="Docker" scheme="https://dev.net.cn/tags/Docker/"/>
    <category term="PostgreSQL" scheme="https://dev.net.cn/tags/PostgreSQL/"/>
    <content>
      <![CDATA[<p>今天抽空，将自己维护的服务都升级了一下，看了下<code>umami</code>从<code>v3</code>开始就不再支持<code>MySQL</code>，而我目前是用<code>MySql</code>版本的，本着<code>用新不用旧、能早升级早升级</code>的理念，那就只能升级加迁移数据库了，下面分享下过程。</p><h2 id="导出MySql的数据"><a href="#导出MySql的数据" class="headerlink" title="导出MySql的数据"></a>导出MySql的数据</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">docker <span class="built_in">exec</span> -i db mysqldump --no-create-info --default-character-set=utf8mb4 --quick --skip-add-locks \</span><br><span class="line">-u root -p umamidb &gt; /tmp/mydbdump.sql</span><br></pre></td></tr></table></figure><p>根据自己习惯来。</p><h2 id="定义环境变量"><a href="#定义环境变量" class="headerlink" title="定义环境变量"></a>定义环境变量</h2><p>在<code>docker-compose.yaml</code>同级目录下，创建<code>init-db</code>目录，里面创建一个文件<code>init.sql</code>。内容如下：</p><figure class="highlight postgresql"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">-- Umami的数据库初始化脚本</span></span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">USER</span> umamiuser <span class="keyword">WITH</span> <span class="keyword">PASSWORD</span> <span class="string">&#x27;password&#x27;</span>;</span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">USER</span> umamiuser <span class="keyword">CREATEDB</span>;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">DATABASE</span> umamidb <span class="keyword">OWNER</span> umamiuser;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- Waline 的数据库初始化脚本</span></span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">USER</span> waline_user <span class="keyword">WITH</span> <span class="keyword">PASSWORD</span> <span class="string">&#x27;password&#x27;</span>;</span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">USER</span> waline_user <span class="keyword">CREATEDB</span>;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">DATABASE</span> waline_db <span class="keyword">OWNER</span> waline_user;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在<code>docker-compose.yaml</code>同级目录下，编辑<code>.env</code>文件（没有就创建）</p><figure class="highlight properties"><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></pre></td><td class="code"><pre><span class="line"><span class="attr">MYSQL_ROOT_PASSWORD</span>=<span class="string">password</span></span><br><span class="line"><span class="attr">MYSQL_USER</span>=<span class="string">username</span></span><br><span class="line"><span class="attr">MYSQL_PASSWORD</span>=<span class="string">password</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># PG</span></span><br><span class="line"><span class="attr">POSTGRES_PASSWORD</span>=<span class="string">password</span></span><br><span class="line"><span class="attr">POSTGRES_USER</span>=<span class="string">postgres</span></span><br><span class="line"><span class="attr">POSTGRES_UMAMI_PWD</span>=<span class="string">password</span></span><br><span class="line"><span class="attr">POSTGRES_WALINE_PWD</span>=<span class="string">password</span></span><br><span class="line"><span class="comment"># SMTP</span></span><br><span class="line"><span class="attr">SMTP_PWD</span>=<span class="string">password</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># umami</span></span><br><span class="line"><span class="attr">UMAMI_APP_SECRET</span>=<span class="string">NiMZovEXm2dYdSfHb47sLcljvjFnPesxxxxxxxxxxxx</span></span><br><span class="line"><span class="attr">UMAMI_DATABASE_URL</span>=<span class="string">postgresql://umamiuser:password@db-pg:5432/umamidb</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># waline</span></span><br><span class="line"><span class="attr">WL_JWT_TOKEN</span>=<span class="string">31HHvaaXFJ984pLc2iCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</span></span><br><span class="line"><span class="attr">WL_AKISMET_KEY</span>=<span class="string">a93dxxxxxxxxxxxxxx</span></span><br><span class="line"><span class="attr">WL_PG_USER</span>=<span class="string">waline_user</span></span><br><span class="line"><span class="attr">WL_PG_DB</span>=<span class="string">waline_db</span></span><br><span class="line"><span class="attr">WL_TURNSTILE_KEY</span>=<span class="string">0x4AAxxxxxxxxxxxxxxxxxx</span></span><br><span class="line"><span class="attr">WL_TURNSTILE_SECRET</span>=<span class="string">0x4AAAxxxxxxxxxxxxxxxxxxxxxx</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>执行<code>docker compose config</code>，确认下配置是否生效</p><h2 id="修改docker-compose-yaml"><a href="#修改docker-compose-yaml" class="headerlink" title="修改docker-compose.yaml"></a>修改docker-compose.yaml</h2><p>在<code>docker-compose.yaml</code>中新增<code>postgresql</code>，并将原来的<code>umami</code>替换为<code>postgresql</code>版本。</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><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><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">db:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">mysql:8.4</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">db</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">env_file:</span> <span class="string">.env</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">dbdata:/var/lib/mysql</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD&quot;</span>, <span class="string">&quot;mysqladmin&quot;</span>, <span class="string">&quot;ping&quot;</span>, <span class="string">&quot;-h&quot;</span>, <span class="string">&quot;localhost&quot;</span>, <span class="string">&quot;-u&quot;</span>, <span class="string">&quot;hc_user&quot;</span>, <span class="string">&quot;--password=yourpassword&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">5s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">5s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">10</span></span><br><span class="line">      <span class="attr">start_period:</span> <span class="string">10s</span> <span class="comment"># 给 MySQL 10秒的宽限期执行初始化</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-network</span></span><br><span class="line">  <span class="attr">db-pg:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">postgres:17-alpine</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">postgresql</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">POSTGRES_USER:</span> <span class="string">postgres</span></span><br><span class="line">      <span class="attr">POSTGRES_PASSWORD:</span> <span class="string">$POSTGRES_PASSWORD</span></span><br><span class="line">      <span class="attr">POSTGRES_DB:</span> <span class="string">postgres</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">pg-data:/var/lib/postgresql/data</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./init-db:/docker-entrypoint-initdb.d</span></span><br><span class="line">    <span class="attr">healthcheck:</span></span><br><span class="line">      <span class="attr">test:</span> [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;pg_isready -U postgres -d postgres&quot;</span>]</span><br><span class="line">      <span class="attr">interval:</span> <span class="string">5s</span></span><br><span class="line">      <span class="attr">timeout:</span> <span class="string">5s</span></span><br><span class="line">      <span class="attr">retries:</span> <span class="number">5</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-network</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">wordpress:</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">db</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">wordpress:6.8.3-php8.4-fpm-alpine</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">wordpress</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">env_file:</span> <span class="string">.env</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">WORDPRESS_DB_HOST=db:3306</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">WORDPRESS_DB_USER=$MYSQL_USER</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">WORDPRESS_DB_NAME=wordpress</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">wordpress:/var/www/html</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./php-config/custom.ini:/usr/local/etc/php/conf.d/custom.ini</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-network</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">vps:</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">db</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">wordpress:6.8.3-php8.4-fpm-alpine</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">wp-vps</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">env_file:</span> <span class="string">.env</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">WORDPRESS_DB_HOST=db:3306</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">WORDPRESS_DB_USER=wp-vps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">WORDPRESS_DB_NAME=wp_vps</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">wp-vps:/var/www/html</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./php-config/custom.ini:/usr/local/etc/php/conf.d/custom.ini</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-network</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">webserver:</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">wordpress</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">vps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">umami</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">waline</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">nginx:1.28.0-alpine</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">webserver</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;80:80&quot;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;443:443&quot;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">wordpress:/var/www/html</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">wp-vps:/var/www/wp-vps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">umami-data:/var/www/umami</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">waline-data:/var/www/waline</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./nginx-conf:/etc/nginx/conf.d</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">certbot-etc:/etc/letsencrypt</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-network</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">umami:</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="attr">db-pg:</span></span><br><span class="line">        <span class="attr">condition:</span> <span class="string">service_healthy</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">ghcr.io/umami-software/umami:postgresql-latest</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">umami</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">expose:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&#x27;3000&#x27;</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">DATABASE_URL:</span> <span class="string">$&#123;UMAMI_DATABASE_URL&#125;</span></span><br><span class="line">      <span class="attr">DATABASE_TYPE:</span> <span class="string">postgresql</span></span><br><span class="line">      <span class="attr">APP_SECRET:</span> <span class="string">$&#123;UMAMI_APP_SECRET&#125;</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-network</span></span><br><span class="line">  </span><br><span class="line">  <span class="attr">waline:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">lizheming/waline:latest</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">waline</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">always</span></span><br><span class="line">    <span class="attr">expose:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;8360&quot;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">waline-data:/app/data</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">TZ:</span> <span class="string">&#x27;Asia/Shanghai&#x27;</span></span><br><span class="line">      <span class="comment"># 数据库设置</span></span><br><span class="line">      <span class="attr">PG_HOST:</span> <span class="string">&#x27;db-pg&#x27;</span></span><br><span class="line">      <span class="attr">PG_PORT:</span> <span class="string">&#x27;5432&#x27;</span></span><br><span class="line">      <span class="attr">PG_DB:</span> <span class="string">&#x27;$&#123;WL_PG_DB&#125;&#x27;</span></span><br><span class="line">      <span class="attr">PG_USER:</span> <span class="string">&#x27;$&#123;WL_PG_USER&#125;&#x27;</span></span><br><span class="line">      <span class="attr">PG_PASSWORD:</span> <span class="string">&#x27;$&#123;POSTGRES_WALINE_PWD&#125;&#x27;</span></span><br><span class="line">      <span class="attr">SITE_NAME:</span> <span class="string">&#x27;码农笔记&#x27;</span></span><br><span class="line">      <span class="attr">SITE_URL:</span> <span class="string">&#x27;https://tech.tvzr.com&#x27;</span></span><br><span class="line">      <span class="attr">SECURE_DOMAINS:</span> <span class="string">&#x27;tech.tvzr.com,waline.tvzr.com&#x27;</span></span><br><span class="line">      <span class="attr">AUTHOR_EMAIL:</span> <span class="string">&#x27;me@tvzr.com&#x27;</span></span><br><span class="line">      <span class="attr">IPQPS:</span> <span class="number">20</span></span><br><span class="line">      <span class="attr">JWT_TOKEN:</span> <span class="string">&#x27;$&#123;WL_JWT_TOKEN&#125;&#x27;</span></span><br><span class="line">      <span class="attr">LEVELS:</span> <span class="string">&#x27;0,10,20,50,100,200&#x27;</span></span><br><span class="line">      <span class="attr">AKISMET_KEY:</span> <span class="string">&#x27;$&#123;WL_AKISMET_KEY&#125;&#x27;</span></span><br><span class="line">      <span class="comment">#TURNSTILE_KEY: &#x27;$&#123;WL_TURNSTILE_KEY&#125;&#x27;</span></span><br><span class="line">      <span class="comment">#TURNSTILE_SECRET: &#x27;$&#123;WL_TURNSTILE_SECRET&#125;&#x27;</span></span><br><span class="line">      <span class="attr">SMTP_HOST:</span> <span class="string">&#x27;mail.tvzr.com&#x27;</span></span><br><span class="line">      <span class="attr">SMTP_PORT:</span> <span class="string">&#x27;465&#x27;</span></span><br><span class="line">      <span class="attr">SMTP_USER:</span> <span class="string">&#x27;no.reply@tvzr.com&#x27;</span></span><br><span class="line">      <span class="attr">SMTP_PASS:</span> <span class="string">&#x27;$&#123;SMTP_PWD&#125;&#x27;</span></span><br><span class="line">      <span class="attr">SMTP_SECURE:</span> <span class="string">&#x27;true&#x27;</span></span><br><span class="line">      <span class="attr">SENDER_NAME:</span> <span class="string">&#x27;码农笔记&#x27;</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="attr">db-pg:</span></span><br><span class="line">        <span class="attr">condition:</span> <span class="string">service_healthy</span></span><br><span class="line">    <span class="attr">networks:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">app-network</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">certbot:</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">webserver</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">certbot/certbot</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">certbot</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">certbot-etc:/etc/letsencrypt</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">wordpress:/var/www/html</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">wp-vps:/var/www/wp-vps</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">umami-data:/var/www/umami</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">waline-data:/var/www/waline</span></span><br><span class="line">    <span class="attr">command:</span> <span class="string">&gt;</span></span><br><span class="line"><span class="string">      certonly --webroot </span></span><br><span class="line"><span class="string">      --non-interactive </span></span><br><span class="line"><span class="string">      --expand</span></span><br><span class="line"><span class="string">      -w /var/www/html -d tvzr.com </span></span><br><span class="line"><span class="string">      -w /var/www/wp-vps -d vps.tvzr.com </span></span><br><span class="line"><span class="string">      --email iat@outlook.com </span></span><br><span class="line"><span class="string">      --agree-tos </span></span><br><span class="line"><span class="string">      --no-eff-email </span></span><br><span class="line"><span class="string">      --force-renewal</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="attr">volumes:</span></span><br><span class="line">  <span class="attr">certbot-etc:</span></span><br><span class="line">  <span class="attr">wordpress:</span></span><br><span class="line">  <span class="attr">dbdata:</span></span><br><span class="line">  <span class="attr">wp-vps:</span></span><br><span class="line">  <span class="attr">umami-data:</span></span><br><span class="line">  <span class="attr">waline-data:</span></span><br><span class="line">  <span class="attr">pg-data:</span></span><br><span class="line"></span><br><span class="line"><span class="attr">networks:</span></span><br><span class="line">  <span class="attr">app-network:</span></span><br><span class="line">    <span class="attr">driver:</span> <span class="string">bridge</span></span><br></pre></td></tr></table></figure><h2 id="重新启动docker-compose"><a href="#重新启动docker-compose" class="headerlink" title="重新启动docker compose"></a>重新启动docker compose</h2><p>在<code>docker-compose.yml</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"><span class="comment"># 停止</span></span><br><span class="line">docker compose down</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动</span></span><br><span class="line">docker compose up -d</span><br><span class="line"><span class="comment"># 此时会自动拉取最新的镜像</span></span><br></pre></td></tr></table></figure><p>启动时，<code>umami</code>会自动检测到URL变更，并且自动初始化所需要的表。</p><p>可以通过<code>docker logs -f umami</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></pre></td><td class="code"><pre><span class="line">All migrations have been successfully applied.</span><br><span class="line"></span><br><span class="line">✓ Database is up to <span class="built_in">date</span>.</span><br><span class="line"></span><br><span class="line">&gt; umami@3.0.3 update-tracker /app</span><br><span class="line">&gt; node scripts/update-tracker.js</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&gt; umami@3.0.3 start-server /app</span><br><span class="line">&gt; node server.js</span><br><span class="line"></span><br><span class="line">   ▲ Next.js 15.5.9</span><br><span class="line">   - Local:        http://localhost:3000</span><br><span class="line">   - Network:      http://0.0.0.0:3000</span><br><span class="line"></span><br><span class="line"> ✓ Starting...</span><br><span class="line"> ✓ Ready <span class="keyword">in</span> 1235m</span><br></pre></td></tr></table></figure><h2 id="转换mysql导出的表"><a href="#转换mysql导出的表" class="headerlink" title="转换mysql导出的表"></a>转换mysql导出的表</h2><p>mysql导出的表不能直接给postgresql使用，可以参考官网的方案进行处理。<a href="https://docs.umami.is/docs/guides/migrate-mysql-postgresql">将MySQL迁移到PostgreSQL</a></p><h3 id="用双引号替换反勾号，使其兼容PostgreSQL。"><a href="#用双引号替换反勾号，使其兼容PostgreSQL。" class="headerlink" title="用双引号替换反勾号，使其兼容PostgreSQL。"></a>用双引号替换反勾号，使其兼容PostgreSQL。</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">sed -i <span class="string">&#x27;s/`/&quot;/g&#x27;</span> mydbdump.sql</span><br></pre></td></tr></table></figure><h3 id="清空postgresql的数据"><a href="#清空postgresql的数据" class="headerlink" title="清空postgresql的数据"></a>清空postgresql的数据</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><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">INSERT 0 13</span><br><span class="line">INSERT 0 201</span><br><span class="line">INSERT 0 1</span><br><span class="line">INSERT 0 2</span><br><span class="line">ERROR:  duplicate key value violates unique constraint <span class="string">&quot;user_pkey&quot;</span></span><br><span class="line">DETAIL:  Key (user_id)=(41e2b680-648e-4b09-bcd7-3e2b10c06264) already exists.</span><br><span class="line">INSERT 0 1</span><br><span class="line">INSERT 0 38</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">docker <span class="built_in">exec</span> -i psql -U umamiuser -d umamidb -c <span class="string">&quot;TRUNCATE TABLE \&quot;user\&quot;, \&quot;session\&quot;, \&quot;website\&quot;, \&quot;team\&quot;, \&quot;team_user\&quot;, \&quot;_prisma_migrations\&quot; CASCADE;&quot;</span></span><br><span class="line">TRUNCATE TABLE</span><br></pre></td></tr></table></figure><h3 id="导入数据到postgresql"><a href="#导入数据到postgresql" class="headerlink" title="导入数据到postgresql"></a>导入数据到postgresql</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">docker <span class="built_in">exec</span> -i postgresql psql -U umamiuser -d umamidb &lt; /tmp/mydbdump.sql</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><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">INSERT 0 13</span><br><span class="line">INSERT 0 201</span><br><span class="line">INSERT 0 1</span><br><span class="line">INSERT 0 2</span><br><span class="line">INSERT 0 2</span><br><span class="line">INSERT 0 1</span><br><span class="line">INSERT 0 386</span><br></pre></td></tr></table></figure><h2 id="升级完成"><a href="#升级完成" class="headerlink" title="升级完成"></a>升级完成</h2><p>到这里就升级完成了，整个过程还是比较简单和顺利的。对比之前，我就需要多运行一个<code>postgresql</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">CONTAINER ID   NAME         CPU %     MEM USAGE / LIMIT    MEM %     NET I/O           BLOCK I/O         PIDS </span><br><span class="line">520d2037e3b8   webserver    0.00%     9.168MiB / 3.83GiB   0.23%     12.6MB / 14.3MB   9.34MB / 4.1kB    4 </span><br><span class="line">1857b85d681c   umami        0.00%     229.4MiB / 3.83GiB   5.85%     1.15MB / 2.09MB   41.5MB / 16.4kB   44 </span><br><span class="line">4c2f0afb1926   waline       0.00%     169MiB / 3.83GiB     4.31%     33.2kB / 14.3kB   67.1MB / 4.1kB    18 </span><br><span class="line">99783b642219   postgresql   0.02%     33.93MiB / 3.83GiB   0.87%     202kB / 120kB     7.67MB / 88.4MB   7 </span><br><span class="line">f35027f6d422   db           1.26%     460MiB / 3.83GiB     11.73%    8.06MB / 119MB    941MB / 163MB     47 </span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://dev.net.cn/migrating-umami-to-v3-with-postgresql/</id>
    <link href="https://dev.net.cn/migrating-umami-to-v3-with-postgresql/"/>
    <published>2026-03-18T03:00:00.000Z</published>
    <summary>
      <![CDATA[<p>今天抽空，将自己维护的服务都升级了一下，看了下<code>umami</code>从<code>v3</code>开始就不再支持<code>MySQL</code>，而我目前是用<code>MySql</code>版本的，本着<code>用新不用旧、能早升级早升级</cod]]>
    </summary>
    <title>升级umami-mysql到v3-postgresql</title>
    <updated>2026-03-18T03:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Git" scheme="https://dev.net.cn/categories/Git/"/>
    <category term="Git" scheme="https://dev.net.cn/tags/Git/"/>
    <category term="GitHub" scheme="https://dev.net.cn/tags/GitHub/"/>
    <content>
      <![CDATA[<p>最近将大部分的开发工具都由WinGet替换为scoop了，一切配置妥当后今天发现给GitHub提交代码时，需要重新验证账号，但通过浏览器认证后一直提示一个错误：<code>fatal: ServicePointManager 不支持具有 socks5 方案的代理</code>，我配置代理一般都是<code>http_proxy</code>，因为它兼容性更好，但此时出现的错误又的确是<code>socks5</code>的问题，想来是多年前配置的了，一直使用也没啥问题，后来我删除了<code>credential</code>中的github账号信息，又出现了这个问题。</p><span id="more"></span><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><p>出现这个问题也比较容易解决，只需要查看下<code>git config</code>，看下都是哪里配置了<code>socks5</code>协议的代理。</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">git config --global --list </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">http.https://github.com.proxy=socks5://127.0.0.1:1080</span><br><span class="line">http.https://github.com.proxy=socks5://127.0.0.1:1080</span><br></pre></td></tr></table></figure><p>将其覆盖一下即可，我本地监听端口是<code>1080</code>，一般默认的是<code>7890</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></pre></td><td class="code"><pre><span class="line">git config --global http.proxy <span class="string">&#x27;http://127.0.0.1:1080&#x27;</span></span><br><span class="line">git config --global https.proxy <span class="string">&#x27;http://127.0.0.1:1080&#x27;</span></span><br><span class="line">git config --global http.https://github.com.proxy <span class="string">&#x27;http://127.0.0.1:1080&#x27;</span></span><br></pre></td></tr></table></figure><h2 id="GitHub账号配置"><a href="#GitHub账号配置" class="headerlink" title="GitHub账号配置"></a>GitHub账号配置</h2><p>我本地是配置了ssh-key的，不过也有大量的<code>https://</code>的github项目，懒得一一修改了。直接在<code>GitHub点击头像</code> -&gt; <code>settings</code> -&gt; <code>Developer settings（最下面）</code> -&gt; <code>Personal access tokens</code> -&gt; <code>Tokens(classic)</code>中，点击右上脚的<code>Generate new token</code>按钮，选择<code>Generate new token(classic)</code>，创建新的Token，输出2FA密码后，权限只需要全选<code>repo</code>即可，有效期就一年吧。将生成的token作为GitHub的密码填入即可。</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></pre></td><td class="code"><pre><span class="line">Username for &#x27;https://github.com&#x27;: xxx    </span><br><span class="line">Password for &#x27;https://xxx@github.com&#x27;: </span><br><span class="line">Enumerating objects: 5, done.</span><br><span class="line">Counting objects: 100% (5/5), done.</span><br><span class="line">Delta compression using up to 20 threads</span><br></pre></td></tr></table></figure><h2 id="Git其他配置优化"><a href="#Git其他配置优化" class="headerlink" title="Git其他配置优化"></a>Git其他配置优化</h2><h3 id="开启安全验证"><a href="#开启安全验证" class="headerlink" title="开启安全验证"></a>开启安全验证</h3><p>因为以前公司的Git仓库都是自己签发的证书，所以我关闭了<code>http.sslVerify</code>，现在都是使用GitHub，索性就全部打开吧。</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="comment"># 开启全局安全验证</span></span><br><span class="line">git config --global http.sslVerify <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>当然，以后可能还会使用局域网内部的git服务，那就到时候根据地址单独配置即可。</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"><span class="comment"># 给内网地址关闭安全验证</span></span><br><span class="line">git config --global http.<span class="string">&quot;https://10.254.32.11/&quot;</span>.sslVerify <span class="literal">false</span></span><br><span class="line">git config --global http.<span class="string">&quot;http://10.40.60.22/&quot;</span>.sslVerify <span class="literal">false</span></span><br></pre></td></tr></table></figure><h3 id="美化log输出"><a href="#美化log输出" class="headerlink" title="美化log输出"></a>美化log输出</h3><p>你现在的 <code>git log</code> 应该是默认的黑白列表。既然用了 <code>pwsh</code> (PowerShell Core) 和图标字体，可以加一个酷炫的多彩 Graph 视图。</p><p><strong>添加一个别名 <code>git lg</code>：</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">git config --global alias.lg <span class="string">&quot;log --color --graph --pretty=format:&#x27;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset&#x27; --abbrev-commit&quot;</span></span><br></pre></td></tr></table></figure><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><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"><span class="comment"># 1. 性能起飞：开启 fsmonitor</span></span><br><span class="line">git config --global core.fsmonitor <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 路径支持</span></span><br><span class="line">git config --global gui.encoding utf-8</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 换行符处理（Windows 必备，防止拉取代码后全是修改）</span></span><br><span class="line">git config --global core.autocrlf <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 开启更智能的合并策略</span></span><br><span class="line">git config --global pull.rebase <span class="literal">true</span></span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://dev.net.cn/servicepointmanager-socks5-proxy-not-supported-error/</id>
    <link href="https://dev.net.cn/servicepointmanager-socks5-proxy-not-supported-error/"/>
    <published>2026-03-17T04:00:00.000Z</published>
    <summary>
      <![CDATA[<p>最近将大部分的开发工具都由WinGet替换为scoop了，一切配置妥当后今天发现给GitHub提交代码时，需要重新验证账号，但通过浏览器认证后一直提示一个错误：<code>fatal: ServicePointManager 不支持具有 socks5 方案的代理</code>，我配置代理一般都是<code>http_proxy</code>，因为它兼容性更好，但此时出现的错误又的确是<code>socks5</code>的问题，想来是多年前配置的了，一直使用也没啥问题，后来我删除了<code>credential</code>中的github账号信息，又出现了这个问题。</p>]]>
    </summary>
    <title>ServicePointManager不支持具有socks5方案的代理</title>
    <updated>2026-03-17T04:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Windows" scheme="https://dev.net.cn/categories/Windows/"/>
    <category term="Windows" scheme="https://dev.net.cn/tags/Windows/"/>
    <category term="Scoop" scheme="https://dev.net.cn/tags/Scoop/"/>
    <content>
      <![CDATA[<p>最近也是将大量的软件管理从<code>WinGet</code>切换到<code>scoop</code>，WinGet总是出现一些幽灵链接，虽然可以通过注册表扫描等方式将其修复，个人还是很反感注册表。索性将能用scoop管理的也都用scoop管理，不过在使用过程中，还是遇到了一点点问题，也是比较容易解决。</p><span id="more"></span><h2 id="由于连接方在一段时间后没有正确答复或连接的主机没有反应，连接尝试失败。"><a href="#由于连接方在一段时间后没有正确答复或连接的主机没有反应，连接尝试失败。" class="headerlink" title="由于连接方在一段时间后没有正确答复或连接的主机没有反应，连接尝试失败。"></a>由于连接方在一段时间后没有正确答复或连接的主机没有反应，连接尝试失败。</h2><p>这个问题应该也比较容易遇到，本质上就是万恶的GFW，导致某些资源无法连接（S3、google cloud等），这里需要来一手代理即可。</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">scoop config proxy <span class="number">127.0</span>.<span class="number">0.1</span>:<span class="number">1080</span></span><br></pre></td></tr></table></figure><p>如果想取消，则执行下面的命令</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">scoop config <span class="built_in">rm</span> proxy</span><br></pre></td></tr></table></figure><h2 id="Couldn’t-find-manifest-for-‘xxx’"><a href="#Couldn’t-find-manifest-for-‘xxx’" class="headerlink" title="Couldn’t find manifest for ‘xxx’"></a>Couldn’t find manifest for ‘xxx’</h2><p>安装miniconda时会出现这个错误是因为 miniconda3 不在 Scoop 的 Main（核心）软件库中，它被收录在专门存放编程相关工具的 Extras 软件库里。只需要添加一下即可。</p><figure class="highlight powershell"><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">scoop bucket add extras</span><br><span class="line">// 然后重新安装</span><br><span class="line">scoop install miniconda3</span><br></pre></td></tr></table></figure><h2 id="Token-might-be-misconfigured"><a href="#Token-might-be-misconfigured" class="headerlink" title="Token might be misconfigured"></a>Token might be misconfigured</h2><p>很久以前就安装了scoop，但是那个时候只用来管理字体，所以也是很久没正经用过了。为了更新字体的版本，出现了如下这个错误</p><figure class="highlight powershell"><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></pre></td><td class="code"><pre><span class="line">JetBrainsMono<span class="literal">-NF</span>: <span class="number">2.1</span>.<span class="number">0</span> -&gt; <span class="number">3.4</span>.<span class="number">0</span></span><br><span class="line"></span><br><span class="line">Updating one outdated app:</span><br><span class="line"></span><br><span class="line">Updating <span class="string">&#x27;JetBrainsMono-NF&#x27;</span> (<span class="number">2.1</span>.<span class="number">0</span> -&gt; <span class="number">3.4</span>.<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">Downloading new version</span><br><span class="line"></span><br><span class="line">WARN  Token might be misconfigured.</span><br><span class="line"></span><br><span class="line">OperationStopped: C:\Users\xxx\scoop\apps\scoop\current\lib\download.ps1:<span class="number">84</span></span><br><span class="line"></span><br><span class="line">Line </span><br><span class="line"></span><br><span class="line">  <span class="number">84</span>           <span class="keyword">throw</span> <span class="variable">$e</span></span><br><span class="line"></span><br><span class="line">               ~~~~~~~~</span><br><span class="line"></span><br><span class="line">      Response status code does not indicate success: <span class="number">401</span> (Unauthorized). </span><br></pre></td></tr></table></figure><p>看样子是github token过期了，后来申请了新的token，通过如下方式配置后，发现还是不行：</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">scoop config github_token &lt;你的Token内容&gt;</span><br></pre></td></tr></table></figure><p>搜索一番后，发现以前配置的似乎是<code>gh_token</code> ，于是将其删除后问题解决。当时也忘记了为啥要配置这个了。</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">scoop config <span class="built_in">rm</span> gh_token </span><br></pre></td></tr></table></figure><p>后面遇到了，再更新~</p>]]>
    </content>
    <id>https://dev.net.cn/how-to-fix-common-scoop-errors-on-windows/</id>
    <link href="https://dev.net.cn/how-to-fix-common-scoop-errors-on-windows/"/>
    <published>2026-03-16T04:54:53.000Z</published>
    <summary>
      <![CDATA[<p>最近也是将大量的软件管理从<code>WinGet</code>切换到<code>scoop</code>，WinGet总是出现一些幽灵链接，虽然可以通过注册表扫描等方式将其修复，个人还是很反感注册表。索性将能用scoop管理的也都用scoop管理，不过在使用过程中，还是遇到了一点点问题，也是比较容易解决。</p>]]>
    </summary>
    <title>Windows Scoop工具常见错误及处理方式</title>
    <updated>2026-03-16T04:54:53.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="OpenClaw" scheme="https://dev.net.cn/categories/OpenClaw/"/>
    <category term="OpenClaw" scheme="https://dev.net.cn/tags/OpenClaw/"/>
    <content>
      <![CDATA[<p>通过前文配置后OpenClaw后，如果需要运行一些自动化任务、抓取数据等需求还需要通过浏览器来实现。但是默认debian是没有安装的浏览器的，本篇介绍下如何给Debian安装浏览器，并且配置到OpenClaw中。</p><h2 id="下载Chrome浏览器"><a href="#下载Chrome浏览器" class="headerlink" title="下载Chrome浏览器"></a>下载Chrome浏览器</h2><p>对于Debian&#x2F;Ubuntu发行版</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">wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb</span><br></pre></td></tr></table></figure><p>对于CentOS&#x2F;RHEL发行版</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">wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm</span><br></pre></td></tr></table></figure><p>一般deb和rpm包就覆盖了国内大部分用户的发行版。这个地址是可以直接连接的。</p><h2 id="安装浏览器和字体"><a href="#安装浏览器和字体" class="headerlink" title="安装浏览器和字体"></a>安装浏览器和字体</h2><p>对于Debian&#x2F;Ubuntu发行版</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">sudo apt install -y ./google-chrome-stable_current_amd64.deb</span><br></pre></td></tr></table></figure><p>对于CentOS&#x2F;RHEL发行版</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">sudo yum install -y liberation-fonts</span><br><span class="line">sudo yum install -y xdg-utils</span><br><span class="line">sudo yum localinstall -y ./google-chrome-stable_current_x86_64.rpm</span><br></pre></td></tr></table></figure><p>安装<strong>Google Noto Sans CJK</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></pre></td><td class="code"><pre><span class="line">// debian/ubuntu</span><br><span class="line">sudo apt install -y fonts-noto-cjk</span><br><span class="line">// CentOS/RHEL</span><br><span class="line">sudo yum install -y google-noto-sans-cjk-fonts</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line">google-chrome --version</span><br><span class="line"></span><br><span class="line">Google Chrome 146.0.7680.75 </span><br></pre></td></tr></table></figure><h2 id="配置OpenClaw"><a href="#配置OpenClaw" class="headerlink" title="配置OpenClaw"></a>配置OpenClaw</h2><h3 id="使用独立浏览器"><a href="#使用独立浏览器" class="headerlink" title="使用独立浏览器"></a>使用独立浏览器</h3><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">openclaw config set browser.defaultProfile &quot;openclaw&quot;</span><br></pre></td></tr></table></figure><h3 id="使用Headless模式（服务器上没显示器-）"><a href="#使用Headless模式（服务器上没显示器-）" class="headerlink" title="使用Headless模式（服务器上没显示器~）"></a>使用Headless模式（服务器上没显示器~）</h3><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">openclaw config set browser.headless true</span><br></pre></td></tr></table></figure><h3 id="禁用沙盒模式"><a href="#禁用沙盒模式" class="headerlink" title="禁用沙盒模式"></a>禁用沙盒模式</h3><p>避免因权限安全机制无法启动</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">openclaw config set browser.noSandbox true</span><br></pre></td></tr></table></figure><h3 id="设置-Chrome-可执行文件路径"><a href="#设置-Chrome-可执行文件路径" class="headerlink" title="设置 Chrome 可执行文件路径"></a>设置 Chrome 可执行文件路径</h3><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">openclaw config set browser.executablePath &quot;$(which google-chrome)&quot;</span><br></pre></td></tr></table></figure><h3 id="重启-openclaw-gateway"><a href="#重启-openclaw-gateway" class="headerlink" title="重启 openclaw gateway"></a>重启 openclaw gateway</h3><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">openclaw gateway restart</span><br></pre></td></tr></table></figure><h3 id="为-openclaw-打开浏览器"><a href="#为-openclaw-打开浏览器" class="headerlink" title="为 openclaw 打开浏览器"></a>为 openclaw 打开浏览器</h3><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">openclaw browser start</span><br></pre></td></tr></table></figure><p>执行命令后，会有如下内容打印：</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">🦞 browser [openclaw] running: true</span><br></pre></td></tr></table></figure><p>没注意看，也可以通过如下命令检查</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">openclaw browser status</span><br></pre></td></tr></table></figure><h2 id="使用QQ-Bot测试一下"><a href="#使用QQ-Bot测试一下" class="headerlink" title="使用QQ Bot测试一下"></a>使用QQ Bot测试一下</h2><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-12.png?x-oss-process=style/large"></p><p>让其截图一下试试</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-13.png?x-oss-process=style/large"></p><p>还能修正一下错别字~</p>]]>
    </content>
    <id>https://dev.net.cn/configure-headless-browser-for-openclaw-debian-server/</id>
    <link href="https://dev.net.cn/configure-headless-browser-for-openclaw-debian-server/"/>
    <published>2026-03-13T08:17:31.000Z</published>
    <summary>
      <![CDATA[<p>通过前文配置后OpenClaw后，如果需要运行一些自动化任务、抓取数据等需求还需要通过浏览器来实现。但是默认debian是没有安装的浏览器的，本篇介绍下如何给Debian安装浏览器，并且配置到OpenClaw中。</p>
<h2 id="下载Chrome浏览器"><a hr]]>
    </summary>
    <title>给Debian服务器上的OpenClaw安装浏览器</title>
    <updated>2026-03-13T08:17:31.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="OpenClaw" scheme="https://dev.net.cn/categories/OpenClaw/"/>
    <category term="OpenClaw" scheme="https://dev.net.cn/tags/OpenClaw/"/>
    <category term="AI" scheme="https://dev.net.cn/tags/AI/"/>
    <content>
      <![CDATA[<h2 id="环境安装"><a href="#环境安装" class="headerlink" title="环境安装"></a>环境安装</h2><p>以Debian为例，配置好SSH-KEY（本机 -&gt; 服务器免密码登录），提前注册号阿里云百炼模型、Kimi模型、DeepSeek模型、bigmodel(GLM)等模型的账号，该实名实名，该充值充值（Kimi充值才能解速）。</p><span id="more"></span><h3 id="安装nvm"><a href="#安装nvm" class="headerlink" title="安装nvm"></a>安装nvm</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></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt update </span><br><span class="line"><span class="built_in">sudo</span> apt upgrade </span><br><span class="line">// 安装依赖</span><br><span class="line"><span class="built_in">sudo</span> apt install build-essential libssl-dev </span><br><span class="line">// 安装nvm</span><br><span class="line">curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh  bash </span><br><span class="line">// 重新打开session即可。</span><br><span class="line">// 安装nodejs 24</span><br><span class="line">nvm install 24</span><br><span class="line">// 切换到nvm</span><br><span class="line">nve use 24</span><br></pre></td></tr></table></figure><h3 id="安装git"><a href="#安装git" class="headerlink" title="安装git"></a>安装git</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">sudo</span> apt install git -y</span><br></pre></td></tr></table></figure><h2 id="安装OpenClaw"><a href="#安装OpenClaw" class="headerlink" title="安装OpenClaw"></a>安装OpenClaw</h2><p>本篇使用npm的方式安装</p><p>如果你的服务器没有配置ssh-key到github，那么你还需要配置一下，将ssh替换为https</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">git config --global url.<span class="string">&quot;https://github.com/&quot;</span>.insteadOf ssh://git@github.com/</span><br><span class="line">git config --global url.<span class="string">&quot;https://&quot;</span>.insteadOf git://</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">npm install -g openclaw@latest</span><br><span class="line"></span><br><span class="line">openclaw onboard --install-daemon</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><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// 脚本负责节点检测、安装和引导</span><br><span class="line">curl -fsSL https://openclaw.ai/install.sh  bash</span><br><span class="line">//或者 只安装二进制</span><br><span class="line">curl -fsSL https://openclaw.ai/install.sh  bash -s -- --no-onboard</span><br></pre></td></tr></table></figure><h2 id="配置OpenClaw"><a href="#配置OpenClaw" class="headerlink" title="配置OpenClaw"></a>配置OpenClaw</h2><h3 id="安全加固免责申明。"><a href="#安全加固免责申明。" class="headerlink" title="安全加固免责申明。"></a>安全加固免责申明。</h3><p>在上一步中，执行了<code>openclaw onboard --install-daemon</code> 命令后，会打开如下所示的内容：</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image.png?x-oss-process=style/large"></p><p>这里通过方向键，选择Yes，回车。</p><h3 id="Onboarding-mode（引导模式）"><a href="#Onboarding-mode（引导模式）" class="headerlink" title="Onboarding mode（引导模式）"></a>Onboarding mode（引导模式）</h3><p>这里选择QuickStart即可。</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-1.png?x-oss-process=style/full"></p><h3 id="Model-auth-Provider-（模型验证）"><a href="#Model-auth-Provider-（模型验证）" class="headerlink" title="Model&#x2F;auth Provider （模型验证）"></a>Model&#x2F;auth Provider （模型验证）</h3><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-2.png?x-oss-process=style/large"></p><p>内置的暂时不需要，我们选择<code>Custom Provider</code> 。</p><p>此时，会让你输入API Base URL,我们以阿里云百炼模型Qwen为例。</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-3.png?x-oss-process=style/full"></p><p>填入阿里云百炼模型URL，选择API Key验证，填写百炼模型的<code>API Key</code>，然后选择<code>OpenAI-compatible</code>，然后输入模型，目前免费体验的模型有qweb3.5-plus（100Wtoken）,当然还有其他的这里只选择一个即可，后面的再添加就是了。</p><h3 id="Select-channel（选择哪个平台的机器人）"><a href="#Select-channel（选择哪个平台的机器人）" class="headerlink" title="Select channel（选择哪个平台的机器人）"></a>Select channel（选择哪个平台的机器人）</h3><p>因为提前创建了飞书、钉钉的机器人，这里就选择飞书，如果没有任何机器人可以选择Skip for now（后续还可以再次添加和修改）。</p><p>选择使用自带的Feishu，然后填写相关信息</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-4.png?x-oss-process=style/large"></p><h3 id="Web-search"><a href="#Web-search" class="headerlink" title="Web search"></a>Web search</h3><p>这个建议使用Kimi的吧，去<a href="https://platform.moonshot.cn/console/api-keys">Moonshot AI 开放平台 - Kimi K2.5 大模型 API 服务</a> 创建一个Key，填写进去即可。其他的就随便。</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-5.png?x-oss-process=style/large"></p><p>此时就安装配置完成了。</p><h3 id="自定义配置"><a href="#自定义配置" class="headerlink" title="自定义配置"></a>自定义配置</h3><p>后面就可以通古WebUI、修改配置文件、命令等方式进行自定义配置了。</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">openclaw configure --section models</span><br></pre></td></tr></table></figure><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-6.png?x-oss-process=style/large"></p><p>选择Local，然后一直到模型，继续选择<code>Custom Provider</code>，接着填写新模型</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-7.png?x-oss-process=style/full"></p><h2 id="通过隧道在本地访问"><a href="#通过隧道在本地访问" class="headerlink" title="通过隧道在本地访问"></a>通过隧道在本地访问</h2><p>默认OpenClaw只绑定127.0.0.1，也非常不建议大家为了方便去反向代理暴露在公网。通常我们使用SSH 隧道连接到这台服务器上，然后在本地打开。</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 -i C:\Users\xxx\.ssh\vps-server -L 18790:127.0.0.1:18789 root@服务器IP地址</span><br></pre></td></tr></table></figure><ul><li>-i C:\Users\xxx\.ssh\vps-server，表示我是用本地名为vps-server密钥登陆。没配置SSH-KEY登录服务器的同学可以使用密码。</li><li>-L 绑定端口。</li></ul><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-8-scaled.png?x-oss-process=style/large"></p><p>登陆时需要一个token，或者你使用密码也行（需要自己修改配置）</p><p>Token，在你重启gateway时就可以看到</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-9.png?x-oss-process=style/large"></p><h2 id="接入QQ"><a href="#接入QQ" class="headerlink" title="接入QQ"></a>接入QQ</h2><p>打开<a href="https://q.qq.com/#/">QQ开放平台</a>，官方页面会有个OpenClaw快捷开通的链接，点击，创建机器人即可。</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-10.png?x-oss-process=style/large"></p><p>按照文档接入即可。</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/03/image-11.png?x-oss-process=style/large"></p>]]>
    </content>
    <id>https://dev.net.cn/install-openclaw-debian/</id>
    <link href="https://dev.net.cn/install-openclaw-debian/"/>
    <published>2026-03-06T05:42:22.000Z</published>
    <summary>
      <![CDATA[<h2 id="环境安装"><a href="#环境安装" class="headerlink" title="环境安装"></a>环境安装</h2><p>以Debian为例，配置好SSH-KEY（本机 -&gt; 服务器免密码登录），提前注册号阿里云百炼模型、Kimi模型、DeepSeek模型、bigmodel(GLM)等模型的账号，该实名实名，该充值充值（Kimi充值才能解速）。</p>]]>
    </summary>
    <title>Debian安装OpenClaw</title>
    <updated>2026-03-06T05:42:22.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="OpenClaw" scheme="https://dev.net.cn/categories/OpenClaw/"/>
    <category term="OpenClaw" scheme="https://dev.net.cn/tags/OpenClaw/"/>
    <category term="AI" scheme="https://dev.net.cn/tags/AI/"/>
    <content>
      <![CDATA[<h2 id="OpenClaw介绍"><a href="#OpenClaw介绍" class="headerlink" title="OpenClaw介绍"></a>OpenClaw介绍</h2><p>OpenClaw 是一个开源、本地部署的 AI Agent 网关。它的核心思路不是“只回答问题”，而是让 AI 具备执行动作的能力，例如访问网页、运行命令、调度任务、连接聊天渠道和管理会话。根据资料，它原先还经历过名称变动：先后出现过 Clawdbot、Moltbot，最终在 2026 年 1 月底确定为 OpenClaw。</p><span id="more"></span><h2 id="安装OpenClaw-环境依赖"><a href="#安装OpenClaw-环境依赖" class="headerlink" title="安装OpenClaw 环境依赖"></a>安装OpenClaw 环境依赖</h2><h3 id="安装NVM"><a href="#安装NVM" class="headerlink" title="安装NVM"></a>安装NVM</h3><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">scoop install nvm</span><br></pre></td></tr></table></figure><h3 id="安装nodejs24"><a href="#安装nodejs24" class="headerlink" title="安装nodejs24"></a>安装nodejs24</h3><figure class="highlight powershell"><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">nvm install <span class="number">24</span></span><br><span class="line"></span><br><span class="line">nvm use <span class="number">24</span></span><br></pre></td></tr></table></figure><h3 id="安装git"><a href="#安装git" class="headerlink" title="安装git"></a>安装git</h3><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">scoop install git</span><br></pre></td></tr></table></figure><h3 id="设置git"><a href="#设置git" class="headerlink" title="设置git"></a>设置git</h3><p>默认似乎用的是<code>ssh://协议</code>，如果本地没有配置ssh-key就会报错。可以通过配置将其替换为<code>https://</code></p><figure class="highlight powershell"><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">git config <span class="literal">--global</span> url.<span class="string">&quot;https://github.com/&quot;</span>.insteadOf ssh://git@github.com/</span><br><span class="line">git config <span class="literal">--global</span> url.<span class="string">&quot;https://&quot;</span>.insteadOf git://</span><br></pre></td></tr></table></figure><h3 id="安装OpenClaw"><a href="#安装OpenClaw" class="headerlink" title="安装OpenClaw"></a>安装OpenClaw</h3><p>确认node版本是22以上，推荐<code>nodejs 24</code>。</p><figure class="highlight powershell"><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">node <span class="literal">-v</span></span><br><span class="line"></span><br><span class="line">v24.<span class="number">14.0</span></span><br></pre></td></tr></table></figure><p>执行如下命令安装openclaw</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">npm install <span class="literal">-g</span> openclaw@latest</span><br></pre></td></tr></table></figure><h2 id="配置OpenClaw"><a href="#配置OpenClaw" class="headerlink" title="配置OpenClaw"></a>配置OpenClaw</h2><p>在<code>PowerShell</code>中，执行如下命令进行初始化配置</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">openclaw onboard <span class="literal">--install-daemon</span></span><br></pre></td></tr></table></figure><h3 id="免责申明"><a href="#免责申明" class="headerlink" title="免责申明"></a>免责申明</h3><p>这里只是做一下免责申明，通过方向键选择yes即可。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/openclaw01.webp" alt="openclaw01"></p><h3 id="引导模式-Onboarding-mode"><a href="#引导模式-Onboarding-mode" class="headerlink" title="引导模式(Onboarding mode)"></a>引导模式(Onboarding mode)</h3><p>这里选择QuickStart即可。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/openclaw02.webp" alt="openclaw02"></p><h3 id="模型验证-Model-auth-Provider"><a href="#模型验证-Model-auth-Provider" class="headerlink" title="模型验证(Model&#x2F;auth Provider)"></a>模型验证(Model&#x2F;auth Provider)</h3><p><img src="https://cdn.tvzr.com/images/tech/2026/03/openclaw03.webp" alt="openclaw03"></p><p>这里通过方向键，将其选中<code>Custom Provider</code>，此时会让你输入API Base URL。自己选一个模型按要求填写即可。</p><h3 id="Select-channel"><a href="#Select-channel" class="headerlink" title="Select channel"></a>Select channel</h3><p>直接跳过，选择<code>Skip for now</code>，安装完成后直接安装QQ bot即可，简单快捷。</p><h3 id="技能"><a href="#技能" class="headerlink" title="技能"></a>技能</h3><p>不建议安装，全部跳过，如果是mac用户可以根据自己实际情况激活，注意，技能越多，越浪费token。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/openclaw04.webp" alt="openclaw04"></p><p>此时便安装完成，可以打开dashboard查看页面。</p><h2 id="配置OpenClaw模型"><a href="#配置OpenClaw模型" class="headerlink" title="配置OpenClaw模型"></a>配置OpenClaw模型</h2><p>最近OpenClaw更新频繁，内容时效性很低，这个配置仅作为OpenClaw 2026.3.2版本是有效果的。</p><p>OpenClaw的配置文件在<strong>C:\Users\xxx.openclaw\openclaw.json</strong>，每次通过命令行修改配置它会自动备份为openclaw.json.bak.{1…n}。</p><p>如果不习惯使用配置文件配置，也可以在<code>Dashboard</code>的页面中修改。在<code>openclaw dashboard</code>启动的状态下，打开<code>web ui</code>，在左侧菜单中选择配置 -&gt; <code>All Settings</code> &gt; <code>RAW</code>。将配置好的内容填写进去即可。（注意：如果配置有自定义Key，然后在Web UI里修改时，会出现无法识别Key，导致配置丢失的问题）</p><p><strong>建议，要么一直使用配置文件，要么使用web ui，二者不要混着修改。</strong></p><p>下面是我的配置，可以进行参考。</p><ul><li><code>&quot;ali&quot;</code>，就是交互配置中的<code>Endpoint</code></li><li><code>“baseUrl”</code>,  API base URL</li><li><code>apiKey</code>，APT Key</li><li>还有一步选项的选择<code>OpenAI-compatible</code>，也就是下面配置文件中的<code>&quot;api&quot;</code>的值。所有模型都兼容Openai，所以都选这个</li><li><code>&quot;id&quot;</code>: Model ID,这里务必要与大模型产商定义的模型名称一模一样，否则会报404。</li><li><code>&quot;name&quot;</code>：随便写，比如那些事付费的，那些是免费的可以自己加个备注：<code>qwen3.5-plus(FREE)</code></li></ul><figure class="highlight json"><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><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">&quot;models&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">   <span class="attr">&quot;mode&quot;</span><span class="punctuation">:</span> <span class="string">&quot;merge&quot;</span><span class="punctuation">,</span></span><br><span class="line">   <span class="attr">&quot;providers&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">     <span class="attr">&quot;ali&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">       <span class="attr">&quot;baseUrl&quot;</span><span class="punctuation">:</span> <span class="string">&quot;https://dashscope.aliyuncs.com/compatible-mode/v1&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;apiKey&quot;</span><span class="punctuation">:</span> <span class="string">&quot;sk-xxxxxxxxxxxxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;api&quot;</span><span class="punctuation">:</span> <span class="string">&quot;openai-completions&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;models&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">         <span class="punctuation">&#123;</span></span><br><span class="line">           <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;qwen3.5-plus&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;qwen3.5-plus&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;reasoning&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">             <span class="string">&quot;text&quot;</span></span><br><span class="line">           <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;cost&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">             <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="number">0.04</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;output&quot;</span><span class="punctuation">:</span> <span class="number">0.12</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;cacheRead&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;cacheWrite&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">           <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;contextWindow&quot;</span><span class="punctuation">:</span> <span class="number">16000</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;maxTokens&quot;</span><span class="punctuation">:</span> <span class="number">4096</span></span><br><span class="line">         <span class="punctuation">&#125;</span></span><br><span class="line">       <span class="punctuation">]</span></span><br><span class="line">     <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">     <span class="attr">&quot;deepseek&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">       <span class="attr">&quot;baseUrl&quot;</span><span class="punctuation">:</span> <span class="string">&quot;https://api.deepseek.com&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;apiKey&quot;</span><span class="punctuation">:</span> <span class="string">&quot;sk-4xxxxxxxxxxxxxxxxxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;api&quot;</span><span class="punctuation">:</span> <span class="string">&quot;openai-completions&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;models&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">         <span class="punctuation">&#123;</span></span><br><span class="line">           <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;deepseek-chat&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;deepseek-chat&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;reasoning&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">             <span class="string">&quot;text&quot;</span></span><br><span class="line">           <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;cost&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">             <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="number">0.002</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;output&quot;</span><span class="punctuation">:</span> <span class="number">0.008</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;cacheRead&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;cacheWrite&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">           <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;contextWindow&quot;</span><span class="punctuation">:</span> <span class="number">16000</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;maxTokens&quot;</span><span class="punctuation">:</span> <span class="number">4096</span></span><br><span class="line">         <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">         <span class="punctuation">&#123;</span></span><br><span class="line">           <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;deepseek-reasoner&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;DeepSeek-R1&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;reasoning&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">             <span class="string">&quot;text&quot;</span></span><br><span class="line">           <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;cost&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">             <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="number">0.002</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;output&quot;</span><span class="punctuation">:</span> <span class="number">0.008</span></span><br><span class="line">           <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;contextWindow&quot;</span><span class="punctuation">:</span> <span class="number">64000</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;maxTokens&quot;</span><span class="punctuation">:</span> <span class="number">16384</span></span><br><span class="line">         <span class="punctuation">&#125;</span></span><br><span class="line">       <span class="punctuation">]</span></span><br><span class="line">     <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">     <span class="attr">&quot;zhipu&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">       <span class="attr">&quot;baseUrl&quot;</span><span class="punctuation">:</span> <span class="string">&quot;https://open.bigmodel.cn/api/paas/v4&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;apiKey&quot;</span><span class="punctuation">:</span> <span class="string">&quot;xxxxxxx.xxxxxxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;api&quot;</span><span class="punctuation">:</span> <span class="string">&quot;openai-completions&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;models&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">         <span class="punctuation">&#123;</span></span><br><span class="line">           <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;glm-4.6v&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;glm-4.6v&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;reasoning&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">             <span class="string">&quot;text&quot;</span></span><br><span class="line">           <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;cost&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">             <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;output&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;cacheRead&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;cacheWrite&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">           <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;contextWindow&quot;</span><span class="punctuation">:</span> <span class="number">16000</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;maxTokens&quot;</span><span class="punctuation">:</span> <span class="number">4096</span></span><br><span class="line">         <span class="punctuation">&#125;</span></span><br><span class="line">       <span class="punctuation">]</span></span><br><span class="line">     <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">     <span class="attr">&quot;kimi&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">       <span class="attr">&quot;baseUrl&quot;</span><span class="punctuation">:</span> <span class="string">&quot;https://api.moonshot.cn/v1&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;apiKey&quot;</span><span class="punctuation">:</span> <span class="string">&quot;sk-xxxxxxxxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;api&quot;</span><span class="punctuation">:</span> <span class="string">&quot;openai-completions&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;models&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">         <span class="punctuation">&#123;</span></span><br><span class="line">           <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;kimi-k2.5&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;kimi-k2.5&quot;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;reasoning&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">             <span class="string">&quot;text&quot;</span></span><br><span class="line">           <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;cost&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">             <span class="attr">&quot;input&quot;</span><span class="punctuation">:</span> <span class="number">4</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;output&quot;</span><span class="punctuation">:</span> <span class="number">21</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;cacheRead&quot;</span><span class="punctuation">:</span> <span class="number">0.7</span><span class="punctuation">,</span></span><br><span class="line">             <span class="attr">&quot;cacheWrite&quot;</span><span class="punctuation">:</span> <span class="number">4</span></span><br><span class="line">           <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;contextWindow&quot;</span><span class="punctuation">:</span> <span class="number">16000</span><span class="punctuation">,</span></span><br><span class="line">           <span class="attr">&quot;maxTokens&quot;</span><span class="punctuation">:</span> <span class="number">4096</span></span><br><span class="line">         <span class="punctuation">&#125;</span></span><br><span class="line">       <span class="punctuation">]</span></span><br><span class="line">     <span class="punctuation">&#125;</span></span><br><span class="line">   <span class="punctuation">&#125;</span></span><br><span class="line"> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">&quot;agents&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">   <span class="attr">&quot;defaults&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">     <span class="attr">&quot;model&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">       <span class="attr">&quot;primary&quot;</span><span class="punctuation">:</span> <span class="string">&quot;kimi/kimi-k2.5&quot;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;fallbacks&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">         <span class="string">&quot;zhipu/glm-4.6v&quot;</span><span class="punctuation">,</span></span><br><span class="line">         <span class="string">&quot;deepseek/deepseek-reasoner&quot;</span></span><br><span class="line">       <span class="punctuation">]</span></span><br><span class="line">     <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">     <span class="attr">&quot;models&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">       <span class="attr">&quot;ali/qwen3.5-plus&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">         <span class="attr">&quot;alias&quot;</span><span class="punctuation">:</span> <span class="string">&quot;qwen-plus&quot;</span></span><br><span class="line">       <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;deepseek/deepseek-chat&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">         <span class="attr">&quot;alias&quot;</span><span class="punctuation">:</span> <span class="string">&quot;dsc&quot;</span></span><br><span class="line">       <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;zhipu/glm-4.6v&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">         <span class="attr">&quot;alias&quot;</span><span class="punctuation">:</span> <span class="string">&quot;glm-4.6v&quot;</span></span><br><span class="line">       <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">       <span class="attr">&quot;kimi/kimi-k2.5&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">         <span class="attr">&quot;alias&quot;</span><span class="punctuation">:</span> <span class="string">&quot;kimi-2.5&quot;</span></span><br><span class="line">       <span class="punctuation">&#125;</span></span><br><span class="line">     <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">     <span class="attr">&quot;workspace&quot;</span><span class="punctuation">:</span> <span class="string">&quot;D:\\openclaw\\workspace&quot;</span><span class="punctuation">,</span></span><br><span class="line">     <span class="attr">&quot;compaction&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">       <span class="attr">&quot;mode&quot;</span><span class="punctuation">:</span> <span class="string">&quot;safeguard&quot;</span></span><br><span class="line">     <span class="punctuation">&#125;</span></span><br><span class="line">   <span class="punctuation">&#125;</span></span><br><span class="line"> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br></pre></td></tr></table></figure><h2 id="接入QQ"><a href="#接入QQ" class="headerlink" title="接入QQ"></a>接入QQ</h2><p>打开<a href="https://q.qq.com/#/">QQ开放平台</a>，官方页面会有个OpenClaw快捷开通的链接，点击，创建机器人即可。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/03/openclaw05.webp" alt="openclaw05"></p><p>然后按照图中的步骤进行就行了。</p>]]>
    </content>
    <id>https://dev.net.cn/how-to-install-openclaw/</id>
    <link href="https://dev.net.cn/how-to-install-openclaw/"/>
    <published>2026-03-06T03:00:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="OpenClaw介绍"><a href="#OpenClaw介绍" class="headerlink" title="OpenClaw介绍"></a>OpenClaw介绍</h2><p>OpenClaw 是一个开源、本地部署的 AI Agent 网关。它的核心思路不是“只回答问题”，而是让 AI 具备执行动作的能力，例如访问网页、运行命令、调度任务、连接聊天渠道和管理会话。根据资料，它原先还经历过名称变动：先后出现过 Clawdbot、Moltbot，最终在 2026 年 1 月底确定为 OpenClaw。</p>]]>
    </summary>
    <title>Windows11安装OpenClaw</title>
    <updated>2026-03-06T03:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Windows" scheme="https://dev.net.cn/categories/Windows/"/>
    <category term="Windows" scheme="https://dev.net.cn/tags/Windows/"/>
    <category term="Scoop" scheme="https://dev.net.cn/tags/Scoop/"/>
    <content>
      <![CDATA[<p>最近抽空将本地的开发工具都升级了一遍，以前都是用一个装一个，多年下来也积累了不少，虽说常用的也都用<code>nvm</code>、<code>uv</code>管理了，但每个都升级一边也着实挺累。想起来以前折腾PowerShell时安装的scoop，觉得还是全部交给它把，反正用起来和<code>brew</code>一样丝滑，不用配置环境变量，还不怎么污染注册表。</p><span id="more"></span><h2 id="安装Scoop"><a href="#安装Scoop" class="headerlink" title="安装Scoop"></a>安装Scoop</h2><p>安装Scoop，需要PowerShell5以上，我本地用的是pws7，所以照着官方文档安装即可：<a href="https://scoop.sh/">Scoop</a>。</p><figure class="highlight powershell"><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">Set-ExecutionPolicy</span> <span class="literal">-ExecutionPolicy</span> RemoteSigned <span class="literal">-Scope</span> CurrentUser</span><br><span class="line"><span class="built_in">Invoke-RestMethod</span> <span class="literal">-Uri</span> https://get.scoop.sh | <span class="built_in">Invoke-Expression</span></span><br></pre></td></tr></table></figure><p>已经安装过的就执行下<code>scoop update</code>更新一下就可以了。</p><p>安装后的目录如下所示：</p><figure class="highlight powershell"><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">apps      <span class="literal">--</span> 安装的软件在这个目录下</span><br><span class="line">buckets   <span class="literal">--</span> 已经添加的软件仓库</span><br><span class="line">cache     <span class="literal">--</span> 缓存目录（下载时的 .zip 或 .msi 安装包。安装完可清理。）</span><br><span class="line">modules   <span class="literal">--</span>  存放 Scoop 自身的 PowerShell 模块</span><br><span class="line">persist   <span class="literal">--</span> 配置目录（例如 maven:setting.xml等）</span><br><span class="line">shims     <span class="literal">--</span>  类似于linux的bin目录，安装的软件都会在这里生成shell脚本，省的去配置环境变量了。</span><br></pre></td></tr></table></figure><h2 id="配置Scoop"><a href="#配置Scoop" class="headerlink" title="配置Scoop"></a>配置Scoop</h2><p>默认Scoop会把各类软件都安装在<code>C:\Users\用户名\scoop</code>，为了节省C盘的空间，我们将其配置在<code>D:\scoop</code>目录。</p><p>1.将整个<code>C:\Users\用户名\scoop</code>剪切到<code>D:</code>盘。</p><p>2.修改环境变量</p><p>右键<code>此电脑</code> -&gt; <code>属性</code> -&gt; <code>高级系统设置</code> -&gt; <strong>环境变量</strong>。</p><p>在“用户变量”中：</p><ul><li>修改（或新建）变量名 <code>SCOOP</code>，值为 <code>D:\Scoop</code>。</li><li>修改 <code>Path</code> 变量，将原本指向 <code>C:\...\scoop\shims</code> 的路径改为 <code>D:\Scoop\shims</code>。</li></ul><p>3.检查一下还有没有遗漏的</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">scoop config</span><br></pre></td></tr></table></figure><p>如果还有<code>C:</code>这种的，都替换一下。</p><div class="note warning modern"><p>对于那种将配置过的开发环境托管到scoop的同学，需要自己将自己配置的所有环境变量统统删除。</p></div><p>以<code>nvm</code>为例（最好是直接删掉，大部分环境使用scoop安装的时候都会自动配置）：</p><figure class="highlight powershell"><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="type">Environment</span>]::SetEnvironmentVariable(<span class="string">&quot;NVM_HOME&quot;</span>, <span class="variable">$null</span>, <span class="string">&quot;User&quot;</span>)</span><br><span class="line">[<span class="type">Environment</span>]::SetEnvironmentVariable(<span class="string">&quot;NVM_SYMLINK&quot;</span>, <span class="variable">$null</span>, <span class="string">&quot;User&quot;</span>)</span><br></pre></td></tr></table></figure><h2 id="Scoop常用命令"><a href="#Scoop常用命令" class="headerlink" title="Scoop常用命令"></a>Scoop常用命令</h2><table><thead><tr><th align="center">Command</th><th align="center">Summary</th></tr></thead><tbody><tr><td align="center">update</td><td align="center">更新</td></tr><tr><td align="center">list</td><td align="center">显示已安装软件</td></tr><tr><td align="center">install</td><td align="center">安装(全局安装 加 <code>-g</code>)</td></tr><tr><td align="center">uninstall</td><td align="center">卸载</td></tr><tr><td align="center">search</td><td align="center">搜索</td></tr><tr><td align="center">status</td><td align="center">检查更新（outdated）</td></tr><tr><td align="center">bucket</td><td align="center">buckets</td></tr><tr><td align="center">cache</td><td align="center">缓存</td></tr><tr><td align="center">reset</td><td align="center">重设（通常用于多版本切换）</td></tr><tr><td align="center">cleanup</td><td align="center">清理下载的旧版</td></tr><tr><td align="center">help</td><td align="center">帮助</td></tr><tr><td align="center">shim</td><td align="center">shim</td></tr></tbody></table><p>除了<code>install</code>、<code>uninstall</code>、<code>update</code>、<code>update</code>以外，通常使用的命令就是</p><p><strong>清理过时（或者安装完的）的安装包</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">scoop cache <span class="built_in">rm</span> *</span><br></pre></td></tr></table></figure><p><strong>查看社区的bucket列表</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">scoop bucket known</span><br></pre></td></tr></table></figure><p><strong>添加bucket</strong></p><figure class="highlight powershell"><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="comment"># 添加了多种软件包(带UI的)</span></span><br><span class="line">scoop bucket add extras</span><br><span class="line"> <span class="comment"># 安装历史版本时需要这个源</span></span><br><span class="line">scoop bucket add versions</span><br><span class="line"><span class="comment"># 安装jdk</span></span><br><span class="line">scoop bucket add java</span><br></pre></td></tr></table></figure><p>其他常用bucket：<a href="https://rasa.github.io/scoop-directory/by-score.html">https://rasa.github.io/scoop-directory/by-score.html</a></p><p><strong>指定仓库安装</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">scoop install &lt;bucket_Name&gt;/&lt;packName&gt;</span><br></pre></td></tr></table></figure><p><strong>切换jdk(或者其他什么的都可以)版本</strong></p><figure class="highlight powershell"><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="comment"># https://github.com/ScoopInstaller/Java/wiki</span></span><br><span class="line">scoop reset temurin21<span class="literal">-jdk</span> </span><br><span class="line"></span><br><span class="line">scoop reset temurin8<span class="literal">-jdk</span> </span><br></pre></td></tr></table></figure><p><strong>清理所有旧版</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">scoop cleanup *</span><br></pre></td></tr></table></figure><p><strong>查看已安装的程序</strong></p><figure class="highlight powershell"><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">scoop list</span><br><span class="line"><span class="comment"># 如果只看名字</span></span><br><span class="line">scoop list | <span class="built_in">Select-Object</span> <span class="literal">-ExpandProperty</span> Name</span><br></pre></td></tr></table></figure><p><strong>查看更新</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">scoop status</span><br></pre></td></tr></table></figure><p><strong>更新版本，仓库</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">scoop update</span><br></pre></td></tr></table></figure><p><strong>自身诊断</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">scoop checkup</span><br></pre></td></tr></table></figure><p><strong>全局安装git</strong></p><figure class="highlight powershell"><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"># 需要在开发者那里开启sudo</span></span><br><span class="line">sudo scoop install git <span class="literal">-g</span> </span><br></pre></td></tr></table></figure><p><strong>查看有哪些保留的安装包</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">scoop cache show</span><br></pre></td></tr></table></figure><h2 id="配置代理"><a href="#配置代理" class="headerlink" title="配置代理"></a>配置代理</h2><p>国内使用这些工具，不可避免得要配置这些。（配置加速地址也行）</p><h3 id="设置代理"><a href="#设置代理" class="headerlink" title="设置代理"></a>设置代理</h3><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">scoop config proxy <span class="number">127.0</span>.<span class="number">0.1</span>:<span class="number">1080</span></span><br></pre></td></tr></table></figure><div class="note warning modern"><p>切记不要使用socks5:&#x2F;&#x2F;127.0.0.1:1080 ，兼容性太差了</p></div><h3 id="关闭代理"><a href="#关闭代理" class="headerlink" title="关闭代理"></a>关闭代理</h3><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">scoop config rm proxy</span><br></pre></td></tr></table></figure><h3 id="使用用户代理"><a href="#使用用户代理" class="headerlink" title="使用用户代理"></a>使用用户代理</h3><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">scoop config proxy currentuser@default</span><br></pre></td></tr></table></figure><h2 id="配置Aria2"><a href="#配置Aria2" class="headerlink" title="配置Aria2"></a>配置Aria2</h2><p>如果网络不好，需要断点续传或者多线程加速下载，可以将其替换为aria2。</p><h3 id="安装aria2"><a href="#安装aria2" class="headerlink" title="安装aria2"></a>安装aria2</h3><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">scoop install aria2</span><br></pre></td></tr></table></figure><h3 id="关闭aria2"><a href="#关闭aria2" class="headerlink" title="关闭aria2"></a>关闭aria2</h3><p>如果不想用，可以使用如下命令关闭</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">scoop config aria2<span class="literal">-enabled</span> false</span><br></pre></td></tr></table></figure><h3 id="aria2其他参数配置"><a href="#aria2其他参数配置" class="headerlink" title="aria2其他参数配置"></a>aria2其他参数配置</h3><figure class="highlight powershell"><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">scoop config aria2<span class="literal">-retry-wait</span> <span class="number">4</span></span><br><span class="line">scoop config aria2<span class="operator">-split</span> <span class="number">16</span></span><br><span class="line">scoop config aria2<span class="literal">-max-connection-per-server</span> <span class="number">16</span></span><br><span class="line">scoop config aria2<span class="literal">-min-split-size</span> <span class="number">4</span>M</span><br></pre></td></tr></table></figure><h3 id="功能增强"><a href="#功能增强" class="headerlink" title="功能增强"></a>功能增强</h3><p>可以安装两个增强包，一个是<code>软件补全</code>，一个是<code>搜索增强</code>。</p><figure class="highlight powershell"><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"># 软件名称补全</span></span><br><span class="line">scoop install scoop<span class="literal">-completion</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 搜索增强</span></span><br><span class="line">scoop install scoop<span class="literal">-search</span></span><br></pre></td></tr></table></figure><p>安装完成后，在PowerShell的配置文件中，加入如下代码：</p><figure class="highlight powershell"><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="comment"># 导入 Scoop 补全模块</span></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">Get-Module</span> <span class="literal">-ListAvailable</span> <span class="literal">-Name</span> scoop<span class="literal">-completion</span>) &#123;</span><br><span class="line">    <span class="built_in">Import-Module</span> scoop<span class="literal">-completion</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用 scoop-search 完美接管原生 scoop search 命令</span></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">Get-Command</span> scoop<span class="literal">-search</span> <span class="literal">-ErrorAction</span> SilentlyContinue) &#123;</span><br><span class="line">    . ([<span class="type">ScriptBlock</span>]::Create((&amp; scoop<span class="literal">-search</span> <span class="literal">--hook</span> | <span class="built_in">Out-String</span>)))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样，使用<code>scoop install zulu</code>，按下<code>tab</code>键盘就可以联想出后续的名称。</p><p><img src="https://cdn.tvzr.com/images/tech/2026/02/windows-scoop-install.png" alt="scoop intall"></p><h2 id="我安装的一些软件"><a href="#我安装的一些软件" class="headerlink" title="我安装的一些软件"></a>我安装的一些软件</h2><figure class="highlight powershell"><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></pre></td><td class="code"><pre><span class="line">scoop list | <span class="built_in">Select-Object</span> <span class="literal">-ExpandProperty</span> Name      </span><br><span class="line">Installed apps:</span><br><span class="line"><span class="number">7</span>zip</span><br><span class="line">composer</span><br><span class="line">FantasqueSansMono<span class="literal">-NF</span></span><br><span class="line">ffmpeg</span><br><span class="line">geekuninstaller</span><br><span class="line">git</span><br><span class="line">git<span class="literal">-lfs</span></span><br><span class="line">go</span><br><span class="line">gradle</span><br><span class="line">JetBrainsMono<span class="literal">-NF</span></span><br><span class="line">libwebp</span><br><span class="line">maven</span><br><span class="line">neovim</span><br><span class="line">nginx</span><br><span class="line">nvm</span><br><span class="line">pandoc</span><br><span class="line">php</span><br><span class="line">sbt</span><br><span class="line">scala2</span><br><span class="line">scoop<span class="literal">-completion</span></span><br><span class="line">scoop<span class="literal">-search</span></span><br><span class="line">temurin<span class="literal">-lts-jdk</span></span><br><span class="line">temurin11<span class="literal">-jdk</span></span><br><span class="line">temurin17<span class="literal">-jdk</span></span><br><span class="line">temurin21<span class="literal">-jdk</span></span><br><span class="line">temurin8<span class="literal">-jdk</span></span><br><span class="line">uv</span><br><span class="line">visualvm</span><br><span class="line">zulufx17<span class="literal">-jdk</span></span><br><span class="line"><span class="number">7</span>zip</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="comment"># 一键安装</span></span><br><span class="line">scoop install  ripgrep fd jq  make sed gawk grep yq fzf imagemagick poppler curl wget gh zoxide  bat exiftool main/ast-grep miller xsv</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://dev.net.cn/windows-scoop/</id>
    <link href="https://dev.net.cn/windows-scoop/"/>
    <published>2026-02-01T09:00:00.000Z</published>
    <summary>
      <![CDATA[<p>最近抽空将本地的开发工具都升级了一遍，以前都是用一个装一个，多年下来也积累了不少，虽说常用的也都用<code>nvm</code>、<code>uv</code>管理了，但每个都升级一边也着实挺累。想起来以前折腾PowerShell时安装的scoop，觉得还是全部交给它把，反正用起来和<code>brew</code>一样丝滑，不用配置环境变量，还不怎么污染注册表。</p>]]>
    </summary>
    <title>使用Scoop管理开发工具</title>
    <updated>2026-02-01T09:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="GitHub" scheme="https://dev.net.cn/categories/GitHub/"/>
    <category term="Python" scheme="https://dev.net.cn/tags/Python/"/>
    <category term="GitHubAction" scheme="https://dev.net.cn/tags/GitHubAction/"/>
    <content>
      <![CDATA[<p>由于百度对于新站或者一些他们认为质量不高的站点，关闭了<code>sitemap</code>的提交方式，为了让百度尽快收录，就需要手动将新的文章链接手动提交到百度站长平台，实在是过于麻烦，所以就想到利用<code>GitHub Action</code>，将站点URL自动提交到百度站长平台和Bing的<code>IndexNow</code>。</p><span id="more"></span><p>首先，确保你的站点已经添加到<a href="https://ziyuan.baidu.com/">百度站长工具平台</a>和<a href="https://www.bing.com/webmasters/">bing webmaster tools</a>，获取他们的密钥。</p><h2 id="获取百度提交密钥"><a href="#获取百度提交密钥" class="headerlink" title="获取百度提交密钥"></a>获取百度提交密钥</h2><p>点击<code>站点管理</code> -&gt; <code>选择需要提交的域名</code> -&gt; <code>普通收录</code>，默认进去就是<code>资源提交</code> -&gt; <code>API提交</code>。此时会给你个推送接口，里面写明了你的密钥，将其记录下来。</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/01/image-1.png?x-oss-process=style/large"></p><h2 id="获取Bing-IndexNow密钥"><a href="#获取Bing-IndexNow密钥" class="headerlink" title="获取Bing IndexNow密钥"></a>获取Bing IndexNow密钥</h2><p>打开 <a href="https://www.bing.com/indexnow/getstarted">How to add IndexNow to your website Bing Webmaster Tools</a>，在下面有个<strong>Generate API Key</strong>，根据指引，将其作为文件名保存为<code>yourapikey.txt</code>，放置在网站根目录，懒得操作的话可以安装Bing推荐的插件，例如<code>RankMath</code>、<code>Yoast</code>等都会自动生成这个API Key，并且这些插件会在新文章发布时自动提交。当然，我们也可以督促Bing去主动爬取，因为一旦提交了<code>IndexNow</code>，Bing的蜘蛛会立马爬取，不像百度那么保守。</p><h2 id="编写代码"><a href="#编写代码" class="headerlink" title="编写代码"></a>编写代码</h2><p>由于Google不支持这种方式提交，所以就没必要照顾Google了，本身它也收录的比较勤快，基本都是当天收录。本次利用Python来实现提交URL，创建一个Python项目，创建一个<code>main.py</code>文件，内容如下：</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> xml.etree.ElementTree <span class="keyword">as</span> ET</span><br><span class="line"></span><br><span class="line"><span class="comment"># --- 配置参数 ---</span></span><br><span class="line">SITE_DOMAIN = <span class="string">&quot;your domain&quot;</span></span><br><span class="line"><span class="comment"># 这里请换成你自己的sitemap地址</span></span><br><span class="line">SITEMAP_URL = <span class="string">f&quot;https://<span class="subst">&#123;SITE_DOMAIN&#125;</span>/post-sitemap.xml&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Bing 配置 </span></span><br><span class="line">BING_KEY = <span class="string">&quot;your api key&quot;</span></span><br><span class="line">BING_API = <span class="string">&quot;https://www.bing.com/indexnow&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 百度配置 更换成自己站点的</span></span><br><span class="line">BAIDU_TOKEN = <span class="string">&quot;your api key&quot;</span></span><br><span class="line">BAIDU_API = <span class="string">f&quot;http://data.zz.baidu.com/urls?site=https://<span class="subst">&#123;SITE_DOMAIN&#125;</span>&amp;token=<span class="subst">&#123;BAIDU_TOKEN&#125;</span>&quot;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_urls_from_sitemap</span>():</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        r = requests.get(SITEMAP_URL, timeout=<span class="number">10</span>)</span><br><span class="line">        r.raise_for_status()</span><br><span class="line">        root = ET.fromstring(r.content)</span><br><span class="line">        <span class="comment"># 提取所有 URL 命名空间处理</span></span><br><span class="line">        namespace = &#123;<span class="string">&#x27;ns&#x27;</span>: <span class="string">&#x27;http://www.sitemaps.org/schemas/sitemap/0.9&#x27;</span>&#125;</span><br><span class="line">        urls = [node.text <span class="keyword">for</span> node <span class="keyword">in</span> root.findall(<span class="string">&quot;.//ns:loc&quot;</span>, namespace)]</span><br><span class="line">        <span class="keyword">return</span> urls</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;解析 Sitemap 出错: <span class="subst">&#123;e&#125;</span>&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> []</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">submit_to_bing</span>(<span class="params">urls</span>):</span><br><span class="line">    <span class="comment"># Bing 全部提交，巨硬比较豪气</span></span><br><span class="line">    data = &#123;</span><br><span class="line">        <span class="string">&quot;host&quot;</span>: SITE_DOMAIN,</span><br><span class="line">        <span class="string">&quot;key&quot;</span>: BING_KEY,</span><br><span class="line">        <span class="string">&quot;keyLocation&quot;</span>: <span class="string">f&quot;https://<span class="subst">&#123;SITE_DOMAIN&#125;</span>/<span class="subst">&#123;BING_KEY&#125;</span>.txt&quot;</span>,</span><br><span class="line">        <span class="string">&quot;urlList&quot;</span>: urls</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        res = requests.post(BING_API, json=data)</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;Bing IndexNow 提交状态: <span class="subst">&#123;res.status_code&#125;</span>&quot;</span>)</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;Bing 提交失败: <span class="subst">&#123;e&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">submit_to_baidu</span>(<span class="params">urls</span>):</span><br><span class="line">    <span class="comment"># 仅取前 10 个链接，我记得百度是数量限制的,就提交前十个吧。</span></span><br><span class="line">    target_urls = urls[:<span class="number">10</span>]</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&quot;正在向百度提交前 <span class="subst">&#123;<span class="built_in">len</span>(target_urls)&#125;</span> 个链接...&quot;</span>)</span><br><span class="line"></span><br><span class="line">    data = <span class="string">&quot;\n&quot;</span>.join(target_urls)</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        res = requests.post(BAIDU_API, data=data, headers=&#123;<span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;text/plain&#x27;</span>&#125;)</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;百度返回结果: <span class="subst">&#123;res.text&#125;</span>&quot;</span>)</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;百度提交失败: <span class="subst">&#123;e&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    all_urls = get_urls_from_sitemap()</span><br><span class="line">    <span class="keyword">if</span> all_urls:</span><br><span class="line">        <span class="comment"># 对 Bing 提交全部链接</span></span><br><span class="line">        submit_to_bing(all_urls)</span><br><span class="line">        <span class="comment"># 对 百度 仅提交前 10 个</span></span><br><span class="line">        submit_to_baidu(all_urls)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;未发现有效 URL，请检查 Sitemap。&quot;</span>)</span><br></pre></td></tr></table></figure><p>编写完成后，先执行一次确认没问题。</p><h2 id="配置GitHub-Action"><a href="#配置GitHub-Action" class="headerlink" title="配置GitHub Action"></a>配置GitHub Action</h2><p>在刚才那个Python文件的同级目录，创建<code>.github/workflows</code>目录，并且创建一个<code>seo_submit.yml</code>的文件，其内容如下：</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><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"><span class="attr">name:</span> <span class="string">SEO</span> <span class="string">Auto</span> <span class="string">Submission</span></span><br><span class="line"></span><br><span class="line"><span class="attr">on:</span></span><br><span class="line">  <span class="attr">schedule:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">cron:</span> <span class="string">&#x27;0 1 * * *&#x27;</span>  <span class="comment"># 每天北京时间早上 9:00 运行(注意时区)</span></span><br><span class="line">  <span class="attr">workflow_dispatch:</span>      <span class="comment"># 允许手动随时点击运行</span></span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">submit:</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Checkout</span> <span class="string">Code</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/checkout@v3</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">Python</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/setup-python@v4</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">python-version:</span> <span class="string">&#x27;3.9&#x27;</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Install</span> <span class="string">Requests</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">pip</span> <span class="string">install</span> <span class="string">requests</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Run</span> <span class="string">Submission</span> <span class="string">Script</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">python</span> <span class="string">main.py</span></span><br></pre></td></tr></table></figure><p>然后将这个项目推送到Github，这样每天就可以定时提交URL了。</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/01/image-2.png?x-oss-process=style/large"></p><p>百度提交可以在数据反馈里看到提交信息，幸运的是本站的sitemap权限并未被关闭，每周也会自动提交一次全量的。Bing的直接打开<code>IndexNow</code>即可看到。</p>]]>
    </content>
    <id>https://dev.net.cn/github-actions-auto-submit-urls/</id>
    <link href="https://dev.net.cn/github-actions-auto-submit-urls/"/>
    <published>2026-01-29T03:15:45.000Z</published>
    <summary>
      <![CDATA[<p>由于百度对于新站或者一些他们认为质量不高的站点，关闭了<code>sitemap</code>的提交方式，为了让百度尽快收录，就需要手动将新的文章链接手动提交到百度站长平台，实在是过于麻烦，所以就想到利用<code>GitHub Action</code>，将站点URL自动提交到百度站长平台和Bing的<code>IndexNow</code>。</p>]]>
    </summary>
    <title>利用GitHub Action自动提交网站链接</title>
    <updated>2026-01-29T03:15:45.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Debian" scheme="https://dev.net.cn/categories/Debian/"/>
    <category term="WSL" scheme="https://dev.net.cn/tags/WSL/"/>
    <category term="Debian" scheme="https://dev.net.cn/tags/Debian/"/>
    <category term="oh-my-zsh" scheme="https://dev.net.cn/tags/oh-my-zsh/"/>
    <content>
      <![CDATA[<p>最近使用WSL频率较高，由于Windows配置了<code>OhMyPosh</code>，看习惯了花里胡哨忽然进入简约的Debian有些别扭，于是就想干脆给Debian也安装一个<code>Oh my zsh</code>算了。</p><p>目前Debian就两个用户，一个普通，一个root，建议给这两个用户分开安装，不要全系统共享，避免因为更新后出现权限问题。</p><h2 id="安装Oh-My-ZSH"><a href="#安装Oh-My-ZSH" class="headerlink" title="安装Oh My ZSH"></a>安装Oh My ZSH</h2><p>对于debian，使用如下命令即可安装（对于需要zsh的用户，每个都执行一次）</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">sh -c <span class="string">&quot;<span class="subst">$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)</span>&quot;</span></span><br></pre></td></tr></table></figure><p>安装过程中会提示你是否将<code>zsh</code>设置为默认<code>shell</code>，选择Y</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">Do you want to change your default shell to zsh? [Y/n] y</span><br></pre></td></tr></table></figure><h2 id="安装主题"><a href="#安装主题" class="headerlink" title="安装主题"></a>安装主题</h2><p><code>Oh My ZSH</code>的主题有很多，具体看一参考这里，个人比较推荐<code>**powerlevel10k**</code>。</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">git <span class="built_in">clone</span> --depth=1 https://github.com/romkatv/powerlevel10k.git <span class="string">&quot;<span class="variable">$&#123;ZSH_CUSTOM:-<span class="variable">$HOME</span>/.oh-my-zsh/custom&#125;</span>/themes/powerlevel10k&quot;</span></span><br></pre></td></tr></table></figure><p>打开 ~&#x2F;.zshrc ，将ZSH_THEME的值修改为powerlevel10k&#x2F;powerlevel10k</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">vim ~/.zshrc</span><br><span class="line"></span><br><span class="line">ZSH_THEME=<span class="string">&quot;powerlevel10k/powerlevel10k&quot;</span></span><br></pre></td></tr></table></figure><h2 id="安装字体"><a href="#安装字体" class="headerlink" title="安装字体"></a>安装字体</h2><p>为了显示一些特殊的图标字符，需要安装一些字体，官方推荐MesloLGS NF，而我Windows上安装的是<code>JetBrainsMono NF</code>（除了个别图标，其他的基本上没区别，甚至JetBrainsMono NF更适合程序员），会造成一些小图标显示为□。</p><p>点击下载链接，下载这四个文件：</p><ul><li><a href="https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Regular.ttf">Regular</a></li><li><a href="https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold.ttf">Bold</a></li><li><a href="https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Italic.ttf">Italic</a></li><li><a href="https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold%20Italic.ttf">Bold Italic</a></li></ul><p>下载到Windows后，分别双击安装即可。</p><h2 id="配置PowerShell"><a href="#配置PowerShell" class="headerlink" title="配置PowerShell"></a>配置PowerShell</h2><p>打开PowerShell，点击标题栏的下三角，打开设置（快捷键：ctrl + .）</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/01/image.png?x-oss-process=style/full" title="PowerShell Debian Tab"></p><p>点击外观，将字体修改为<code>MesloLGS NF</code>。点击保存即可。</p><p>接着在Debian（在PowerShell打开Debian标签）中输入如下，检查字体是否正确</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">echo</span> <span class="string">&quot;\ue0b0 \u00b1 \ue0a0 \u27a6 \u2718 \u26a1 \u2699&quot;</span></span><br></pre></td></tr></table></figure><p>此时会输出一些图标。</p><h2 id="配置主题"><a href="#配置主题" class="headerlink" title="配置主题"></a>配置主题</h2><p>字体安装完成后，就可以配置主题了，使用<code>p10k configure</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></pre></td><td class="code"><pre><span class="line">p10k configure</span><br><span class="line"></span><br><span class="line"><span class="comment"># 第一步 是否正确显示了菱形，如果显示正确说明字体渲染成功，选择 Y</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第二步 是否正确显示了🔒，如果显示正确，选择Y</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第三步 是否正确显示了向上的箭头，如果显示正确，选择Y （选择N也没关系，只是做个检查而已）</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第四步 有个箭头会指向一串数字中的某一个，输入指向的数字即可，一般就是1和2，箭头指向谁，输出谁</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第五步 图标是否被挤在一起，选择Y即可，一般安装完字体后就没啥问题了</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第六步 选择Prompt Style ，有四个选项，看你喜欢那个，我比较喜欢 Rainbow 输入 3</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第七步 选择编码，一般就Unicode，输入 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第八步 选择展示当前时间，我比较喜欢24小时制 输入 2</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第九步 选择分隔符，看你个人喜好，我选择Angled，输入 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第十步  选择Prompt Heads ，我选择Sharp 输入 3</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第十一步 Prompt Tails，尾部时间样式，我喜欢Flat 输入 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第十二步 单行还是双行，个人喜欢单行。 输入 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第十三步 紧凑还是宽松，我喜欢宽松 Sparse 输入 2</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第十四步 图标个数，华丽花哨就选择Many icons，简约点就Few icons ，我个人输入 2 </span></span><br><span class="line"></span><br><span class="line"><span class="comment">#  第十五步 选择 1 就行，上一步图标以及很华丽了，没必要更详细的说明</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第十六步 是否开启瞬时提示符，这个仁者见仁智者见智，效果就是只有当前命令行才需要这些华丽花哨，使用回车后的命令都会显示为简单的&gt; xxx ，这样可以节约资源，也能更好的复制命令，通常推荐Y</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第十七步 ，预渲染 选择推荐选项即可 Verbose 输入 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 第十八步，将配置保（覆）存（盖）在~/.p10k.zsh， 选择Y</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>当然，越花里胡哨，执行命令时越卡顿。</p><h2 id="安装插件"><a href="#安装插件" class="headerlink" title="安装插件"></a>安装插件</h2><p><code>oh my zsh</code>自带一些插件，包括<code>powerlevel10k</code>也有自己的插件，如果需要更强的功能，那么还需要单独安装三个插件</p><h3 id="自动提示插件"><a href="#自动提示插件" class="headerlink" title="自动提示插件"></a>自动提示插件</h3><p>根据历史记录建议命令（按 <code>→</code> 键补全）。安装命令如下：</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">git <span class="built_in">clone</span> https://github.com/zsh-users/zsh-autosuggestions <span class="variable">$&#123;ZSH_CUSTOM:-~/.oh-my-zsh/custom&#125;</span>/plugins/zsh-autosuggestions</span><br></pre></td></tr></table></figure><h3 id="增强补全"><a href="#增强补全" class="headerlink" title="增强补全"></a>增强补全</h3><p>为命令提供更强大的 <code>Tab</code> 键补全。</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">git <span class="built_in">clone</span> https://github.com/zsh-users/zsh-completions <span class="variable">$&#123;ZSH_CUSTOM:-~/.oh-my-zsh/custom&#125;</span>/plugins/zsh-completions</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/zsh-users/zsh-syntax-highlighting.git <span class="variable">$&#123;ZSH_CUSTOM:-~/.oh-my-zsh/custom&#125;</span>/plugins/zsh-syntax-highlighting</span><br></pre></td></tr></table></figure><p>配置到插件时，务必配置在插件列表的最后一项，如果它放在中间，会和其他插件冲突导致输入字符时有明显的粘滞感。</p><p>配置插件，打开<code>~/.zshrc</code>，在<code>plugins</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></pre></td><td class="code"><pre><span class="line">plugins=(</span><br><span class="line">  git</span><br><span class="line">  <span class="built_in">sudo</span></span><br><span class="line">  z</span><br><span class="line">  zsh-autosuggestions</span><br><span class="line">  zsh-completions</span><br><span class="line">  zsh-syntax-highlighting</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>每个插件用空格隔开（单行），或者如上方式（多行）。注意插件越多，敲命令也会月卡顿。非不要插件尽量不要开启。下面介绍下插件介绍</p><ul><li>git ：zsh默认自带插件，提供了非常多git的缩写命令，例如git status 可以直接输入 gst</li><li>sudo：执行命令是会提示权限不够，按两下esc，自动在命令前面添加sudo</li><li>z ：最强路径跳转。它会记住你常去的目录，输入 z spark 就能直接跳到你那个深层的 Spark 项目目录。</li><li>extract（未启用）：一个命令解压所有压缩包，个人还是习惯敲对应的命令，敲习惯了也忘不了。</li></ul><h2 id="解决卡顿问题"><a href="#解决卡顿问题" class="headerlink" title="解决卡顿问题"></a>解决卡顿问题</h2><p>以上配置完，终端是好看了，但一个很影响体验的就是卡顿。输入命令会有明显卡顿，这主要来自三个方面：zsh本身插件过多、主题自带的一些功能（例如检查jdk版本，git仓库等）、还有就是wsl会扫描Windows的一些环境变量，每次都会很慢。</p><h3 id="过滤Windows的环境变量"><a href="#过滤Windows的环境变量" class="headerlink" title="过滤Windows的环境变量"></a>过滤Windows的环境变量</h3><p>如果在WSL的Debian中输入<code>echo $PATH</code>，会输出大量的Windows的环境变量例如</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">/mnt/d/devtools/go/bin:/mnt/d/devtools/scala/scala-2.13.8/bin:/mnt/d/devtools/gradle-7.5.1/bin:/mnt/d/devtools/python/python310:</span><br></pre></td></tr></table></figure><p>WSL本身访问<code>/mnt</code>这类的路径就很慢，所以每次执行命令都要扫描一边就会更慢了，解决办法就是将其过略，在<code>~/.zshrc</code>配置文件的最顶部，添加如下代码：</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">path=(<span class="variable">$&#123;path:#/mnt/*&#125;</span>)</span><br></pre></td></tr></table></figure><p>即可过滤掉<code>/mnt/c/</code>的一些环境变量。source一下使其生效，效果还比较明显。</p><h3 id="禁用右侧提示"><a href="#禁用右侧提示" class="headerlink" title="禁用右侧提示"></a>禁用右侧提示</h3><p>这里需要编辑<code>powerlevel10k</code>主题的配置文件，编辑<code>~/.p10k.zsh</code>,找到<code>java_version</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></pre></td><td class="code"><pre><span class="line"><span class="built_in">typeset</span> -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(</span><br><span class="line">   status                  <span class="comment"># exit code of the last command</span></span><br><span class="line">   command_execution_time  <span class="comment"># duration of the last command</span></span><br><span class="line">   background_jobs         <span class="comment"># presence of background jobs</span></span><br><span class="line">   direnv                  <span class="comment"># direnv status (https://direnv.net/)</span></span><br><span class="line">   asdf                    <span class="comment"># asdf version manager (https://github.com/asdf-vm/asdf)</span></span><br><span class="line">   virtualenv              <span class="comment"># python virtual environment (https://docs.python.org/3/library/venv.html)</span></span><br><span class="line">   anaconda                <span class="comment"># conda environment (https://conda.io/)</span></span><br><span class="line">   pyenv                   <span class="comment"># python environment (https://github.com/pyenv/pyenv)</span></span><br><span class="line">   goenv                   <span class="comment"># go environment (https://github.com/syndbg/goenv)</span></span><br><span class="line">   nodenv                  <span class="comment"># node.js version from nodenv (https://github.com/nodenv/nodenv)</span></span><br><span class="line">   nvm                     <span class="comment"># node.js version from nvm (https://github.com/nvm-sh/nvm)</span></span><br><span class="line">   nodeenv                 <span class="comment"># node.js environment (https://github.com/ekalinin/nodeenv)</span></span><br><span class="line">   <span class="comment"># node_version          # node.js version</span></span><br><span class="line">   <span class="comment"># go_version            # go version (https://golang.org)</span></span><br><span class="line">   <span class="comment"># rust_version          # rustc version (https://www.rust-lang.org)</span></span><br><span class="line">   <span class="comment"># dotnet_version        # .NET version (https://dotnet.microsoft.com)</span></span><br><span class="line">   <span class="comment"># php_version           # php version (https://www.php.net/)</span></span><br><span class="line">   <span class="comment"># laravel_version       # laravel php framework version (https://laravel.com/)</span></span><br><span class="line">   <span class="comment"># java_version          # java version (https://www.java.com/)</span></span><br><span class="line">   <span class="comment"># package               # name@version from package.json (https://docs.npmjs.com/files/package.json)</span></span><br><span class="line">   <span class="comment"># rbenv                   # ruby version from rbenv (https://github.com/rbenv/rbenv)</span></span><br><span class="line">   <span class="comment"># rvm                     # ruby version from rvm (https://rvm.io)</span></span><br><span class="line">   fvm                     <span class="comment"># flutter version management (https://github.com/leoafarias/fvm)</span></span><br><span class="line">   plenv                   <span class="comment"># perl version from plenv (https://github.com/tokuhirom/plenv)</span></span><br><span class="line">   perlbrew                <span class="comment"># perl version from perlbrew (https://github.com/gugod/App-perlbrew)</span></span><br><span class="line">   <span class="comment"># phpenv                  # php version from phpenv (https://github.com/phpenv/phpenv)</span></span><br><span class="line">   <span class="comment"># scalaenv                # scala version from scalaenv (https://github.com/scalaenv/scalaenv)</span></span><br><span class="line">   haskell_stack           <span class="comment"># haskell version from stack (https://haskellstack.org/)</span></span><br><span class="line">   kubecontext             <span class="comment"># current kubernetes context (https://kubernetes.io/)</span></span><br><span class="line">   terraform               <span class="comment"># terraform workspace (https://www.terraform.io)</span></span><br><span class="line">   <span class="comment"># terraform_version     # terraform version (https://www.terraform.io)</span></span><br><span class="line">   <span class="comment"># aws                     # aws profile (https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html)</span></span><br><span class="line">   <span class="comment"># aws_eb_env              # aws elastic beanstalk environment (https://aws.amazon.com/elasticbeanstalk/)</span></span><br><span class="line">   <span class="comment"># azure                   # azure account name (https://docs.microsoft.com/en-us/cli/azure)</span></span><br><span class="line">   <span class="comment"># gcloud                  # google cloud cli account and project (https://cloud.google.com/)</span></span><br><span class="line">   <span class="comment"># google_app_cred         # google application credentials (https://cloud.google.com/docs/authentication/production)</span></span><br><span class="line">   <span class="comment"># toolbox                 # toolbox name (https://github.com/containers/toolbox)</span></span><br><span class="line">   context                 <span class="comment"># user@hostname</span></span><br><span class="line">   <span class="comment"># nordvpn                 # nordvpn connection status, linux only (https://nordvpn.com/)</span></span><br><span class="line">   ranger                  <span class="comment"># ranger shell (https://github.com/ranger/ranger)</span></span><br><span class="line">   yazi                    <span class="comment"># yazi shell (https://github.com/sxyazi/yazi)</span></span><br><span class="line">   nnn                     <span class="comment"># nnn shell (https://github.com/jarun/nnn)</span></span><br><span class="line">   lf                      <span class="comment"># lf shell (https://github.com/gokcehan/lf)</span></span><br><span class="line">   xplr                    <span class="comment"># xplr shell (https://github.com/sayanarijit/xplr)</span></span><br><span class="line">   vim_shell               <span class="comment"># vim shell indicator (:sh)</span></span><br><span class="line">   midnight_commander      <span class="comment"># midnight commander shell (https://midnight-commander.org/)</span></span><br><span class="line">   nix_shell               <span class="comment"># nix shell (https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html)</span></span><br><span class="line">   chezmoi_shell           <span class="comment"># chezmoi shell (https://www.chezmoi.io/)</span></span><br><span class="line">   vi_mode                 <span class="comment"># vi mode (you don&#x27;t need this if you&#x27;ve enabled prompt_char)</span></span><br><span class="line">   <span class="comment"># vpn_ip                # virtual private network indicator</span></span><br><span class="line">   <span class="comment"># load                  # CPU load</span></span><br><span class="line">   <span class="comment"># disk_usage            # disk usage</span></span><br><span class="line">   <span class="comment"># ram                   # free RAM</span></span><br><span class="line">   <span class="comment"># swap                  # used swap</span></span><br><span class="line">   todo                    <span class="comment"># todo items (https://github.com/todotxt/todo.txt-cli)</span></span><br><span class="line">   timewarrior             <span class="comment"># timewarrior tracking status (https://timewarrior.net/)</span></span><br><span class="line">   taskwarrior             <span class="comment"># taskwarrior task count (https://taskwarrior.org/)</span></span><br><span class="line">   per_directory_history   <span class="comment"># Oh My Zsh per-directory-history local/global indicator</span></span><br><span class="line">   <span class="comment"># cpu_arch              # CPU architecture</span></span><br><span class="line">   <span class="keyword">time</span>                    <span class="comment"># current time</span></span><br><span class="line">   <span class="comment"># ip                    # ip address and bandwidth usage for a specified network interface</span></span><br><span class="line">   <span class="comment"># public_ip             # public IP address</span></span><br><span class="line">   <span class="comment"># proxy                 # system-wide http/https/ftp proxy</span></span><br><span class="line">   <span class="comment"># battery               # internal battery</span></span><br><span class="line">   <span class="comment"># wifi                  # wifi speed</span></span><br><span class="line">   <span class="comment"># example               # example user-defined segment (see prompt_example function below)</span></span><br><span class="line"> )</span><br></pre></td></tr></table></figure><p>修改完成后，<code>source ~/.zshrc</code>即可生效。</p>]]>
    </content>
    <id>https://dev.net.cn/how-to-install-and-configure-oh-my-zsh-on-debian/</id>
    <link href="https://dev.net.cn/how-to-install-and-configure-oh-my-zsh-on-debian/"/>
    <published>2026-01-23T04:10:56.000Z</published>
    <summary>
      <![CDATA[<p>最近使用WSL频率较高，由于Windows配置了<code>OhMyPosh</code>，看习惯了花里胡哨忽然进入简约的Debian有些别扭，于是就想干脆给Debian也安装一个<code>Oh my zsh</code>算了。</p>
<p>目前Debian就两个用户，]]>
    </summary>
    <title>给Debian安装Oh my zsh</title>
    <updated>2026-01-23T04:10:56.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="PowerShell" scheme="https://dev.net.cn/categories/PowerShell/"/>
    <category term="Windows" scheme="https://dev.net.cn/tags/Windows/"/>
    <category term="PowerShell" scheme="https://dev.net.cn/tags/PowerShell/"/>
    <content>
      <![CDATA[<p>上篇介绍了《<a href="https://dev.net.cn/756.html">PowerShell统计Windows的文件夹大小</a> 》，根据统计结果，我发现总共有几个文件占用比较夸张，具体如下所示：</p><figure class="highlight powershell"><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">C:\ProgramData\</span><br><span class="line"></span><br><span class="line">Kaspersky Lab                        <span class="number">6890.59</span> MB</span><br><span class="line">NVIDIA                               <span class="number">4536.47</span> MB</span><br><span class="line">NVIDIA Corporation                   <span class="number">4189.88</span> MB</span><br><span class="line">Microsoft                            <span class="number">2385.78</span> MB</span><br><span class="line">Lenovo                               <span class="number">1654.15</span> MB</span><br><span class="line"><span class="comment"># 环境变量为 $env:APPDATA</span></span><br><span class="line">C:\Users\用户\AppData\Roaming</span><br><span class="line">Notion                                    <span class="number">19016.78</span> MB</span><br><span class="line">Tencent                                   <span class="number">7532.22</span> MB</span><br><span class="line">JetBrains                                 <span class="number">3691.49</span> MB</span><br><span class="line">npm<span class="literal">-cache</span>                                 <span class="number">1899.45</span> MB</span><br><span class="line"></span><br><span class="line"><span class="comment"># 环境变量为$env:LOCALAPPDATA</span></span><br><span class="line"> C:\Users\用户\AppData\Local</span><br><span class="line">Microsoft                                 <span class="number">6967.01</span> MB</span><br><span class="line">NVIDIA                                    <span class="number">5484.8</span> MB</span><br><span class="line">JetBrains                                 <span class="number">3243.41</span> MB</span><br><span class="line">Temp                                      <span class="number">2379.17</span> MB</span><br><span class="line">Programs                                  <span class="number">1812.47</span> MB</span><br><span class="line">Lenovo                                    <span class="number">1506.49</span> MB</span><br><span class="line">Google                                    <span class="number">1231.54</span> MB</span><br><span class="line">Packages                                  <span class="number">962.48</span> MB</span><br></pre></td></tr></table></figure><figure class="highlight powershell"><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="variable">$env:LOCALAPPDATA</span> 对应 C:\Users\用户\AppData\Local  </span><br><span class="line"><span class="variable">$env:APPDATA</span> 对应 C:\Users\用户\AppData\Roaming</span><br></pre></td></tr></table></figure><p>从上面的统计可以看到，NVIDIA占用真的多啊，此时需要寄出老祖经典名场面</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/01/linus-torvalds-linus.gif"></p><p>大概看了下，Notion是因为里面的C:\Users\用户\AppData\Roaming\Notion\Partitions占用了18G，直接将其删除掉，保险起见使用如下命令：</p><figure class="highlight powershell"><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"># 停止进程</span></span><br><span class="line"><span class="built_in">Stop-Process</span> <span class="literal">-Name</span> <span class="string">&quot;Notion&quot;</span> <span class="literal">-ErrorAction</span> SilentlyContinue</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除目录</span></span><br><span class="line"><span class="built_in">Remove-Item</span> <span class="literal">-Path</span> <span class="string">&quot;<span class="variable">$env:APPDATA</span>\Notion\Partitions&quot;</span> <span class="literal">-Recurse</span> <span class="literal">-Force</span></span><br></pre></td></tr></table></figure><p>Notion 使用了类似浏览器的索引技术（IndexedDB），当你浏览含有大量图片、视频或嵌入内容的页面时，Notion 会将这些资源缓存在本地以提高加载速度。<br><strong>多账号切换：</strong> 如果你在客户端登录了多个账号，每个账号都会生成独立的缓存。<br><strong>重型页面：</strong> 频繁查看带有大量附件的数据库会迅速填满该目录。</p><p>为了避免后期缓存太多导致占用C盘，将其剪切到其他盘，例如<strong>E:\AppData</strong>\Notion,然后创建软连接到这里</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">New-Item</span> <span class="literal">-ItemType</span> Junction <span class="literal">-Path</span> <span class="string">&quot;<span class="variable">$env:APPDATA</span>\Notion&quot;</span> <span class="literal">-Target</span> <span class="string">&quot;E:\AppData\Notion&quot;</span></span><br></pre></td></tr></table></figure><p>同样的方式可以将JetBrains也如此操作：</p><figure class="highlight powershell"><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"><span class="built_in">New-Item</span> <span class="literal">-ItemType</span> Junction <span class="literal">-Path</span> <span class="string">&quot;<span class="variable">$env:LOCALAPPDATA</span>\JetBrains&quot;</span> <span class="literal">-Target</span> <span class="string">&quot;E:\AppData\JetBrains\Local&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">New-Item</span> <span class="literal">-ItemType</span> Junction <span class="literal">-Path</span> <span class="string">&quot;<span class="variable">$env:LOCALAPPDATA</span>\JetBrains&quot;</span> <span class="literal">-Target</span> <span class="string">&quot;E:\AppData\JetBrains\Roaming&quot;</span></span><br></pre></td></tr></table></figure><p>如果你是用的是CMD，也可以使用如下命令，效果是相同的，但更推荐使用PowerShell：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mklink /j &quot;C:\Users\用户\AppData\Local\JetBrains&quot; &quot;E:\AppData\JetBrains\Local&quot;</span><br></pre></td></tr></table></figure><p>设置完成后确认下是否有误</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">Get-Item</span> <span class="string">&quot;<span class="variable">$env:APPDATA</span>\Notion&quot;</span>  <span class="built_in">Select-Object</span> Mode, LinkType, Target</span><br></pre></td></tr></table></figure><p>输出如下：</p><figure class="highlight powershell"><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">Mode  LinkType Target</span><br><span class="line"><span class="literal">----</span>  <span class="literal">--------</span> <span class="literal">------</span></span><br><span class="line">l<span class="literal">----</span> Junction E:\AppData\Notion</span><br></pre></td></tr></table></figure><p>这样就再也不用担心C盘被塞满了。当然，Nvidia也可以这么操作，但是通常不建议这么干。</p><p>最佳方案就是笔记本系统盘使用1T的SSD，另一个插槽买个2T SSD，为了方便管理可以将2T的分为D盘和E盘。</p><p>关于PowerShell的目录链接和符号链接，大致区别如下：</p><p><strong>特性</strong></p><p><strong>Junction (目录联接)</strong></p><p><strong>Symbolic Link (符号链接)</strong></p><p><strong>创建命令</strong></p><p><code>New-Item -ItemType Junction</code></p><p><code>New-Item -ItemType SymboliLink</code></p><p><strong>支持对象</strong></p><p><strong>仅限目录</strong>（文件夹）</p><p><strong>目录 + 文件</strong></p><p><strong>跨盘符支持</strong></p><p>支持（从 C 搬到 D）</p><p>支持</p><p><strong>远程路径</strong></p><p><strong>不支持</strong>（必须是本地硬盘）</p><p><strong>支持</strong>（可以链接到局域网共享目录）</p><p><strong>路径类型</strong></p><p>使用<strong>绝对路径</strong></p><p>支持<strong>相对路径</strong></p><p><strong>移动目标后</strong></p><p>立即失效</p><p>立即失效</p><h4 id="Junction-目录联接-——-“分身术”"><a href="#Junction-目录联接-——-“分身术”" class="headerlink" title="Junction (目录联接) —— “分身术”"></a><strong>Junction (目录联接) —— “分身术”</strong></h4><p>Junction 是 NTFS 文件系统的一种硬性重定向。当你访问 <code>C:\Users\用户\AppData\Local\JetBrains</code> 时，文件系统内核会直接将其重定向到 <code>D:\JetBrains_Data\Local</code>。</p><ul><li><strong>特点</strong>：对于软件来说，它<strong>完全意识不到</strong>自己在 D 盘工作。它的兼容性最高，非常适合用来搬移 <code>AppData</code> 下的软件缓存。</li><li><strong>历史</strong>：从 Windows 2000 开始就存在，非常稳定。</li></ul><h4 id="Symbolic-Link-符号链接-软链接-——-“更强的快捷方式”"><a href="#Symbolic-Link-符号链接-软链接-——-“更强的快捷方式”" class="headerlink" title="Symbolic Link (符号链接&#x2F;软链接) —— “更强的快捷方式”"></a><strong>Symbolic Link (符号链接&#x2F;软链接) —— “更强的快捷方式”</strong></h4><p>它更像是一个特殊的“文件”，里面记录了目标的路径信息。</p><ul><li><strong>特点</strong>：它可以指向文件（比如把一个巨大的游戏资源文件 <code>.pak</code> 链到别处）。</li><li><strong>缺点</strong>：创建符号链接通常需要<strong>管理员权限</strong>（除非开启了 Windows 开发人员模式）。有些旧软件可能不识别符号链接。</li></ul>]]>
    </content>
    <id>https://dev.net.cn/how-to-free-up-c-drive-space-using-directory-junctions/</id>
    <link href="https://dev.net.cn/how-to-free-up-c-drive-space-using-directory-junctions/"/>
    <published>2026-01-12T03:06:41.000Z</published>
    <summary>
      <![CDATA[<p>上篇介绍了《<a href="https://dev.net.cn/756.html">PowerShell统计Windows的文件夹大小</a> 》，根据统计结果，我发现总共有几个文件占用比较夸张，具体如下所示：</p>
<figure class="highlight]]>
    </summary>
    <title>利用目录连接解决C盘数据文件过大的问题</title>
    <updated>2026-01-12T03:06:41.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="PowerShell" scheme="https://dev.net.cn/categories/PowerShell/"/>
    <category term="PowerShell" scheme="https://dev.net.cn/tags/PowerShell/"/>
    <category term="Windows11" scheme="https://dev.net.cn/tags/Windows11/"/>
    <content>
      <![CDATA[<p>在这两年使用Windows的过程中，总是遇到一个问题就是200G的C盘空间，动不动就爆满，这还是在我把腾讯系的数据目录迁移到其他盘、所有软件能不安装在C盘就不安装的情况下发生的。印象中2015年以前，我的Windows电脑C盘才60G。最开始我都是通过联想自带的清理工具进行硬盘清理，但是很显然这样的方式不够理想，而且我也禁用了联想的服务，那么就需要手动删除。手动删除就要先统计下那些目录占用的空间比较多，根据实际情况有选择的进行删除。</p><span id="more"></span><p><img src="https://cdn.dev.net.cn/dev/images/2026/01/windows-ssd-01.png?x-oss-process=style/large"></p><h2 id="定义函数"><a href="#定义函数" class="headerlink" title="定义函数"></a>定义函数</h2><p>PowerShell似乎没有类似du那样的命令，但是可以通过自动函数来实现这个功能。</p><p>打开PowerShell的环境环境配置，我本地安装的是VS Code，那么就执行如下命令：</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">code <span class="variable">$PROFILE</span></span><br></pre></td></tr></table></figure><p>执行后，VS Code会打开一个配置文件，在最下面新增如下代码：</p><figure class="highlight powershell"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Get-DirSize</span></span> &#123;</span><br><span class="line">    <span class="keyword">param</span> (</span><br><span class="line">        [<span class="built_in">string</span>]<span class="variable">$Path</span> = <span class="string">&quot;.&quot;</span>,</span><br><span class="line">        [<span class="type">switch</span>]<span class="variable">$GB</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    <span class="built_in">Write-Host</span> <span class="string">&quot;正在计算目录大小，请稍候...&quot;</span> <span class="literal">-ForegroundColor</span> Cyan</span><br><span class="line"></span><br><span class="line">    <span class="built_in">Get-ChildItem</span> <span class="literal">-Path</span> <span class="variable">$Path</span> <span class="literal">-Directory</span>  <span class="built_in">ForEach-Object</span> &#123;</span><br><span class="line">        <span class="variable">$subFiles</span> = <span class="built_in">Get-ChildItem</span> <span class="variable">$_</span>.FullName <span class="literal">-Recurse</span> <span class="operator">-File</span> <span class="literal">-ErrorAction</span> SilentlyContinue</span><br><span class="line">        <span class="variable">$sizeSum</span> = (<span class="variable">$subFiles</span>  <span class="built_in">Measure-Object</span> <span class="literal">-Property</span> Length <span class="literal">-Sum</span>).Sum</span><br><span class="line">        </span><br><span class="line">        <span class="comment"># 默认显示 MB，如果指定 -GB 参数则显示 GB</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="variable">$GB</span>) &#123;</span><br><span class="line">            <span class="variable">$finalSize</span> = [<span class="type">math</span>]::Round(<span class="variable">$sizeSum</span> / <span class="number">1</span>GB, <span class="number">2</span>)</span><br><span class="line">            <span class="variable">$unit</span> = <span class="string">&quot;GB&quot;</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="variable">$finalSize</span> = [<span class="type">math</span>]::Round(<span class="variable">$sizeSum</span> / <span class="number">1</span>MB, <span class="number">2</span>)</span><br><span class="line">            <span class="variable">$unit</span> = <span class="string">&quot;MB&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        [<span class="type">PSCustomObject</span>]<span class="selector-tag">@</span>&#123;</span><br><span class="line">            FolderName = <span class="variable">$_</span>.Name</span><br><span class="line">            Size       = <span class="string">&quot;<span class="variable">$finalSize</span> <span class="variable">$unit</span>&quot;</span></span><br><span class="line">            RawSize    = <span class="variable">$sizeSum</span> <span class="comment"># 用于后续排序</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;  <span class="built_in">Sort-Object</span> RawSize <span class="literal">-Descending</span>  <span class="built_in">Select-Object</span> FolderName, Size</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后保存并关闭，执行如下代码使其生效。</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="variable">$PROFILE</span>  </span><br></pre></td></tr></table></figure><p>或者重新打开PowerShell也可以让其生效。</p><h2 id="统计文件大小"><a href="#统计文件大小" class="headerlink" title="统计文件大小"></a>统计文件大小</h2><p>该函数使用方法如下：</p><p><strong>查看当前目录：</strong> 直接输入 <code>Get-DirSize</code></p><p><strong>查看指定目录：</strong> 输入 <code>Get-DirSize -Path &quot;D:\Work&quot;</code></p><p><strong>以 GB 为单位显示：</strong> 输入 <code>Get-DirSize -GB</code></p><p>注意，尽可能不要去扫描那些没有权限的目录，如果非要扫描，那就需要使用管理员启动PowerShell（这是我默认启动方式）。通常占用比较大的目录就是下面几个</p><figure class="highlight powershell"><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">C:\ProgramData\</span><br><span class="line">C:\Users\用户\AppData\Local</span><br><span class="line">C:\Users\用户\AppData\Roaming</span><br><span class="line">C:\Users\用户\（如果有maven、node、docker、rustup、cargo、scoop、cursor等在这里占用也比较大）</span><br></pre></td></tr></table></figure><p>接下来就可以根据实际情况进行统计删除了。效果如下：</p><figure class="highlight powershell"><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></pre></td><td class="code"><pre><span class="line"> <span class="built_in">Get-DirSize</span></span><br><span class="line">正在计算目录大小，请稍候...</span><br><span class="line"></span><br><span class="line">FolderName                           Size</span><br><span class="line"><span class="literal">----------</span>                           <span class="literal">----</span></span><br><span class="line">Kaspersky Lab                        <span class="number">6890.59</span> MB</span><br><span class="line">NVIDIA                               <span class="number">4536.47</span> MB</span><br><span class="line">NVIDIA Corporation                   <span class="number">4189.88</span> MB</span><br><span class="line">Microsoft                            <span class="number">2385.78</span> MB</span><br><span class="line">Lenovo                               <span class="number">1654.15</span> MB</span><br><span class="line">LogiOptionsPlus                      <span class="number">1060.71</span> MB</span><br><span class="line">Package Cache                        <span class="number">686.49</span> MB</span><br><span class="line">Battle.net                           <span class="number">219.41</span> MB</span><br><span class="line">Dropbox                              <span class="number">105.59</span> MB</span><br><span class="line">USOShared                            <span class="number">82.74</span> MB</span><br><span class="line">Oray                                 <span class="number">79.04</span> MB</span><br><span class="line">Oracle                               <span class="number">78.73</span> MB</span><br><span class="line">Logishrd                             <span class="number">58.36</span> MB</span><br><span class="line">Windows Master Store                 <span class="number">30.03</span> MB</span><br><span class="line">A<span class="literal">-Volute</span>                             <span class="number">29.77</span> MB</span><br><span class="line">Tobii                                <span class="number">26.83</span> MB</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://dev.net.cn/how-to-calculate-folder-size-with-powershell/</id>
    <link href="https://dev.net.cn/how-to-calculate-folder-size-with-powershell/"/>
    <published>2026-01-11T01:25:37.000Z</published>
    <summary>
      <![CDATA[<p>在这两年使用Windows的过程中，总是遇到一个问题就是200G的C盘空间，动不动就爆满，这还是在我把腾讯系的数据目录迁移到其他盘、所有软件能不安装在C盘就不安装的情况下发生的。印象中2015年以前，我的Windows电脑C盘才60G。最开始我都是通过联想自带的清理工具进行硬盘清理，但是很显然这样的方式不够理想，而且我也禁用了联想的服务，那么就需要手动删除。手动删除就要先统计下那些目录占用的空间比较多，根据实际情况有选择的进行删除。</p>]]>
    </summary>
    <title>PowerShell统计Windows的文件夹大小</title>
    <updated>2026-01-11T01:25:37.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="WordPress" scheme="https://dev.net.cn/categories/WordPress/"/>
    <category term="WordPress" scheme="https://dev.net.cn/tags/WordPress/"/>
    <category term="PHP" scheme="https://dev.net.cn/tags/PHP/"/>
    <content>
      <![CDATA[<p>更新到WordPress6.9后，发信无法对评论回复进行邮件通知，并且WordPress自带的评论审核邮件也是非常的原始，本文就介绍下如何解决邮件通知和评论审核邮件美化问题。</p><span id="more"></span><h2 id="解决邮件通知问题"><a href="#解决邮件通知问题" class="headerlink" title="解决邮件通知问题"></a>解决邮件通知问题</h2><p>首先，需要安装一个利用STMP发送邮件的插件，本文推荐FluentSMTP。根据插件配置，先配置好SMTP，并发送一份测试邮件，确保SMTP配置正确。</p><p>此时，只能做到评论通知，但回复评论却无法发送邮件。</p><p>打开外观-&gt;主题文件编辑器，一般主题都会有一个自定义的Theme Functions(functions.php)，在这里添加如下代码：</p><figure class="highlight php"><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="comment">// 修复发送邮件的问题</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">use_no_sender</span>(<span class="params"> <span class="variable">$phpmailer</span> </span>) </span>&#123;</span><br><span class="line"><span class="variable">$phpmailer</span>-&gt;Sender = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_ invoke__">add_action</span>( <span class="string">&#x27;phpmailer_init&#x27;</span>, <span class="string">&#x27;use_no_sender&#x27;</span> );</span><br></pre></td></tr></table></figure><p>点击保存后即可修复评论回复邮件通知的问题。</p><h2 id="邮件通知美化"><a href="#邮件通知美化" class="headerlink" title="邮件通知美化"></a>邮件通知美化</h2><p>依旧在外观-&gt;主题文件编辑器的Theme Functions(functions.php)中，添加如下代码：</p><figure class="highlight php"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//WordPress 评论回复邮件通知代码</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">comment_mail_notify</span>(<span class="params"><span class="variable">$comment_id</span></span>) </span>&#123;</span><br><span class="line"><span class="variable">$admin_email</span> = <span class="title function_ invoke__">get_bloginfo</span> (<span class="string">&#x27;admin_email&#x27;</span>);</span><br><span class="line"><span class="variable">$blogname</span> = <span class="title function_ invoke__">wp_specialchars_decode</span>(<span class="title function_ invoke__">get_option</span>(<span class="string">&#x27;blogname&#x27;</span>), ENT_QUOTES);</span><br><span class="line"><span class="variable">$comment</span> = <span class="title function_ invoke__">get_comment</span>(<span class="variable">$comment_id</span>);</span><br><span class="line"><span class="variable">$parent_id</span> = <span class="variable">$comment</span>-&gt;comment_parent ? <span class="variable">$comment</span>-&gt;comment_parent : <span class="string">&#x27;&#x27;</span>;</span><br><span class="line"><span class="variable">$spam_confirmed</span> = <span class="variable">$comment</span>-&gt;comment_approved;</span><br><span class="line"><span class="keyword">global</span> <span class="variable">$wpdb</span>;</span><br><span class="line"><span class="variable">$comments_waiting</span> = <span class="variable">$wpdb</span>-&gt;<span class="title function_ invoke__">get_var</span>(<span class="string">&quot;SELECT count(comment_ID) FROM <span class="subst">$wpdb</span>-&gt;comments WHERE comment_approved = &#x27;0&#x27;&quot;</span>);</span><br><span class="line"><span class="keyword">if</span> ((<span class="variable">$parent_id</span> != <span class="string">&#x27;&#x27;</span>) &amp;&amp; (<span class="variable">$spam_confirmed</span> != <span class="string">&#x27;spam&#x27;</span>) &amp;&amp; (<span class="variable">$to</span> != <span class="variable">$admin_email</span>)) &#123;</span><br><span class="line"><span class="variable">$wp_email</span> = <span class="string">&#x27;no-reply@&#x27;</span> . <span class="title function_ invoke__">preg_replace</span>(<span class="string">&#x27;#^www\.#&#x27;</span>, <span class="string">&#x27;&#x27;</span>, <span class="title function_ invoke__">strtolower</span>(<span class="variable">$_SERVER</span>[<span class="string">&#x27;SERVER_NAME&#x27;</span>]));</span><br><span class="line"><span class="variable">$to</span> = <span class="title function_ invoke__">trim</span>(<span class="title function_ invoke__">get_comment</span>(<span class="variable">$parent_id</span>)-&gt;comment_author_email);</span><br><span class="line"><span class="variable">$subject</span> = <span class="string">&#x27;您在 [&#x27;</span> . <span class="variable">$blogname</span> . <span class="string">&#x27;]&#x27;</span> . <span class="string">&#x27; 中的留言有了新回复！&#x27;</span>;</span><br><span class="line"><span class="variable">$message</span> = <span class="string">&#x27;&lt;div style=&quot;background-color:white;border-left: 2px solid #555555;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;width:500px;margin:50px auto;color:#555555;font-family:&quot;Source Sans Pro&quot;,&quot;Hiragino Sans GB&quot;,&quot;Microsoft Yahei&quot;,SimSun,Helvetica,Arial,Sans-serif,monospace;font-size:14px;&quot;&gt; </span></span><br><span class="line"><span class="string">            &lt;h2 style=&quot;border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;&quot;&gt;&lt;span style=&quot;color: #f59200;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;您在 &lt;a style=&quot;text-decoration:none; color:#f59200;font-weight:600;&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">home_url</span>() . <span class="string">&#x27;&quot;&gt;&#x27;</span> . <span class="variable">$blogname</span> . <span class="string">&#x27;&lt;/a&gt; 的留言有回复啦！&lt;/h2&gt;&lt;div style=&quot;font-size: 14px; color: #777; padding: 0 10px; margin-top: 18px;&quot;&gt;</span></span><br><span class="line"><span class="string">&lt;p&gt;&lt;b&gt;&#x27;</span> . <span class="title function_ invoke__">trim</span>(<span class="title function_ invoke__">get_comment</span>(<span class="variable">$parent_id</span>)-&gt;comment_author)  . <span class="string">&#x27;&lt;/b&gt; 同学，您曾在文章&lt;b&gt;《&#x27;</span> . <span class="title function_ invoke__">get_the_title</span>(<span class="variable">$comment</span>-&gt;comment_post_ID) . <span class="string">&#x27;》&lt;/b&gt;上发表评论:&lt;/p&gt;</span></span><br><span class="line"><span class="string">&lt;p style=&quot;background: #F5F5F5; padding: 10px 15px; margin: 18px 0;&quot;&gt;&#x27;</span> . <span class="title function_ invoke__">nl2br</span>(<span class="title function_ invoke__">strip_tags</span>(<span class="title function_ invoke__">get_comment</span>(<span class="variable">$parent_id</span>)-&gt;comment_content)) . <span class="string">&#x27;&lt;/p&gt;</span></span><br><span class="line"><span class="string">&lt;p&gt;&#x27;</span> . <span class="string">&#x27;&lt;b&gt;&#x27;</span> . <span class="title function_ invoke__">trim</span>(<span class="variable">$comment</span>-&gt;comment_author) . <span class="string">&#x27;&lt;/b&gt;&#x27;</span>. <span class="string">&#x27; 给您的回复如下:&lt;/p&gt;</span></span><br><span class="line"><span class="string">&lt;p style=&quot;background: #F5F5F5; padding: 10px 15px; margin: 18px 0;&quot;&gt;&#x27;</span> . <span class="title function_ invoke__">nl2br</span>(<span class="title function_ invoke__">strip_tags</span>(<span class="variable">$comment</span>-&gt;comment_content)) . <span class="string">&#x27;&lt;/p&gt;</span></span><br><span class="line"><span class="string">&lt;p&gt;您可以点击 &lt;a style=&quot;text-decoration:none; color:#f59200&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">htmlspecialchars</span>(<span class="title function_ invoke__">get_comment_link</span>(<span class="variable">$parent_id</span>)) . <span class="string">&#x27;&quot;&gt;查看完整的回复內容&lt;/a&gt;，也欢迎再次光临 &lt;a style=&quot;text-decoration:none; color:#f59200&quot;</span></span><br><span class="line"><span class="string">href=&quot;&#x27;</span> . <span class="title function_ invoke__">home_url</span>() . <span class="string">&#x27;&quot;&gt;&#x27;</span> . <span class="variable">$blogname</span> . <span class="string">&#x27;&lt;/a&gt;。祝您生活愉快！&lt;/p&gt;</span></span><br><span class="line"><span class="string">&lt;p style=&quot;padding-bottom: 15px;&quot;&gt;(此邮件由系统自动发出,请勿直接回复!)&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&#x27;</span>;</span><br><span class="line"><span class="variable">$from</span> = <span class="string">&quot;From: \&quot;&quot;</span> . <span class="title function_ invoke__">get_option</span>(<span class="string">&#x27;blogname&#x27;</span>) . <span class="string">&quot;\&quot; &lt;<span class="subst">$wp_email</span>&gt;&quot;</span>;</span><br><span class="line"><span class="variable">$headers</span> = <span class="string">&quot;<span class="subst">$from</span>\nContent-Type: text/html; charset=&quot;</span> . <span class="title function_ invoke__">get_option</span>(<span class="string">&#x27;blog_charset&#x27;</span>) . <span class="string">&quot;\n&quot;</span>;</span><br><span class="line"><span class="title function_ invoke__">wp_mail</span>( <span class="variable">$to</span>, <span class="variable">$subject</span>, <span class="variable">$message</span>, <span class="variable">$headers</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">if</span> (<span class="variable">$parent_id</span> == <span class="string">&#x27;&#x27;</span> &amp;&amp; (<span class="title function_ invoke__">trim</span>(<span class="variable">$comment</span>-&gt;comment_author_email) != <span class="title function_ invoke__">trim</span>(<span class="variable">$admin_email</span>)) &amp;&amp; (<span class="variable">$spam_confirmed</span> != <span class="string">&#x27;spam&#x27;</span>) &amp;&amp; (<span class="variable">$comment</span>-&gt;comment_approved != <span class="number">0</span>))&#123;</span><br><span class="line">        <span class="variable">$wp_email</span> = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">        <span class="variable">$subject</span> = <span class="string">&#x27;在「&#x27;</span> . <span class="variable">$blogname</span> .<span class="string">&#x27;」的文章《&#x27;</span>. <span class="title function_ invoke__">get_the_title</span>(<span class="variable">$comment</span>-&gt;comment_post_ID) .<span class="string">&#x27;》一文有新的评论&#x27;</span>;</span><br><span class="line">        <span class="variable">$message</span> = <span class="string">&#x27;&lt;div style=&quot;background-color:white;border-left: 2px solid #555555;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;width:500px;margin:50px auto;color:#555555;font-family:&quot;Source Sans Pro&quot;,&quot;Hiragino Sans GB&quot;,&quot;Microsoft Yahei&quot;,SimSun,Helvetica,Arial,Sans-serif,monospace;font-size:14px;&quot;&gt; </span></span><br><span class="line"><span class="string">            &lt;h2 style=&quot;border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;&quot;&gt;&lt;span style=&quot;color: #f59200;font-weight: bold;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;a style=&quot;text-decoration:none;color: #f59200;&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">home_url</span>() . <span class="string">&#x27;&quot;&gt;&#x27;</span> . <span class="variable">$blogname</span> . <span class="string">&#x27;&lt;/a&gt; 博客有新的评论啦！ &lt;/h2&gt; </span></span><br><span class="line"><span class="string">            &lt;div style=&quot;padding:0 12px 0 12px;margin-top:18px;&quot;&gt; </span></span><br><span class="line"><span class="string">            &lt;p&gt;&lt;b&gt;&#x27;</span>. <span class="variable">$comment</span>-&gt;comment_author . <span class="string">&#x27;&lt;/b&gt; 同学在文章&lt;b&gt;《&#x27;</span> . <span class="title function_ invoke__">get_the_title</span>(<span class="variable">$comment</span>-&gt;comment_post_ID) . <span class="string">&#x27;》&lt;/b&gt;上发表评论:&lt;/p&gt; </span></span><br><span class="line"><span class="string">            &lt;p style=&quot;background-color: #f5f5f5;border: 0px solid #DDD;padding: 10px 15px;margin:18px 0;&quot;&gt;&#x27;</span> . <span class="variable">$comment</span>-&gt;comment_content . <span class="string">&#x27;&lt;/p&gt; </span></span><br><span class="line"><span class="string">            &lt;p&gt;您可以点击 &lt;a style=&quot;text-decoration:none; color:#f59200&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">htmlspecialchars</span>(<span class="title function_ invoke__">get_comment_link</span>(<span class="variable">$parent_id</span>)) . <span class="string">&#x27;&quot;&gt;查看完整的回复內容&lt;/a&gt;，也欢迎再次光临 &lt;a style=&quot;text-decoration:none; color:#f59200&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">home_url</span>() . <span class="string">&#x27;&quot;&gt;&#x27;</span> . <span class="variable">$blogname</span> . <span class="string">&#x27;&lt;/a&gt;。祝您生活愉快！&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&#x27;</span>;</span><br><span class="line">        <span class="variable">$headers</span> = <span class="string">&quot;Content-Type: text/html; charset=&quot;</span> . <span class="title function_ invoke__">get_option</span>(<span class="string">&#x27;blog_charset&#x27;</span>) . <span class="string">&quot;\n&quot;</span>;</span><br><span class="line">        <span class="title function_ invoke__">wp_mail</span>( <span class="variable">$admin_email</span>, <span class="variable">$subject</span>, <span class="variable">$message</span>, <span class="variable">$headers</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">if</span> (<span class="variable">$parent_id</span> == <span class="string">&#x27;&#x27;</span> &amp;&amp; (<span class="title function_ invoke__">trim</span>(<span class="variable">$comment</span>-&gt;comment_author_email) != <span class="title function_ invoke__">trim</span>(<span class="variable">$admin_email</span>)) &amp;&amp; (<span class="variable">$spam_confirmed</span> != <span class="string">&#x27;spam&#x27;</span>) &amp;&amp; (<span class="variable">$spam_confirmed</span> != <span class="string">&#x27;trash&#x27;</span>)  &amp;&amp; (<span class="variable">$comment</span>-&gt;comment_approved == <span class="number">0</span>))&#123;</span><br><span class="line">        <span class="variable">$wp_email</span> = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">        <span class="variable">$subject</span> = <span class="string">&#x27;在「&#x27;</span> . <span class="variable">$blogname</span> .<span class="string">&#x27;」的文章《&#x27;</span> . <span class="title function_ invoke__">get_the_title</span>(<span class="variable">$comment</span>-&gt;comment_post_ID) . <span class="string">&#x27;》中有新的评论需要审核&#x27;</span>;</span><br><span class="line">        <span class="variable">$message</span> = <span class="string">&#x27;&lt;div style=&quot;background-color:white;border-left: 2px solid #555555;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;width:500px;margin:50px auto;color:#555555;font-family:&quot;Source Sans Pro&quot;,&quot;Hiragino Sans GB&quot;,&quot;Microsoft Yahei&quot;,SimSun,Helvetica,Arial,Sans-serif,monospace;font-size:14px;&quot;&gt; </span></span><br><span class="line"><span class="string">            &lt;h2 style=&quot;border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;&quot;&gt;&lt;span style=&quot;color: #f59200;font-weight: bold;&quot;&gt;&amp;gt; 「 &lt;/span&gt;&lt;a style=&quot;text-decoration:none;color: #f59200;&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">home_url</span>() . <span class="string">&#x27;&quot;&gt;&#x27;</span> . <span class="variable">$blogname</span> . <span class="string">&#x27;」&lt;/a&gt; 中有一条评论等待您的审核 &lt;/h2&gt; </span></span><br><span class="line"><span class="string">            &lt;div style=&quot;padding:0 12px 0 12px;margin-top:18px;&quot;&gt; </span></span><br><span class="line"><span class="string">            &lt;p&gt;&lt;b&gt;&#x27;</span>. <span class="variable">$comment</span>-&gt;comment_author . <span class="string">&#x27;&lt;/b&gt; 同学在文章&lt;b&gt;&lt;a style=&quot;text-decoration:none;color: #f59200;&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">get_permalink</span>(<span class="variable">$comment</span>-&gt;comment_post_ID) . <span class="string">&#x27;&quot;&gt;《&#x27;</span> . <span class="title function_ invoke__">get_the_title</span>(<span class="variable">$comment</span>-&gt;comment_post_ID) . <span class="string">&#x27;》&lt;/a&gt;&lt;/b&gt;上发表评论:&lt;/p&gt; </span></span><br><span class="line"><span class="string">            &lt;p style=&quot;background-color: #f5f5f5;border: 0px solid #DDD;padding: 10px 15px;margin:18px 0;&quot;&gt;&#x27;</span> . <span class="variable">$comment</span>-&gt;comment_content . <span class="string">&#x27;&lt;/p&gt; </span></span><br><span class="line"><span class="string">            &lt;p&gt;&lt;a style=&quot;text-decoration:none;color: #12ADDB;&quot; href=&quot;&#x27;</span>. <span class="title function_ invoke__">admin_url</span>( <span class="string">&quot;comment.php?action=approve&amp;c=<span class="subst">&#123;$comment_id&#125;</span>#wpbody-content&quot;</span> ) . <span class="string">&#x27;&quot;&gt;[批准评论]&lt;/a&gt;  &lt;a style=&quot;text-decoration:none;color: #12ADDB;&quot; href=&quot;&#x27;</span>. <span class="title function_ invoke__">admin_url</span>( <span class="string">&quot;comment.php?action=trash&amp;c=<span class="subst">&#123;$comment_id&#125;</span>#wpbody-content&quot;</span> ) . <span class="string">&#x27;&quot;&gt;[移至回收站]&lt;/a&gt;。您还可以：&lt;a style=&quot;text-decoration:none; color:#12ADDB&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">admin_url</span>( <span class="string">&quot;comment.php?action=delete&amp;c=<span class="subst">&#123;$comment_id&#125;</span>#wpbody-content&quot;</span> ) . <span class="string">&#x27;&quot;&gt;永久删除评论&lt;/a&gt;  &lt;a style=&quot;text-decoration:none;color: #12ADDB;&quot; href=&quot;&#x27;</span>. <span class="title function_ invoke__">admin_url</span>( <span class="string">&quot;comment.php?action=spam&amp;c=<span class="subst">&#123;$comment_id&#125;</span>#wpbody-content&quot;</span> ) . <span class="string">&#x27;&quot;&gt;标记为垃圾评论&lt;/a&gt;</span></span><br><span class="line"><span class="string">&lt;p&gt;当前有 &#x27;</span> . <span class="variable">$comments_waiting</span> . <span class="string">&#x27; 条评论等待审核。请移步&lt;a style=&quot;text-decoration:none;color: #f59200;&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">admin_url</span>(<span class="string">&#x27;edit-comments.php?comment_status=moderated#wpbody-content&#x27;</span>) . <span class="string">&#x27;&quot;&gt;审核页面&lt;/a&gt;来查看。&lt;/p&gt;也欢迎再次光临 &lt;a style=&quot;text-decoration:none; color:#f59200&quot; href=&quot;&#x27;</span> . <span class="title function_ invoke__">home_url</span>() . <span class="string">&#x27;&quot;&gt;&#x27;</span> . <span class="variable">$blogname</span> . <span class="string">&#x27;&lt;/a&gt;。祝您生活愉快！&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&#x27;</span>;</span><br><span class="line">        <span class="variable">$headers</span> = <span class="string">&quot;Content-Type: text/html; charset=&quot;</span> . <span class="title function_ invoke__">get_option</span>(<span class="string">&#x27;blog_charset&#x27;</span>) . <span class="string">&quot;\n&quot;</span>;</span><br><span class="line">        <span class="title function_ invoke__">wp_mail</span>( <span class="variable">$admin_email</span>, <span class="variable">$subject</span>, <span class="variable">$message</span>, <span class="variable">$headers</span> );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_ invoke__">add_action</span>(<span class="string">&#x27;comment_post&#x27;</span>, <span class="string">&#x27;comment_mail_notify&#x27;</span>);</span><br></pre></td></tr></table></figure><p>点击保存。然后去设置-&gt; 讨论中，将如下三个选项关闭。</p><p><img src="https://cdn.dev.net.cn/dev/images/2026/01/wordpress-mail-01.png?x-oss-process=style/full"></p><p>此时就可以收到美化后的通知邮件了，下面是我在另一给网站测试的效果图：</p><p><strong>评论审核</strong></p><p><img src="https://cdn.dev.net.cn/dev/images/2026/01/wordpress-mail-02.png?x-oss-process=style/full"></p><p><strong>回复评论通知</strong></p><p><img src="https://cdn.dev.net.cn/dev/images/2026/01/wordpress-mail-03.png?x-oss-process=style/full"></p><p>如果需要自己定义样式，可根据以上的代码进行编写。</p>]]>
    </content>
    <id>https://dev.net.cn/how-to-beautify-wordpress-comment-notification-emails/</id>
    <link href="https://dev.net.cn/how-to-beautify-wordpress-comment-notification-emails/"/>
    <published>2026-01-07T12:12:46.000Z</published>
    <summary>
      <![CDATA[<p>更新到WordPress6.9后，发信无法对评论回复进行邮件通知，并且WordPress自带的评论审核邮件也是非常的原始，本文就介绍下如何解决邮件通知和评论审核邮件美化问题。</p>]]>
    </summary>
    <title>WordPress6.9 评论通知邮件美化</title>
    <updated>2026-01-07T12:12:46.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Windows" scheme="https://dev.net.cn/categories/Windows/"/>
    <category term="Windows" scheme="https://dev.net.cn/tags/Windows/"/>
    <category term="PowerShell" scheme="https://dev.net.cn/tags/PowerShell/"/>
    <category term="webp" scheme="https://dev.net.cn/tags/webp/"/>
    <content>
      <![CDATA[<p>最开始因为懒，所以一直用的在线转换。虽然方便但也有个弊端，速度慢、广告多还涉及隐私问题。于是就动了自己转换的想法，看了下<a href="https://developers.google.com/speed/webp/download?hl=zh-cn">Google官方工具</a>也是支持windows的，就懒得往WSL里面装了。</p><p>目前我使用winget安装：</p><figure class="highlight powershell"><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">winget install libwebp</span><br><span class="line"></span><br><span class="line"><span class="comment"># scoop </span></span><br><span class="line">scoop install libwebp</span><br></pre></td></tr></table></figure><p>安装完成后重新启动powershell就可以使用cweb命令了。</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">cwebp <span class="literal">-q</span> 质量（<span class="number">0</span><span class="literal">-100</span>，越小质量越差，默认是<span class="number">75</span>） .\cloudflare.png（需要转换的图片） <span class="literal">-o</span> .\cloudflare.webp（转换后输出的图片）</span><br></pre></td></tr></table></figure><p>示例：</p><figure class="highlight powershell"><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">cwebp <span class="literal">-q</span> <span class="number">80</span> .\cloudflare.png <span class="literal">-o</span> .\cloudflare.webp</span><br><span class="line">Saving file <span class="string">&#x27;.\cloudflare.webp&#x27;</span></span><br><span class="line">File:      .\cloudflare.png</span><br><span class="line">Dimension: <span class="number">1200</span> x <span class="number">800</span></span><br><span class="line">Output:    <span class="number">9794</span> bytes Y<span class="literal">-U-V-All-PSNR</span> <span class="number">54.05</span> <span class="number">51.73</span> <span class="number">51.72</span>   <span class="number">53.13</span> dB</span><br><span class="line">           (<span class="number">0.08</span> bpp)</span><br><span class="line">block count:  intra4:        <span class="number">241</span>  (<span class="number">6.43</span>%)</span><br><span class="line">              intra16:      <span class="number">3509</span>  (<span class="number">93.57</span>%)</span><br><span class="line">              skipped:      <span class="number">3454</span>  (<span class="number">92.11</span>%)</span><br><span class="line">bytes used:  header:            <span class="number">235</span>  (<span class="number">2.4</span>%)</span><br><span class="line">             mode<span class="literal">-partition</span>:   <span class="number">2485</span>  (<span class="number">25.4</span>%)</span><br><span class="line"> Residuals bytes  segment <span class="number">1</span>segment <span class="number">2</span>segment <span class="number">3</span>segment <span class="number">4</span>  total</span><br><span class="line">    macroblocks:         <span class="number">1</span>%       <span class="number">3</span>%       <span class="number">4</span>%      <span class="number">92</span>%    <span class="number">3750</span></span><br><span class="line">      quantizer:        <span class="number">27</span>       <span class="number">27</span>       <span class="number">27</span>       <span class="number">18</span> </span><br><span class="line">   <span class="keyword">filter</span> level:         <span class="number">8</span>        <span class="number">6</span>        <span class="number">5</span>        <span class="number">2</span> </span><br></pre></td></tr></table></figure><p>如果本地图片多，还可以写成脚本，批量执行。</p><figure class="highlight powershell"><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="variable">$images</span> = <span class="built_in">Get-ChildItem</span> <span class="literal">-Path</span> (<span class="built_in">Get-Location</span>) <span class="literal">-Filter</span> *.png</span><br><span class="line"><span class="keyword">foreach</span> (<span class="variable">$image</span> <span class="keyword">in</span> <span class="variable">$images</span>) &#123;</span><br><span class="line">  <span class="variable">$fileName</span> = <span class="variable">$image</span>.DirectoryName + <span class="string">&quot;\&quot;</span> + <span class="variable">$image</span>.BaseName + <span class="string">&quot;.webp&quot;</span></span><br><span class="line">  cwebp.exe <span class="literal">-q</span> <span class="number">80</span> <span class="variable">$image</span>.FullName <span class="literal">-o</span> <span class="variable">$fileName</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://dev.net.cn/how-to-install-and-use-cwebp-on-windows11/</id>
    <link href="https://dev.net.cn/how-to-install-and-use-cwebp-on-windows11/"/>
    <published>2026-01-06T11:28:04.000Z</published>
    <summary>
      <![CDATA[<p>最开始因为懒，所以一直用的在线转换。虽然方便但也有个弊端，速度慢、广告多还涉及隐私问题。于是就动了自己转换的想法，看了下<a href="https://developers.google.com/speed/webp/download?hl=zh-cn">Google官方]]>
    </summary>
    <title>Windows11安装webp转换程序cweb</title>
    <updated>2026-01-06T11:28:04.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="CloudFlare" scheme="https://dev.net.cn/categories/CloudFlare/"/>
    <category term="CloudFlare" scheme="https://dev.net.cn/tags/CloudFlare/"/>
    <content>
      <![CDATA[<p>本站一直使用Typora+PicGo组合来处理markdown和图片的，以往都是用的是阿里云OSS，但最近看到不少受害者一觉醒来被刷掉几千块，为了避免遭受此问题，我还是将所有站点的静态资源从阿里云OSS迁移到CloudFlare R2。本次记录一下PicGo的配置过程。</p><h2 id="下载插件"><a href="#下载插件" class="headerlink" title="下载插件"></a>下载插件</h2><p>PicGo默认不支持CloudFlare R2，但有插件系统，可以通过别人开发的插件来实现。由于CloudFlare R2兼容S3，所以我们只需要下载S3插件即可。在插件列表中搜索S3：</p><p><img src="https://cdn.tvzr.com/images/tech/2026/01/image-20260106115154144.png" alt="picgo-plugins"></p><p>插件版本不同配置也会稍微有些差异。本次PigGo版本为<code>2.4.1</code>、插件版本为<code>s3 1.5.1</code>。</p><h2 id="新建CloudFlare-R2桶"><a href="#新建CloudFlare-R2桶" class="headerlink" title="新建CloudFlare R2桶"></a>新建CloudFlare R2桶</h2><p>打开CloudFlare的R2，点击创建存储桶</p><p><img src="https://cdn.tvzr.com/images/tech/2026/01/image-20260106115611935.png" alt="创建存储桶"></p><p>填写桶名称即可，其他默认。创建好以后，点击<code>刚才新建的桶</code>-&gt;<code>设置</code>。自定义域，绑定自己的域名。如果域名在CloudFlare，这一切都是自动的，点点就完事。</p><h2 id="创建API-Tokens"><a href="#创建API-Tokens" class="headerlink" title="创建API Tokens"></a>创建API Tokens</h2><p>在桶列表的右侧，<code>Account Details</code>中，点击<code>Manage</code>标签，打开令牌页面。点击<code>创建User Api令牌</code></p><p><img src="https://cdn.tvzr.com/images/tech/2026/01/image-20260106120118630.png" alt="创建令牌"></p><p>创建成功后会出现如下页面。</p><div class="note warning modern"><p>请注意别关页面，这玩意只显示一次，安全起见也没必要保存，页面停留着即可。</p></div><p><img src="https://cdn.tvzr.com/images/tech/2026/01/image-20260106115457048.png" alt="配置CloudFlareR2的API令牌"></p><h2 id="配置PicGo的S3"><a href="#配置PicGo的S3" class="headerlink" title="配置PicGo的S3"></a>配置PicGo的S3</h2><h3 id="打开图床配置界面，新增一个配置，或者修改默认配置。"><a href="#打开图床配置界面，新增一个配置，或者修改默认配置。" class="headerlink" title="打开图床配置界面，新增一个配置，或者修改默认配置。"></a>打开图床配置界面，新增一个配置，或者修改默认配置。</h3><p><img src="https://cdn.tvzr.com/images/tech/2026/01/image-20260106120413673.png" alt="主界面-图床设置"></p><h3 id="图床配置名"><a href="#图床配置名" class="headerlink" title="图床配置名"></a>图床配置名</h3><p>就是给你的图床起个别名，方便自己选中，例如我的名称就是<code>CloudFlare R2</code></p><h3 id="应用密钥"><a href="#应用密钥" class="headerlink" title="应用密钥"></a>应用密钥</h3><p>这里填写刚才创建API页面中的<code>访问密钥ID</code></p><h3 id="应用密钥-1"><a href="#应用密钥-1" class="headerlink" title="应用密钥"></a>应用密钥</h3><p>填写刚才创建API页面中的<code>机密访问密钥</code></p><h3 id="桶名"><a href="#桶名" class="headerlink" title="桶名"></a>桶名</h3><p>填写刚才创建的桶名称</p><h3 id="上传文件路径"><a href="#上传文件路径" class="headerlink" title="上传文件路径"></a>上传文件路径</h3><p>这里按你需要填写。假设你的自定义域名是<code>https://img.abc.com</code>，你想要在桶中创建一个<code>images/tech</code>（因为我有多个子站点，用于区分）目录，并且将图片以<code>年/月/文件名.后缀</code>保存，那么那就填写<code>images/tech/&#123;year&#125;/&#123;month&#125;/&#123;fullName&#125;</code>,具体占位符规则如下：</p><table><thead><tr><th align="center">payload</th><th align="center">描述</th></tr></thead><tbody><tr><td align="center">{year}</td><td align="center">当前日期-年</td></tr><tr><td align="center">{month}</td><td align="center">当前日期-月</td></tr><tr><td align="center">{day}</td><td align="center">当前日期-日</td></tr><tr><td align="center">{hour}</td><td align="center">当然日期-时</td></tr><tr><td align="center">{minute}</td><td align="center">当前日期-分</td></tr><tr><td align="center">{second}</td><td align="center">当前日期-秒</td></tr><tr><td align="center">{millisecond}</td><td align="center">当前日期-毫秒</td></tr><tr><td align="center">{timestamp}</td><td align="center">Unix时间戳</td></tr><tr><td align="center">{timestampMS}</td><td align="center">Unix时间戳（毫秒）</td></tr><tr><td align="center">{fullName}</td><td align="center">完整的文件名（包含后缀）</td></tr><tr><td align="center">{fileName}</td><td align="center">文件名（不包含后缀）</td></tr><tr><td align="center">{extName}</td><td align="center">扩展名（不含<code>.</code>）</td></tr><tr><td align="center">{md5}</td><td align="center">图片MD5计算值</td></tr><tr><td align="center">{sha1}</td><td align="center">图片SHA1计算值</td></tr><tr><td align="center">{sha256}</td><td align="center">图片SHA256计算值</td></tr></tbody></table><h3 id="地区"><a href="#地区" class="headerlink" title="地区"></a>地区</h3><p>刚才创建的时候给的是亚太的确，如果你不知道是哪个地区填<code>auto</code>即可。</p><h3 id="自定义节点"><a href="#自定义节点" class="headerlink" title="自定义节点"></a>自定义节点</h3><p>填写刚才创建的API中的<code>为 S3 客户端使用管辖权地特定的终结点</code>的地址，以<code>r2.cloudflarestorage.com</code>结尾的那个。</p><h3 id="代理"><a href="#代理" class="headerlink" title="代理"></a>代理</h3><p>可以空着，如果你本地网络无法访问R2，可以填写你得shadowsockets地址。目前R2还未被封禁（拜托各位邻居轻点蹬）。</p><h3 id="拒绝无效TLS证书连接"><a href="#拒绝无效TLS证书连接" class="headerlink" title="拒绝无效TLS证书连接"></a>拒绝无效TLS证书连接</h3><p>选项切换到<code>yes</code>即可。</p><h3 id="ACL访问控制列表"><a href="#ACL访问控制列表" class="headerlink" title="ACL访问控制列表"></a>ACL访问控制列表</h3><p>填写<code>public-read</code>即可。</p><h3 id="ForcePathStyle"><a href="#ForcePathStyle" class="headerlink" title="ForcePathStyle"></a>ForcePathStyle</h3><p>建议开启，因为我们要使用自定义域名去访问图片。</p><h3 id="自定义输出URL模板"><a href="#自定义输出URL模板" class="headerlink" title="自定义输出URL模板"></a>自定义输出URL模板</h3><p>空着就行</p><h3 id="设置输出图片URL前缀"><a href="#设置输出图片URL前缀" class="headerlink" title="设置输出图片URL前缀"></a>设置输出图片URL前缀</h3><p>填写绑定到桶上的自定义域名，例如<code>https://img.abc.com</code></p><h3 id="设置输出图片URL后缀"><a href="#设置输出图片URL后缀" class="headerlink" title="设置输出图片URL后缀"></a>设置输出图片URL后缀</h3><p>这个一般是处理图片样式、动态裁剪图片的。虽然CloudFlare也支持images来处理图片样式，但是我并没有开启，相对R2，它还是略微贵一点，原本就是为了怕被刷导致破费才换到R2的，没必要开启这个。</p><h3 id="Bucket前缀"><a href="#Bucket前缀" class="headerlink" title="Bucket前缀"></a>Bucket前缀</h3><p>建议开启。因为我想要的路径是<code>https://img.abc.com/images/tech/2026/01/xxx.webp</code>这种格式，如果不开启，它会自带一个层桶的目录，变成了<code>https://img.abc.com/桶名称/images/tech/2026/01/xxx.webp</code>。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>有些配置项还是有些歧义，但多试试就可以了。后续写个脚本，批量将阿里云的文件全部迁移到<code>CloudFlare R2</code>。</p>]]>
    </content>
    <id>https://dev.net.cn/piggo-configuration-cloudflare-r2/</id>
    <link href="https://dev.net.cn/piggo-configuration-cloudflare-r2/"/>
    <published>2026-01-05T03:00:00.000Z</published>
    <summary>
      <![CDATA[<p>本站一直使用Typora+PicGo组合来处理markdown和图片的，以往都是用的是阿里云OSS，但最近看到不少受害者一觉醒来被刷掉几千块，为了避免遭受此问题，我还是将所有站点的静态资源从阿里云OSS迁移到CloudFlare R2。本次记录一下PicGo的配置过程。</]]>
    </summary>
    <title>PicGo配置CloudflareR2</title>
    <updated>2026-01-05T03:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Charles</name>
    </author>
    <category term="Java" scheme="https://dev.net.cn/categories/Java/"/>
    <category term="Java" scheme="https://dev.net.cn/tags/Java/"/>
    <content>
      <![CDATA[<p>2025年9月，Java开发者将迎来一个重要的里程碑——JDK25的发布。作为长期支持版本（LTS），JDK25不仅带来了多项语言增强，还在性能、安全和用户体验方面进行了显著优化。本文将为您详细介绍JDK25的主要功能预览，让您提前领略这一版本的强大功能。</p><span id="more"></span><h2 id="语言特性增强"><a href="#语言特性增强" class="headerlink" title="语言特性增强"></a>语言特性增强</h2><h3 id="基本类型模式匹配（JEP-507）"><a href="#基本类型模式匹配（JEP-507）" class="headerlink" title="基本类型模式匹配（JEP 507）"></a>基本类型模式匹配（JEP 507）</h3><p>JDK25在Java的模式匹配框架<code>instanceof</code>和<code>switch</code>中直接支持原始类型（如<code>int</code>、<code>boolean</code>），打破基本类型（Primitive Types）与引用类型（Reference Types）在模式匹配中的隔阂，让基本类型在 <code>instanceof</code> 和 <code>switch</code> 中也能像对象一样灵活使用。例如：</p><figure class="highlight java"><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">// 使用 instanceof 检查安全转换</span></span><br><span class="line"><span class="keyword">if</span> (obj <span class="keyword">instanceof</span> <span class="type">int</span> i) &#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;这是一个可以安全存入 int 的数值: &quot;</span> + i);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 在 switch 中直接匹配基本类型</span></span><br><span class="line"><span class="keyword">return</span> <span class="keyword">switch</span> (val) &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="type">int</span> i -&gt; <span class="string">&quot;整数: &quot;</span> + i;</span><br><span class="line">    <span class="keyword">case</span> <span class="type">double</span> d &amp;&amp; d &gt; <span class="number">0</span> -&gt; <span class="string">&quot;正浮点数: &quot;</span> + d;</span><br><span class="line">    <span class="keyword">case</span> <span class="type">boolean</span> b -&gt; <span class="string">&quot;布尔值: &quot;</span> + b;</span><br><span class="line">    <span class="keyword">default</span> -&gt; <span class="string">&quot;其他&quot;</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>对比下Java21之前得做法</p><figure class="highlight java"><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="keyword">if</span> (obj <span class="keyword">instanceof</span> Long l) &#123;</span><br><span class="line">    <span class="comment">// 手动转换</span></span><br><span class="line">    <span class="keyword">if</span> (l &gt;= Integer.MIN_VALUE &amp;&amp; l &lt;= Integer.MAX_VALUE) &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> l.intValue();</span><br><span class="line">        System.out.println(<span class="string">&quot;安全转换: &quot;</span> + i);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这一改进让代码更加简洁，提高了开发效率。</p><h3 id="模块导入声明（JEP-511）"><a href="#模块导入声明（JEP-511）" class="headerlink" title="模块导入声明（JEP 511）"></a>模块导入声明（JEP 511）</h3><p>JDK25引入了<code>import module</code>语句，用于声明模块依赖，替代部分包导入。缺点是增加了重名得风险。例如：</p><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//Java 21之前</span></span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"><span class="keyword">import</span> java.util.stream.Stream;</span><br><span class="line"><span class="keyword">import</span> java.io.File;</span><br><span class="line"><span class="keyword">import</span> java.nio.file.Path;</span><br><span class="line"></span><br><span class="line"><span class="comment">//Java 25</span></span><br><span class="line"><span class="keyword">import</span> <span class="keyword">module</span> java.base;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="压缩源文件与实例主方法（JEP-512）"><a href="#压缩源文件与实例主方法（JEP-512）" class="headerlink" title="压缩源文件与实例主方法（JEP 512）"></a>压缩源文件与实例主方法（JEP 512）</h3><p>JDK25简化了程序入口，支持类级别的<code>void main()</code>方法，无需<code>public static</code>修饰。如果你的 <code>.java</code> 文件中没有显式定义 <code>class</code>，编译器会为你自动生成一个<strong>隐式类（Implicitly Declared Class）</strong>。例如：</p><figure class="highlight java"><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"><span class="comment">// Java 25之前</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloWorld</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;Hello, World!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Java 25</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">main</span><span class="params">()</span> &#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;Hello Java 25!&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="灵活的构造函数体（JEP-513）"><a href="#灵活的构造函数体（JEP-513）" class="headerlink" title="灵活的构造函数体（JEP 513）"></a>灵活的构造函数体（JEP 513）</h3><p><strong>JEP 513</strong> 是 Java 25（JDK 25）中一个非常实用的语法增强，全称为 <strong>“Flexible Constructor Bodies”（灵活的构造函数体）</strong>。</p><p>它打破了 Java 自诞生以来的一条铁律：<strong>“构造函数的第一行必须是 <code>super()</code> 或 <code>this()</code>”</strong>。例如：</p><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// Java21 之前</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SubClass</span> <span class="keyword">extends</span> <span class="title class_">SuperClass</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">SubClass</span><span class="params">(<span class="type">int</span> value)</span> &#123;</span><br><span class="line">        <span class="comment">// 这里不能写 if (value &lt; 0) ... 必须第一行就是 super</span></span><br><span class="line">        <span class="built_in">super</span>(prepareValue(value)); </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">prepareValue</span><span class="params">(<span class="type">int</span> v)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (v &lt; <span class="number">0</span>) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalArgumentException</span>();</span><br><span class="line">        <span class="keyword">return</span> v;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Java25</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SubClass</span> <span class="keyword">extends</span> <span class="title class_">SuperClass</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">SubClass</span><span class="params">(<span class="type">int</span> value)</span> &#123;</span><br><span class="line">        <span class="comment">// ✅ 允许：在 super 之前进行校验</span></span><br><span class="line">        <span class="keyword">if</span> (value &lt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalArgumentException</span>(<span class="string">&quot;值不能为负数&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// ✅ 允许：在 super 之前初始化自己的字段</span></span><br><span class="line">        <span class="built_in">this</span>.someField = value * <span class="number">2</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="built_in">super</span>(value); <span class="comment">// 显式调用父类构造函数</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>关键规则：</p><p>虽然变灵活了，但 Java 依然保留了底层的安全红线，以确保对象初始化顺序的正确性：</p><ol><li><strong>序言（Prologue）限制</strong>：在调用 <code>super()</code> 之前的代码块被称为“序言”。在序言中，你<strong>不能访问 <code>this</code> 指针（即不能调用实例方法）</strong>。</li><li><strong>字段赋值</strong>：你可以给当前类定义的字段赋值，但不能读取它们。</li><li><strong>构造函数链</strong>：<code>super()</code> 或 <code>this()</code> 依然必须被调用（显式或隐式），只是它们不再必须位于第一行。</li><li><strong>异常处理</strong>：你可以在 <code>super()</code> 之前抛出异常，这样如果参数不合法，根本就不会触发昂贵的父类初始化过程，性能更优。</li></ol><p>引入特性的原因：</p><ul><li><p><strong>增强安全性</strong>：允许在父类构造函数运行之前验证参数，防止父类在无效状态下启动。</p></li><li><p><strong>代码可读性</strong>：不再需要为了绕过“第一行限制”而创建大量隐蔽的 <code>private static</code> 辅助方法。</p></li><li><p><strong>字段初始化</strong>：子类可以在父类构造函数运行前初始化自己的字段。这解决了一个经典坑：如果父类构造函数中调用了一个被子类覆写的方法，子类字段此时已经有值了，而不会是默认值。</p></li></ul><h2 id="性能优化"><a href="#性能优化" class="headerlink" title="性能优化"></a>性能优化</h2><h3 id="压缩对象头（JEP-519）"><a href="#压缩对象头（JEP-519）" class="headerlink" title="压缩对象头（JEP 519）"></a>压缩对象头（JEP 519）</h3><p>JDK25通过在对象中头使用紧凑的同步和标识数据布局，减少了64位体系结构上的对象头大小，从而减少了Java对象的内存占用。</p><h3 id="String类性能改进"><a href="#String类性能改进" class="headerlink" title="String类性能改进"></a>String类性能改进</h3><p>通过常量折叠优化，JDK25提升了静态不可修改Map的查询效率，加速了键值检索。</p><h3 id="结构化并发"><a href="#结构化并发" class="headerlink" title="结构化并发"></a>结构化并发</h3><p>JDK25将子任务视为逻辑单元，父任务取消时自动终止子线程，简化了错误处理和取消操作，防止资源泄漏，提升了高并发的可靠性。</p><h2 id="安全特性增强"><a href="#安全特性增强" class="headerlink" title="安全特性增强"></a>安全特性增强</h2><h3 id="抗量子加密算法"><a href="#抗量子加密算法" class="headerlink" title="抗量子加密算法"></a>抗量子加密算法</h3><p>JDK25引入了基于晶格密码的<code>ML-KEM</code>（密钥）封装和<code>ML-DSA</code>（数字签名），以抵御未来量子计算攻击。</p><h3 id="加密功能扩展"><a href="#加密功能扩展" class="headerlink" title="加密功能扩展"></a>加密功能扩展</h3><p>JDK25支持PEM格式密钥交换，并支持多种加密标准。</p><h3 id="作用域值（ScopedValue）"><a href="#作用域值（ScopedValue）" class="headerlink" title="作用域值（ScopedValue）"></a>作用域值（ScopedValue）</h3><p>JDK25引入了<code>ScopedValue</code>，替代<code>ThreadLocal</code>，支持线程间安全共享不可变数据，简化了生命周期管理。</p><h2 id="体验优化"><a href="#体验优化" class="headerlink" title="体验优化"></a>体验优化</h2><h3 id="飞行记录仪（JFR）升级"><a href="#飞行记录仪（JFR）升级" class="headerlink" title="飞行记录仪（JFR）升级"></a>飞行记录仪（JFR）升级</h3><p>JDK25增强了Linux系统CPU时间分析，精准定位性能瓶颈，并支持协作式采样，优化Java程序性能。</p><h3 id="类文件API转正"><a href="#类文件API转正" class="headerlink" title="类文件API转正"></a>类文件API转正</h3><p>JDK25标准化了类文件解析与生成接口，取代了ASM等第三方库。</p><h3 id="垃圾回收器改进"><a href="#垃圾回收器改进" class="headerlink" title="垃圾回收器改进"></a>垃圾回收器改进</h3><p>JDK25正式转正了Shenandoah分代回收器，优化了内存管理效率，并增强了G1垃圾回收器的后期屏障，减少了停顿时间。</p><h3 id="弃用陈旧特性"><a href="#弃用陈旧特性" class="headerlink" title="弃用陈旧特性"></a>弃用陈旧特性</h3><p>JDK25完全删除了32位x86平台的支持，包括删除相关源代码、移除构建配置和测试基础设施中与x86-32相关的内容，只保留对x86-64（64位）平台的支持，推动现代化硬件迁移。</p>]]>
    </content>
    <id>https://dev.net.cn/java-25-lts-new-features/</id>
    <link href="https://dev.net.cn/java-25-lts-new-features/"/>
    <published>2026-01-03T08:00:00.000Z</published>
    <summary>
      <![CDATA[<p>2025年9月，Java开发者将迎来一个重要的里程碑——JDK25的发布。作为长期支持版本（LTS），JDK25不仅带来了多项语言增强，还在性能、安全和用户体验方面进行了显著优化。本文将为您详细介绍JDK25的主要功能预览，让您提前领略这一版本的强大功能。</p>]]>
    </summary>
    <title>Java25新特性</title>
    <updated>2026-01-03T08:00:00.000Z</updated>
  </entry>
</feed>
