<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="/lib/rss/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>月青悠</title>
    <link>https://vccv.cc/index.html</link>
    <description>Recent content on vccv.cc</description>
    <generator>Hugo</generator>
    <language>zh</language>
    <lastBuildDate>Sat, 26 Jul 2025 21:05:47 +0800</lastBuildDate>
    <atom:link href="https://vccv.cc/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>源码编译Flash Attention</title>
      <link>https://vccv.cc/article/flash-attn-compile.html</link>
      <pubDate>Sat, 26 Jul 2025 21:05:47 +0800</pubDate>
      <guid>https://vccv.cc/article/flash-attn-compile.html</guid>
      <description>记录一次在A800上折腾Flash Attention源码编译的笔记。如果你也遇到了编译时间过长、内存溢出killed等问题，本文提供的关键环境变量设置和踩坑经验或许能帮你节省一些时间。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>Flash Attention对于大语言模型（LLM）的训练和推理来说，几乎是必备的组件，其带来的性能提升有目共睹。通常<code>pip install flash-attn</code>就能搞定。但当我们面对特定硬件（比如A800）或者需要最新版的功能时，从源码编译就成了绕不开的路。</p>
<p>在跳坑多次后（：，今天还是来记录一下在A800服务器上，从源码编译安装<code>flash-attn</code>的完整过程，以及其中遇到的一些“坑”和关键注意事项。</p>
<h2 id="环境与背景">环境与背景</h2>
<h3 id="本地环境">本地环境</h3>
<ul>
<li><strong>服务器</strong>: 64 Cores CPU, 512G RAM</li>
<li><strong>GPU</strong>: NVIDIA A800 80G (PCIe)</li>
<li><strong>CUDA</strong>: 12.2</li>
<li><strong>PyTorch</strong>: 2.7.1+cu118</li>
</ul>
<h3 id="官方仓库的readme文档">官方仓库的<a href="https://github.com/Dao-AILab/flash-attention" target="_blank" rel="noopener">README文档</a></h3>
<blockquote>
<p><strong>Requirements:</strong></p>
<ul>
<li>CUDA toolkit or ROCm toolkit</li>
<li>PyTorch 2.2 and above.</li>
<li><code>packaging</code> Python package (<code>pip install packaging</code>)</li>
<li><code>ninja</code> Python package (<code>pip install ninja</code>) *</li>
<li>Linux. Might work for Windows starting v2.3.2 (we&rsquo;ve seen a few positive <a href="https://github.com/Dao-AILab/flash-attention/issues/595" target="_blank" rel="noopener">reports</a>) but Windows compilation still requires more testing. If you have ideas on how to set up prebuilt CUDA wheels for Windows, please reach out via Github issue.</li>
</ul>
<p>* Make sure that <code>ninja</code> is installed and that it works correctly (e.g. <code>ninja --version</code> then <code>echo $?</code> should return exit code 0). If not (sometimes <code>ninja --version</code> then <code>echo $?</code> returns a nonzero exit code), uninstall then reinstall
<code>ninja</code> (<code>pip uninstall -y ninja &amp;&amp; pip install ninja</code>). Without <code>ninja</code>,
compiling can take a very long time (2h) since it does not use multiple CPU
cores. With <code>ninja</code> compiling takes 3-5 minutes on a 64-core machine using CUDA toolkit.</p>
<p><strong>To install:</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install flash-attn --no-build-isolation
</span></span></code></pre></td></tr></table>
</div>
</div><p>Alternatively you can compile from source:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">python setup.py install
</span></span></code></pre></td></tr></table>
</div>
</div><p>If your machine has less than 96GB of RAM and lots of CPU cores, <code>ninja</code> might
run too many parallel compilation jobs that could exhaust the amount of RAM. To
limit the number of parallel compilation jobs, you can set the environment
variable <code>MAX_JOBS</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">MAX_JOBS</span><span class="o">=</span><span class="m">4</span> pip install flash-attn --no-build-isolation
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<p>小吐槽：官方文档提到“With <code>ninja</code> compiling takes 3-5 minutes on a 64-core machine using CUDA toolkit.”，不知道他们的设备该有多好，羡慕ing。。。</p>
<h2 id="核心编译步骤">核心编译步骤</h2>
<h3 id="升级基础构建工具">升级基础构建工具</h3>
<p>在开始任何编译工作前，一个良好且最新的构建环境能避免掉80%的玄学问题。所以，确保<code>pip</code>,<code>wheel</code>和<code>setuptools</code>都是最新的。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install pip wheel setuptools -U
</span></span></code></pre></td></tr></table>
</div>
</div><p>旧的<code>setuptools</code>可能会在解析构建脚本时格外的慢，不要问我怎么知道的。。。</p>
<h3 id="安装并验证ninja">安装并验证<code>ninja</code></h3>
<p><a href="https://github.com/Dao-AILab/flash-attention" target="_blank" rel="noopener">官方文档</a>也强调了<code>ninja</code>的重要性。没有它，编译过程会退化成单线程，耗时可能从几分钟飙升到几小时。哦不，几十分钟变成几百分钟也不是不可能。（官方仓库issue里面的<strong>真人真事</strong></p>
<ol>
<li>
<p><strong>安装 Ninja</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install ninja
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>验证 Ninja</strong></p>
<p>官方文档提到的验证方法是运行<code>ninja --version</code>然后<code>echo $?</code>查看退出码是否为 0。 我个人更推荐一个更直观的方法：在开始编译后，立刻新开一个终端，执行<code>htop</code>。如果你看到 CPU 列表里几十个<code>cicc</code>或者<code>nvcc</code>进程在同时运行，把 CPU 核心吃满，那<code>ninja</code>就肯定在正常工作了。</p>
<p><a href="/article/flash-attn-compile/QQ_1753589440483_hu_846e30db22456e4e.webp" data-fancybox="gallery" data-src="/article/flash-attn-compile/QQ_1753589440483_hu_846e30db22456e4e.webp" data-caption="安装ninja后自动启用多线程">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/flash-attn-compile/QQ_1753589440483_hu_ac174cddc668ad3d.webp 480w, /article/flash-attn-compile/QQ_1753589440483_hu_8c818226d4cf0724.webp 720w, /article/flash-attn-compile/QQ_1753589440483_hu_f0014322694fb7e8.webp 960w, /article/flash-attn-compile/QQ_1753589440483_hu_529684eb3af8189e.webp 1440w, /article/flash-attn-compile/QQ_1753589440483_hu_846e30db22456e4e.webp 2662w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2662"
                    height="986"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/flash-attn-compile/QQ_1753589440483_hu_8c818226d4cf0724.webp"
                    srcset="/article/flash-attn-compile/QQ_1753589440483_hu_ac174cddc668ad3d.webp 480w, /article/flash-attn-compile/QQ_1753589440483_hu_8c818226d4cf0724.webp 720w, /article/flash-attn-compile/QQ_1753589440483_hu_f0014322694fb7e8.webp 960w, /article/flash-attn-compile/QQ_1753589440483_hu_529684eb3af8189e.webp 1440w, /article/flash-attn-compile/QQ_1753589440483_hu_846e30db22456e4e.webp 2662w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="安装ninja后自动启用多线程"
                    
                />
            </picture>
        </a></p>
<p>如果发现<code>ninja</code>工作不正常，最直接的办法是彻底重装：<code>pip uninstall -y ninja &amp;&amp; pip install ninja</code>。</p>
</li>
</ol>
<h3 id="配置关键环境变量">配置关键环境变量</h3>
<p>这是整个编译过程的灵魂，直接决定了编译能否成功以及效率如何。</p>
<ol>
<li>
<p><strong><code>FLASH_ATTN_CUDA_ARCHS</code>：指定 GPU 计算能力</strong></p>
<p>这个环境变量告诉编译器，我们只为特定架构的 GPU 生成代码。A100 和 A800 的 <strong>Compute Capability</strong> 都是<code>8.0</code>，因此我们设置为 &ldquo;80&rdquo;。如果不指定，它会尝试编译所有支持的架构，很浪费时间。</p>
<ul>
<li><strong>查询地址</strong>: <a href="https://developer.nvidia.com/cuda-gpus" target="_blank" rel="noopener">NVIDIA CUDA GPUs</a></li>
</ul>
<p>在终端中设置：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">FLASH_ATTN_CUDA_ARCHS</span><span class="o">=</span><span class="s2">&#34;80&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong><code>MAX_JOBS</code>：设置并行编译任务数</strong></p>
<p>这个变量控制<code>ninja</code>并行编译时使用的 CPU 核心数。理论上越多越快，但代价是内存消耗剧增。需要根据机器的 CPU 核心数和内存大小权衡。</p>
<ul>
<li><strong>我的实践</strong>: 在 64 核 CPU、512GB 内存的机器上，我大胆地设置为<code>MAX_JOBS=64</code>。</li>
<li><strong>性能表现</strong>:<code>htop</code>显示 64 核全满，编译峰值内存占用超过 300GB，耗时约 10-15 分钟。一个有趣的观察是，当<code>htop</code>中看到内存占用开始显著回落时，说明编译已接近尾声。</li>
<li><strong>建议</strong>: 如果你的内存没那么充裕，可以从 CPU 核心数的一半开始尝试，例如<code>MAX_JOBS=32</code>。</li>
</ul>
</li>
</ol>
<h3 id="最终执行安装">最终执行安装</h3>
<p>万事俱备，只欠东风。整合所有环境变量，执行最终的安装命令。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">FLASH_ATTN_CUDA_ARCHS</span><span class="o">=</span><span class="s2">&#34;80&#34;</span> <span class="nv">MAX_JOBS</span><span class="o">=</span><span class="m">64</span> pip install flash-attn --no-build-isolation
</span></span></code></pre></td></tr></table>
</div>
</div><p>这里必须加上<code>--no-build-isolation</code>参数。它的作用是告诉<code>pip</code>在当前 shell 环境中直接构建，而不是创建一个隔离的虚拟环境。这样，我们刚刚<code>export</code>的那些环境变量才能被构建进程正确读取。</p>
<h2 id="一些小坑troubleshooting">一些“小”坑（Troubleshooting）</h2>
<ul>
<li>
<p><strong>问题一：编译报错<code>g++: fatal error: Killed signal terminated program cc1plus</code></strong></p>
<ul>
<li><strong>原因</strong>：这 99% 是内存不足（OOM Killer 发威了）。<code>cc1plus</code>是 C++ 编译器进程，<code>MAX_JOBS</code>设置得太高，并行进程过多，瞬间就把内存吃完了。</li>
<li><strong>解决</strong>：调低<code>MAX_JOBS</code>的值，比如从 64 降到 32 或者 16 再试。</li>
</ul>
</li>
<li>
<p><strong>问题二：提示GNU版本太高</strong></p>
<ul>
<li>
<p><strong>原因</strong>：截止发文时，编译要求<code>gcc-11</code>和<code>g++-11</code>。</p>
<p><a href="/article/flash-attn-compile/QQ_1753589136678_hu_252a1dc1ae1e066a.webp" data-fancybox="gallery" data-src="/article/flash-attn-compile/QQ_1753589136678_hu_252a1dc1ae1e066a.webp" data-caption="gcc版本要求最高11">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/flash-attn-compile/QQ_1753589136678_hu_4e8ba902ee6b284b.webp 480w, /article/flash-attn-compile/QQ_1753589136678_hu_346fc47c1875c921.webp 720w, /article/flash-attn-compile/QQ_1753589136678_hu_ccda90b81c294ca1.webp 960w, /article/flash-attn-compile/QQ_1753589136678_hu_1ca6ecf4f7d8e998.webp 1440w, /article/flash-attn-compile/QQ_1753589136678_hu_252a1dc1ae1e066a.webp 2668w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2668"
                    height="1098"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/flash-attn-compile/QQ_1753589136678_hu_346fc47c1875c921.webp"
                    srcset="/article/flash-attn-compile/QQ_1753589136678_hu_4e8ba902ee6b284b.webp 480w, /article/flash-attn-compile/QQ_1753589136678_hu_346fc47c1875c921.webp 720w, /article/flash-attn-compile/QQ_1753589136678_hu_ccda90b81c294ca1.webp 960w, /article/flash-attn-compile/QQ_1753589136678_hu_1ca6ecf4f7d8e998.webp 1440w, /article/flash-attn-compile/QQ_1753589136678_hu_252a1dc1ae1e066a.webp 2668w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="gcc版本要求最高11"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p><strong>解决</strong>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 以Ubuntu22.04为例</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 安装gcc-11</span>
</span></span><span class="line"><span class="cl">apt install gcc-11 g++-11
</span></span><span class="line"><span class="cl"><span class="c1"># 查看路径</span>
</span></span><span class="line"><span class="cl">which gcc-11
</span></span><span class="line"><span class="cl">which g++-11
</span></span><span class="line"><span class="cl"><span class="c1"># 设置环境变量</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CC</span><span class="o">=</span>/usr/bin/gcc-11
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CXX</span><span class="o">=</span>/usr/bin/g++-11
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
</li>
<li>
<p><strong>问题三：编译时间长得离谱</strong></p>
<ul>
<li><strong>原因</strong>：<code>ninja</code>没有正常工作，编译退化成了单线程模式。</li>
<li><strong>解决</strong>：按上文的方法验证<code>ninja</code>。检查是否安装，或者重装<code>ninja</code>。</li>
</ul>
</li>
<li>
<p><strong>问题四：各种 CUDA 相关的编译错误</strong></p>
<ul>
<li><strong>原因</strong>：大概率是<code>FLASH_ATTN_CUDA_ARCHS</code>没设对，或者 PyTorch 版本与 CUDA Toolkit 版本不兼容。</li>
<li><strong>解决</strong>：再次确认你的 GPU 型号和对应的计算能力。检查<code>nvidia-smi</code>和<code>nvcc --version</code>的输出，确保环境一致。</li>
</ul>
</li>
</ul>
<h2 id="备选方案">备选方案</h2>
<p>如果源码编译实在折腾不下去，或者你只是想快速用上一个稳定版，可以考虑：</p>
<ol>
<li><strong>pip 安装预编译包</strong>:<code>pip</code>仓库有时会提供针对主流环境的预编译包（wheels）。直接<code>pip install flash-attn</code>有时就能成功，但版本不一定最新，且不保证支持最新硬件。</li>
<li><strong>conda 安装</strong>:<code>conda</code>渠道也可能提供预编译好的<code>flash-attn</code>，值得一试，运行<code>conda install flash-attn -c conda-forge</code>即可。</li>
</ol>
<h2 id="致谢">致谢</h2>
<p><a href="https://github.com/Dao-AILab/flash-attention" target="_blank" rel="noopener">Flash Attention官方仓库</a></p>
<p><a href="https://github.com/Dao-AILab/flash-attention/issues" target="_blank" rel="noopener">官方仓库的issue</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>VS Code助力Python远程开发</title>
      <link>https://vccv.cc/article/vscode-python-remote-development.html</link>
      <pubDate>Tue, 14 Jan 2025 17:12:58 +0800</pubDate>
      <guid>https://vccv.cc/article/vscode-python-remote-development.html</guid>
      <description>简要介绍一下vscode与ssh的远程开发联动，顺带推荐一下notebook。现在发现在python的远程服务器开发中配合使用notebook是真的太方便了。熟悉流程后部署非常快，主要是真的太！方！便！了！！！</description>
      <content:encoded><![CDATA[<h2 id="开门见山">开门见山</h2>
<p>我们的目的便是通过<a href="https://code.visualstudio.com" target="_blank" rel="noopener">Visual Studio Code</a>，以下简称<code>vscode</code>，这个著名且免费的IDE来进行远程开发。本篇特指通过<strong>SSH连接远程服务器进行开发</strong>这一类需求，并且实现近乎本地开发的体验。特别是针对Jupyter Notebook的体验，配合vscode的notebook插件，效果是真的很好。</p>
<blockquote>
<p>为了行文方便，在文中我将对以下名称的叫法进行统一：</p>
<ul>
<li>Visual Studio Code这个软件 &raquo; &raquo; &raquo; vscode</li>
<li>你的远程服务器，通常是Linux系统 &raquo; &raquo; &raquo; 远程服务器</li>
<li>你的本地主机，可能是Windows系统、macOS系统或者Linux系统 &raquo; &raquo; &raquo; 宿主机</li>
<li>Remote-SSH这个vscode的插件 &raquo; &raquo; &raquo; remote插件</li>
<li>Jupyter Notebook这个工具 &raquo; &raquo; &raquo; notebook</li>
<li>vscode的扩展或者插件功能，英文名extension &raquo; &raquo; &raquo; 插件</li>
</ul>
</blockquote>
<p>vscode能获得如此成功，在我看来，很大一部分要归功于其开源的伟大以及丰富且活跃开发的插件（扩展）市场。进行远程开发，也是由<code>Remote-SSH</code>插件实现的，以下简称为remote插件。</p>
<p><a href="/article/vscode-python-remote-development/image-20250114172655999_hu_5ce2fe555b744b14.webp" data-fancybox="gallery" data-src="/article/vscode-python-remote-development/image-20250114172655999_hu_5ce2fe555b744b14.webp" data-caption="Remote-SSH插件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/vscode-python-remote-development/image-20250114172655999_hu_cd9ee5fc29b6dc23.webp 480w, /article/vscode-python-remote-development/image-20250114172655999_hu_7865ced146d7f75a.webp 720w, /article/vscode-python-remote-development/image-20250114172655999_hu_f40b331df0e747ab.webp 960w, /article/vscode-python-remote-development/image-20250114172655999_hu_5ea45bb823be981c.webp 1440w, /article/vscode-python-remote-development/image-20250114172655999_hu_5ce2fe555b744b14.webp 1678w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1678"
                    height="414"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/vscode-python-remote-development/image-20250114172655999_hu_7865ced146d7f75a.webp"
                    srcset="/article/vscode-python-remote-development/image-20250114172655999_hu_cd9ee5fc29b6dc23.webp 480w, /article/vscode-python-remote-development/image-20250114172655999_hu_7865ced146d7f75a.webp 720w, /article/vscode-python-remote-development/image-20250114172655999_hu_f40b331df0e747ab.webp 960w, /article/vscode-python-remote-development/image-20250114172655999_hu_5ea45bb823be981c.webp 1440w, /article/vscode-python-remote-development/image-20250114172655999_hu_5ce2fe555b744b14.webp 1678w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Remote-SSH插件"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>远程开发其实远不止通过SSH连接远程服务器，还包含了：</p>
<ul>
<li>Windows宿主机连接本地的WSL（Windows Subsystem for Linux）子系统。</li>
<li>连接本地的Docker镜像。</li>
<li>连接GitHub的代码空间（Codespaces）。</li>
</ul>
</blockquote>
<p>所以进行远程开发的第一步，就是<a href="https://code.visualstudio.com/Download" target="_blank" rel="noopener">下载vscode</a>并且安装remote插件，安装后在左下角会出现一个远程连接的快捷图标。</p>
<blockquote>
<p>如果插件安装失败，建议升级vscode或者卸载后重新安装。</p>
</blockquote>
<p><a href="/article/vscode-python-remote-development/image-20250114180224389_hu_cf5657df9b94a98e.webp" data-fancybox="gallery" data-src="/article/vscode-python-remote-development/image-20250114180224389_hu_cf5657df9b94a98e.webp" data-caption="安装remote插件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/vscode-python-remote-development/image-20250114180224389_hu_8e9c7eeb08ecd804.webp 480w, /article/vscode-python-remote-development/image-20250114180224389_hu_137351019c458612.webp 720w, /article/vscode-python-remote-development/image-20250114180224389_hu_3d3faabe34fa564c.webp 960w, /article/vscode-python-remote-development/image-20250114180224389_hu_cbc5330076ec159e.webp 1440w, /article/vscode-python-remote-development/image-20250114180224389_hu_cf5657df9b94a98e.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1700"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/vscode-python-remote-development/image-20250114180224389_hu_137351019c458612.webp"
                    srcset="/article/vscode-python-remote-development/image-20250114180224389_hu_8e9c7eeb08ecd804.webp 480w, /article/vscode-python-remote-development/image-20250114180224389_hu_137351019c458612.webp 720w, /article/vscode-python-remote-development/image-20250114180224389_hu_3d3faabe34fa564c.webp 960w, /article/vscode-python-remote-development/image-20250114180224389_hu_cbc5330076ec159e.webp 1440w, /article/vscode-python-remote-development/image-20250114180224389_hu_cf5657df9b94a98e.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="安装remote插件"
                    
                />
            </picture>
        </a></p>
<h2 id="配置服务器信息">配置服务器信息</h2>
<p>点击左下角的快捷图标后，针对远程开发的不同对象选择对应选项，我们这里选择<strong>连接到主机</strong>。接下来便是填写具体的远程服务器信息，提供两种方式进行参考。</p>
<h3 id="方法一ssh命令">方法一：ssh命令</h3>
<p><a href="/article/vscode-python-remote-development/image-20250114213238538_hu_d7b7690ef200342c.webp" data-fancybox="gallery" data-src="/article/vscode-python-remote-development/image-20250114213238538_hu_d7b7690ef200342c.webp" data-caption="ssh命令登录">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/vscode-python-remote-development/image-20250114213238538_hu_dd58619068502464.webp 480w, /article/vscode-python-remote-development/image-20250114213238538_hu_12163038dbb5b969.webp 720w, /article/vscode-python-remote-development/image-20250114213238538_hu_e0f556e9645bae0f.webp 960w, /article/vscode-python-remote-development/image-20250114213238538_hu_6a55ffc340d0770f.webp 1440w, /article/vscode-python-remote-development/image-20250114213238538_hu_d7b7690ef200342c.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1700"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/vscode-python-remote-development/image-20250114213238538_hu_12163038dbb5b969.webp"
                    srcset="/article/vscode-python-remote-development/image-20250114213238538_hu_dd58619068502464.webp 480w, /article/vscode-python-remote-development/image-20250114213238538_hu_12163038dbb5b969.webp 720w, /article/vscode-python-remote-development/image-20250114213238538_hu_e0f556e9645bae0f.webp 960w, /article/vscode-python-remote-development/image-20250114213238538_hu_6a55ffc340d0770f.webp 1440w, /article/vscode-python-remote-development/image-20250114213238538_hu_d7b7690ef200342c.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="ssh命令登录"
                    
                />
            </picture>
        </a></p>
<p>可以直接在输入框中输入完整的<code>ssh</code>命令即可成功进行配置，本段下面的代码框给出了详细的解释和示例。需要注意的是，<code>username</code>替换为远程服务器上自己的用户名，<code>host</code>替换为远程服务器的IP地址或者域名，<code>port</code>替换为远程服务器的端口。需要跳板机的情况下，<code>-J</code>后输入的同样是在跳板机上面的用户名、跳板机host以及跳板机端口。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># port默认为22</span>
</span></span><span class="line"><span class="cl"><span class="c1"># username@后面的host 可以是ip地址（例如127.0.0.1） 也可以是域名（例如vccv.cc）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 需要跳板机的意思是 只能通过先登录到跳板机A 再通过跳板机A登录到最终的目标服务器B</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 这通常是为了安全考虑 目标服务器B并不直接暴露在公网中 而是与跳板机A处于同一内网</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 第一种情况 不需要跳板机</span>
</span></span><span class="line"><span class="cl">ssh username@host:port
</span></span><span class="line"><span class="cl"><span class="c1"># 示例：</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ssh yuesir@127.0.0.1:22</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ssh yuesir@vccv.cc:22</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 第二种情况 需要跳板机 增加-J参数</span>
</span></span><span class="line"><span class="cl">ssh username@host:port -J username@host:port
</span></span><span class="line"><span class="cl"><span class="c1"># 示例：</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 跳板机A上我的用户名是yuesir A的host是192.168.0.1 A的port是22</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 目标服务器B上我的用户名是yueqingyou B的host是192.168.0.2 B的port是2222</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ssh yueqingyou@192.168.0.2:2222 -J yuesir@192.168.0.1:22</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="方法二config文件">方法二：config文件</h3>
<p>通过输入ssh命令成功连接到服务器后，vscode会自动将远程服务器相关配置信息保存到config配置文件中，理所当然的可以直接编辑config文件达到与命令一致的效果。点击<strong>连接到主机 -&gt; 配置SSH主机</strong>后，通常选择自己用户目录下的<code>.ssh/config</code>文件，如图就是<code>yuesir</code>用户。</p>
<p><a href="/article/vscode-python-remote-development/image-20250114213636856_hu_e5fd05e466349f16.webp" data-fancybox="gallery" data-src="/article/vscode-python-remote-development/image-20250114213636856_hu_e5fd05e466349f16.webp" data-caption="配置文件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/vscode-python-remote-development/image-20250114213636856_hu_65e0642b5462d1db.webp 480w, /article/vscode-python-remote-development/image-20250114213636856_hu_4a6dfedec2f8e976.webp 720w, /article/vscode-python-remote-development/image-20250114213636856_hu_d3b9744e97d0c162.webp 960w, /article/vscode-python-remote-development/image-20250114213636856_hu_84ed307bf2d6e26.webp 1440w, /article/vscode-python-remote-development/image-20250114213636856_hu_e5fd05e466349f16.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1700"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/vscode-python-remote-development/image-20250114213636856_hu_4a6dfedec2f8e976.webp"
                    srcset="/article/vscode-python-remote-development/image-20250114213636856_hu_65e0642b5462d1db.webp 480w, /article/vscode-python-remote-development/image-20250114213636856_hu_4a6dfedec2f8e976.webp 720w, /article/vscode-python-remote-development/image-20250114213636856_hu_d3b9744e97d0c162.webp 960w, /article/vscode-python-remote-development/image-20250114213636856_hu_84ed307bf2d6e26.webp 1440w, /article/vscode-python-remote-development/image-20250114213636856_hu_e5fd05e466349f16.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="配置文件"
                    
                />
            </picture>
        </a></p>
<p>同样的，针对是否需要跳板机，给出两种配置文件格式，特别注意，这里的<code>Host</code>是服务器的名称，这只是一个昵称，方便用户快速辨认，可以随意指定，中英文均可。<strong>注意区别ssh命令中host的含义，配置文件中HostName才是与命令中host一致的含义</strong>。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 不需要跳板机</span>
</span></span><span class="line"><span class="cl">Host 服务器名称
</span></span><span class="line"><span class="cl">  HostName 服务器Host（IP或者域名）
</span></span><span class="line"><span class="cl">  Port 服务器端口
</span></span><span class="line"><span class="cl">  User 用户名
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl"><span class="c1"># 需要跳板机</span>
</span></span><span class="line"><span class="cl">Host 目标服务器名称
</span></span><span class="line"><span class="cl">  HostName 目标服务器Host（IP或者域名）
</span></span><span class="line"><span class="cl">  Port 目标服务器端口
</span></span><span class="line"><span class="cl">  User 用户名
</span></span><span class="line"><span class="cl">  ProxyJump 跳板机的用户名@跳板机的Host:跳板机的端口
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl"><span class="c1"># 示例：</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 跳板机A上我的用户名是yuesir A的host是192.168.0.1 A的port是22</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 目标服务器B上我的用户名是yueqingyou B的host是192.168.0.2 B的port是2222</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ssh yueqingyou@192.168.0.2:2222 -J yuesir@192.168.0.1:22</span>
</span></span><span class="line"><span class="cl">Host yueqingyou的服务器
</span></span><span class="line"><span class="cl">  HostName 192.168.0.2
</span></span><span class="line"><span class="cl">  Port <span class="m">2222</span>
</span></span><span class="line"><span class="cl">  User yueqingyou
</span></span><span class="line"><span class="cl">  ProxyJump yuesir@192.168.0.1:22
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="异常情况">异常情况</h3>
<p>这里需要多提醒一下，在连接过程中可能会遇到一直卡在<code>正在下载 VS Code 服务器</code>这个状态，原因就是远程服务器不能正常连接到<code>vscode-server</code>的地址，可能是由于服务器本身不通网，也可能是下载地址被墙不能直接访问。可以通过在本地宿主机手动下载后上传到服务器的方式解决这个问题，这里给出几篇文章以供参考。</p>
<ul>
<li><a href="https://www.cnblogs.com/michaelcjl/p/18262833" target="_blank" rel="noopener">离线安装 VS Code Server</a></li>
<li><a href="https://blog.csdn.net/mc_pang/article/details/123078089" target="_blank" rel="noopener">离线安装vscode server以及免密登录</a></li>
<li><a href="https://www.cnblogs.com/ziangshen/articles/17741402.html" target="_blank" rel="noopener">Linux/VS Code-正在本地下载 VS Code 服务器</a></li>
</ul>
<h2 id="配置免密登录">配置免密登录</h2>
<p>单独将这一小节拿出来介绍，主要是因为手动输入密码实在是太！麻！烦！啦！！！</p>
<p>这对于懒人来说实在是折磨，更别说还存在某些远程服务器需要单独配置VPN进行访问的情况，这时如果VPN效果不太稳定，经常会出现断连需要重新输入密码的情况。好在SSH早就考虑过这个问题了，通过配置<strong>密钥登录</strong>，不仅方便还安全（对我来说主要是方便。。。</p>
<blockquote>
<p>同时这也是vscode官网教程推荐的方式，原文如下：</p>
<p>We recommend using key-based authentication (if you use a username/password, you&rsquo;ll be prompted to enter your credentials more than once by the extension).</p>
</blockquote>
<h3 id="检查宿主机密钥对">检查宿主机密钥对</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 首先确认用户主目录（~）下是否存在密钥对</span>
</span></span><span class="line"><span class="cl">ls -la ~ <span class="p">|</span> grep .ssh
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 如果存在.ssh目录</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 检查是否存在密钥文件</span>
</span></span><span class="line"><span class="cl">ls -la ~/.ssh <span class="p">|</span> grep id_rsa
</span></span><span class="line"><span class="cl"><span class="c1"># 或者</span>
</span></span><span class="line"><span class="cl">ls -la ~/.ssh <span class="p">|</span> grep id_ed25519
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果存在类似的文件则跳过下面的<strong>创建宿主机密钥对</strong>步骤。</p>
<p><a href="/article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp" data-fancybox="gallery" data-src="/article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp" data-caption="宿主机密钥对">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/vscode-python-remote-development/image-20250115152319134_hu_b22cdd01149a9af5.webp 480w, /article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp 710w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="710"
                    height="154"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp"
                    srcset="/article/vscode-python-remote-development/image-20250115152319134_hu_b22cdd01149a9af5.webp 480w, /article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp 710w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="宿主机密钥对"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>这是插播一个知识点，之所以会存在多种（两种）可能的密钥文件，主要是由于加密算法的不同。更具体来说主要是RSA算法与Ed25519算法。</p>
<table>
  <thead>
      <tr>
          <th style="text-align: center">命令</th>
          <th style="text-align: center">ssh-keygen -t rsa -b 4096</th>
          <th style="text-align: center">ssh-keygen -t ed25519</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: center">密钥类型</td>
          <td style="text-align: center">RSA</td>
          <td style="text-align: center">Ed25519</td>
      </tr>
      <tr>
          <td style="text-align: center">性能</td>
          <td style="text-align: center">较慢（但仍足够快）</td>
          <td style="text-align: center">更快</td>
      </tr>
      <tr>
          <td style="text-align: center">安全性</td>
          <td style="text-align: center">高</td>
          <td style="text-align: center">更高</td>
      </tr>
      <tr>
          <td style="text-align: center">兼容性</td>
          <td style="text-align: center">与旧系统兼容性更好</td>
          <td style="text-align: center">某些非常旧的系统可能不支持</td>
      </tr>
  </tbody>
</table>
<p>其实就是安全性、性能与兼容性的取舍，默认使用<code>ssh-keygen -t ed25519</code>即可。</p>
</blockquote>
<h3 id="创建宿主机密钥对">创建宿主机密钥对</h3>
<p>Windows系统打开cmd（命令提示符）或者Windows PowerShell，macOS或者Linux直接打开终端（Terminal）即可。如图是Windows 10系统使用cmd进行操作的示意图。</p>
<p><a href="/article/vscode-python-remote-development/QQ_1736926370168_hu_d49e598161aa8ec5.webp" data-fancybox="gallery" data-src="/article/vscode-python-remote-development/QQ_1736926370168_hu_d49e598161aa8ec5.webp" data-caption="创建密钥对操作示意图">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/vscode-python-remote-development/QQ_1736926370168_hu_145e174e6415f113.webp 480w, /article/vscode-python-remote-development/QQ_1736926370168_hu_ea044de59e5bec0e.webp 720w, /article/vscode-python-remote-development/QQ_1736926370168_hu_f00bebaaa12b01ee.webp 960w, /article/vscode-python-remote-development/QQ_1736926370168_hu_9b11061ae15b4a00.webp 1440w, /article/vscode-python-remote-development/QQ_1736926370168_hu_d49e598161aa8ec5.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1702"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/vscode-python-remote-development/QQ_1736926370168_hu_ea044de59e5bec0e.webp"
                    srcset="/article/vscode-python-remote-development/QQ_1736926370168_hu_145e174e6415f113.webp 480w, /article/vscode-python-remote-development/QQ_1736926370168_hu_ea044de59e5bec0e.webp 720w, /article/vscode-python-remote-development/QQ_1736926370168_hu_f00bebaaa12b01ee.webp 960w, /article/vscode-python-remote-development/QQ_1736926370168_hu_9b11061ae15b4a00.webp 1440w, /article/vscode-python-remote-development/QQ_1736926370168_hu_d49e598161aa8ec5.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="创建密钥对操作示意图"
                    
                />
            </picture>
        </a></p>
<p>存在两种方式，优先选择第一个命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Ed25519</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 优先使用</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 默认创建 id_ed25519.pub 和 id_ed25519</span>
</span></span><span class="line"><span class="cl">ssh-keygen -t ed25519
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># RSA</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 兼容使用</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 默认创建 id_rsa.pub 和 id_rsa</span>
</span></span><span class="line"><span class="cl">ssh-keygen -t rsa -b <span class="m">4096</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>系统会提示输入文件保存路径以及安全密码，都可以直接输入回车（Enter），相当于将密码留空，同时默认的保存路径在宿主机的用户主目录的<code>.ssh</code>目录下。例如，如果我的宿主机用户名都是yuesir，那么在Windows系统中通常是<code>C:/Users/yuesir/.ssh</code>，macOS上通常是<code>/Users/yuesir/.ssh</code>，Linux上通常是<code>/home/yuesir/.ssh</code>。</p>
<p>进入上述目录，应该可以发现存在一个<code>id_ed25519.pub</code>或者<code>id_rsa.pub</code>文件，其中就包含了公共密钥，还有一个对应的没有<code>.pub</code>后缀的文件，那是你的私钥。特别提醒：.pub公钥可以公开，但是没有后缀的私钥不能公开给其他人。</p>
<h3 id="添加公钥到远程服务器">添加公钥到远程服务器</h3>
<p>如果你是购买的云服务器，那么通常可以在购买的页面或者机器信息页面填入或者上传你的公钥。图为官方教程的一个截图。</p>
<p><a href="/article/vscode-python-remote-development/QQ_1736926873754_hu_7d91c8b6a1751505.webp" data-fancybox="gallery" data-src="/article/vscode-python-remote-development/QQ_1736926873754_hu_7d91c8b6a1751505.webp" data-caption="云服务器填入公钥">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/vscode-python-remote-development/QQ_1736926873754_hu_cd950c647632b795.webp 480w, /article/vscode-python-remote-development/QQ_1736926873754_hu_bdd970057d6e805e.webp 720w, /article/vscode-python-remote-development/QQ_1736926873754_hu_d4e8d9a3f1fa710c.webp 960w, /article/vscode-python-remote-development/QQ_1736926873754_hu_d9a2c34723cda6c7.webp 1440w, /article/vscode-python-remote-development/QQ_1736926873754_hu_7d91c8b6a1751505.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1456"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/vscode-python-remote-development/QQ_1736926873754_hu_bdd970057d6e805e.webp"
                    srcset="/article/vscode-python-remote-development/QQ_1736926873754_hu_cd950c647632b795.webp 480w, /article/vscode-python-remote-development/QQ_1736926873754_hu_bdd970057d6e805e.webp 720w, /article/vscode-python-remote-development/QQ_1736926873754_hu_d4e8d9a3f1fa710c.webp 960w, /article/vscode-python-remote-development/QQ_1736926873754_hu_d9a2c34723cda6c7.webp 1440w, /article/vscode-python-remote-development/QQ_1736926873754_hu_7d91c8b6a1751505.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="云服务器填入公钥"
                    
                />
            </picture>
        </a></p>
<p>这是一种比较直观的配置方式，但有时候并不适用。我们的远程服务器可能就是一个IP加上用户名和密码，这时候可以使用命令行的方式或者手动编辑。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 方法一：宿主机命令行</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 宿主机上运行</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 公钥文件改为自己具体的路径和名称</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 后面接的 username@host:port 与前文连接远程服务器的命令保持一致</span>
</span></span><span class="line"><span class="cl">ssh-copy-id -i ~/.ssh/id_ed25519.pub 远程服务器的用户名@远程服务器的host:远程服务器的端口
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 方法二：手动编辑</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 首先在宿主机上操作 复制公钥文件内容</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 宿主机是Linux系统可以通过cat vim等命令 Windows或者macOS系统可以直接在文件管理中打开公钥文件直接进行复制</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 接着在远程服务器上运行下面的命令 这里以vim编辑器为例</span>
</span></span><span class="line"><span class="cl">vim ~/.ssh/authorized_keys
</span></span><span class="line"><span class="cl"><span class="c1"># 点击 i 进入编辑模式</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 如果文件存在内容 移动方向键将光标移动到内容末尾然后回车换行即可</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 如果文件不存在vim会自动创建 此时还是点击 i 进入编辑模式</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 将复制的公钥文件内容直接粘贴到这个文件中即可</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 点击 Esc 退出编辑模式</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 输入以下命令即可保存文件并退出vim编辑器</span>
</span></span><span class="line"><span class="cl">:wq
</span></span><span class="line"><span class="cl"><span class="c1"># 或者</span>
</span></span><span class="line"><span class="cl">ZZ
</span></span></code></pre></td></tr></table>
</div>
</div><p>此时就可以关闭vscode并且尝试重新连接远程服务器，如果不需要手动输入密码即为成功。接下来的内容针对于特定编程语言与notebook工具，请选择性阅读。</p>
<h2 id="python">Python</h2>
<p>使用vscode在远程服务器进行开发，同样需要在远程服务器上安装对应的插件。在这一点的操作上与本地几乎无异，只是需要注意安装到远程服务器上而不是宿主机。vscode会主动提醒你安装必须的插件，这里仅稍作记录。</p>
<p><a href="/article/vscode-python-remote-development/QQ_1736928419969_hu_c6694abb8ea42579.webp" data-fancybox="gallery" data-src="/article/vscode-python-remote-development/QQ_1736928419969_hu_c6694abb8ea42579.webp" data-caption="远程服务器安装插件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/vscode-python-remote-development/QQ_1736928419969_hu_4004eff5606954e2.webp 480w, /article/vscode-python-remote-development/QQ_1736928419969_hu_3c2a4773c10993e9.webp 720w, /article/vscode-python-remote-development/QQ_1736928419969_hu_eb600fa3c7a756eb.webp 960w, /article/vscode-python-remote-development/QQ_1736928419969_hu_e835b2af4343c874.webp 1440w, /article/vscode-python-remote-development/QQ_1736928419969_hu_c6694abb8ea42579.webp 2392w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2392"
                    height="1700"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/vscode-python-remote-development/QQ_1736928419969_hu_3c2a4773c10993e9.webp"
                    srcset="/article/vscode-python-remote-development/QQ_1736928419969_hu_4004eff5606954e2.webp 480w, /article/vscode-python-remote-development/QQ_1736928419969_hu_3c2a4773c10993e9.webp 720w, /article/vscode-python-remote-development/QQ_1736928419969_hu_eb600fa3c7a756eb.webp 960w, /article/vscode-python-remote-development/QQ_1736928419969_hu_e835b2af4343c874.webp 1440w, /article/vscode-python-remote-development/QQ_1736928419969_hu_c6694abb8ea42579.webp 2392w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="远程服务器安装插件"
                    
                />
            </picture>
        </a></p>
<p>当然还是推荐搭配Conda进行环境管理，具体的介绍可以查看下面文章。</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/article/conda-r-jupyter.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Conda安装R内核的Notebook
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2022-10-10
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #r
                #jupyter
                #droplet
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                由于博主多次在Linux远程服务器上使用conda配置r内核的jupyter notebook，但每次时间一久就会忘记某些步骤（最主要是一样的坑每次都会踩出不一样的问题）。在综合网上相关教程以及自己的亲身经验后，总结出一份安装指北，供大家以及将来的我参考。
            </div>
        </div>
    </a>
    
    
</div>

<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/article/conda-env-transfer.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Conda环境备份与迁移
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2024-06-29
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #conda pack
                #droplet
                #deep learning
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                最近，我遇到了一个需要迁移 Conda 环境的场景。通常来说，深度学习项目的环境搭建是相当复杂的，因为依赖包之间的版本关系非常紧密，而且硬件驱动的版本也常常有限制。如果能够直接将已经配置好的环境从一台服务器迁移到另一台服务器，将大大节省时间和精力。
            </div>
        </div>
    </a>
    
    
</div>

<p>关于notebook与R或者Python的联动，请查阅下一章节Notebook。</p>
<h2 id="notebook">Notebook</h2>
<p>关于notebook配置的文章本博客写了比较多，整理如下。需要说明的是，一是下面文章撰写的时间比较早了，那时候还是notebook的6版本，现在都已经进入7大版本了。</p>
<p>对于没有了解过notebook的童鞋，可以查阅一下<a href="https://jupyter.org/install" target="_blank" rel="noopener">安装教程</a>以及<a href="https://jupyter-notebook.readthedocs.io/en/latest/" target="_blank" rel="noopener">官方文档</a>。</p>
<p>如果需要一个比较详细的操作教程，可以在评论区留言（<del>尽量不鸽</del></p>
<h3 id="r与notebook">R与Notebook</h3>
<p>R语言并不是只能在<a href="https://posit.co/download/rstudio-desktop/" target="_blank" rel="noopener">RStudio</a>或者<a href="https://posit.co/products/open-source/rstudio-server/" target="_blank" rel="noopener">RStudio Server</a>中使用，配合Notebook，我觉得可视化更为方便。</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/article/conda-r-jupyter.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Conda安装R内核的Notebook
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2022-10-10
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #r
                #jupyter
                #droplet
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                由于博主多次在Linux远程服务器上使用conda配置r内核的jupyter notebook，但每次时间一久就会忘记某些步骤（最主要是一样的坑每次都会踩出不一样的问题）。在综合网上相关教程以及自己的亲身经验后，总结出一份安装指北，供大家以及将来的我参考。
            </div>
        </div>
    </a>
    
    
</div>

<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/article/brew-r-jupyter.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Brew安装R内核的Notebook
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2023-01-16
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #brew
                #r
                #jupyter
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                我在另一篇文章介绍了在Linux远程服务器上使用conda配置r内核的jupyter notebook，但我发现conda对于各种依赖冲突处理不好，经常导致安装不成功。在macOS系统下本机使用brew进行安装更加简单快捷，总结出来步骤供大家以及将来的我参考。
            </div>
        </div>
    </a>
    
    
</div>

<h3 id="python与notebook">Python与Notebook</h3>
<p>这里还记录了一些常见的问题，但是现在使用vscode来操作notebook后，方便了很多，基本上已经不用看了。</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/article/conda-r-jupyter.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Conda安装R内核的Notebook
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2022-10-10
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #r
                #jupyter
                #droplet
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                由于博主多次在Linux远程服务器上使用conda配置r内核的jupyter notebook，但每次时间一久就会忘记某些步骤（最主要是一样的坑每次都会踩出不一样的问题）。在综合网上相关教程以及自己的亲身经验后，总结出一份安装指北，供大家以及将来的我参考。
            </div>
        </div>
    </a>
    
    
</div>

<h2 id="感谢">感谢</h2>
<p><a href="https://code.visualstudio.com/docs/remote/remote-overview" target="_blank" rel="noopener">VS Code Remote Development</a></p>
<p><a href="https://code.visualstudio.com/docs/remote/ssh-tutorial" target="_blank" rel="noopener">Remote development over SSH</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Conda环境备份与迁移</title>
      <link>https://vccv.cc/article/conda-env-transfer.html</link>
      <pubDate>Sat, 29 Jun 2024 12:28:14 +0800</pubDate>
      <guid>https://vccv.cc/article/conda-env-transfer.html</guid>
      <description>最近，我遇到了一个需要迁移 Conda 环境的场景。通常来说，深度学习项目的环境搭建是相当复杂的，因为依赖包之间的版本关系非常紧密，而且硬件驱动的版本也常常有限制。如果能够直接将已经配置好的环境从一台服务器迁移到另一台服务器，将大大节省时间和精力。</description>
      <content:encoded><![CDATA[<h2 id="背景">背景</h2>
<p>在深度学习的项目中，环境配置是一个非常重要且复杂的步骤。一个稳定的深度学习环境通常包含多个相互依赖的包，如 <code>torch</code>、<code>transformers</code> 以及 <code>cuda</code> 等。这些依赖之间的关系非常紧密，不同版本之间可能存在兼容性问题，导致环境在不同的服务器上难以复现。</p>
<p>最近，我在一台服务器上配置好了一个稳定的深度学习 Conda 环境，包含了所有需要的依赖包。为了将这个环境迁移到另一台服务器上，我决定使用 <code>conda-pack</code> 工具。<code>conda-pack</code> 是一个非常方便的工具，它可以将 Conda 环境打包成一个独立的文件，方便在其他Linux服务器上达到开箱即用的效果。</p>
<h2 id="导出">导出</h2>
<p>要将原始环境从一台服务器迁移到另一台服务器，首先需要在原始环境服务器上导出所需的环境。</p>
<ol>
<li>
<p><strong>查看所有环境</strong></p>
<p>使用 <code>conda env list</code> 查看服务器上所有的 Conda 环境。确保待迁移的环境不是默认的 <code>base</code> 环境。如果需要迁移的是 <code>base</code> 环境，可以使用 <code>conda clone</code> 命令复制成其他名字。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda env list
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>激活待迁移的环境</strong></p>
<p>假设待迁移的环境名为 <code>torch</code>，则可以使用以下命令激活该环境：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda activate torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>安装 <code>conda-pack</code></strong></p>
<p>在激活的环境中，使用 <code>conda</code> 命令安装 <code>conda-pack</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda install conda-pack -c conda-forge
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>打包原环境</strong></p>
<p>使用 <code>conda pack -n &lt;环境名&gt;</code> 来打包环境，这里的 <code>&lt;环境名&gt;</code> 替换为你的环境名，例如 <code>torch</code>。打包速度还是挺快的，打包后会生成一个 <code>环境名.tar.gz</code> 文件。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda pack -n torch
</span></span></code></pre></td></tr></table>
</div>
</div><p>完成后，将会在当前目录下生成一个 <code>torch.tar.gz</code> 文件。</p>
</li>
</ol>
<p>打包的速度与环境的大小成正相关，例如我的环境就比较大，打包的时间也就对应的较长，好在有进度条可以查看具体进度。下图可以看到我的torch环境占用了近20GB的空间。</p>
<p><a href="/article/conda-env-transfer/image-20240629132237812_hu_d15b4707209a1ab9.webp" data-fancybox="gallery" data-src="/article/conda-env-transfer/image-20240629132237812_hu_d15b4707209a1ab9.webp" data-caption="conda环境占用一览">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-env-transfer/image-20240629132237812_hu_38d0df800822b6df.webp 480w, /article/conda-env-transfer/image-20240629132237812_hu_a0bf6e5b8fed4b65.webp 720w, /article/conda-env-transfer/image-20240629132237812_hu_74d4f7f55ae7def5.webp 960w, /article/conda-env-transfer/image-20240629132237812_hu_d15b4707209a1ab9.webp 1038w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1038"
                    height="344"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-env-transfer/image-20240629132237812_hu_a0bf6e5b8fed4b65.webp"
                    srcset="/article/conda-env-transfer/image-20240629132237812_hu_38d0df800822b6df.webp 480w, /article/conda-env-transfer/image-20240629132237812_hu_a0bf6e5b8fed4b65.webp 720w, /article/conda-env-transfer/image-20240629132237812_hu_74d4f7f55ae7def5.webp 960w, /article/conda-env-transfer/image-20240629132237812_hu_d15b4707209a1ab9.webp 1038w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="conda环境占用一览"
                    
                />
            </picture>
        </a></p>
<p>最终我的<code>torch</code>环境导出的 <code>torch.tar.gz</code> 文件就达到了近10GB，压缩效果还是不错的，就是具体运行了多久我也忘记了。</p>
<p><a href="/article/conda-env-transfer/image-20240629131923704_hu_c110c65733fd8f66.webp" data-fancybox="gallery" data-src="/article/conda-env-transfer/image-20240629131923704_hu_c110c65733fd8f66.webp" data-caption="torch环境导出文件大小">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-env-transfer/image-20240629131923704_hu_4da93e99537b81b8.webp 480w, /article/conda-env-transfer/image-20240629131923704_hu_67f6d510d2ac9f57.webp 720w, /article/conda-env-transfer/image-20240629131923704_hu_c110c65733fd8f66.webp 894w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="894"
                    height="156"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-env-transfer/image-20240629131923704_hu_67f6d510d2ac9f57.webp"
                    srcset="/article/conda-env-transfer/image-20240629131923704_hu_4da93e99537b81b8.webp 480w, /article/conda-env-transfer/image-20240629131923704_hu_67f6d510d2ac9f57.webp 720w, /article/conda-env-transfer/image-20240629131923704_hu_c110c65733fd8f66.webp 894w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="torch环境导出文件大小"
                    
                />
            </picture>
        </a></p>
<h2 id="导入">导入</h2>
<p>在成功打包并下载环境文件后，我们需要将其上传并导入到目标服务器。</p>
<h3 id="上传文件到目标服务器">上传文件到目标服务器</h3>
<p>有几种方法可以将打包好的环境文件上传到目标服务器：</p>
<ol>
<li>
<p><strong>下载到本地再上传</strong></p>
<p>这种方法可以保留一份副本。首先将 <code>torch.tar.gz</code> 文件下载到本地电脑，然后再上传到目标服务器。具体操作以你使用的SSH软件为准。</p>
</li>
<li>
<p><strong>使用 <code>rsync</code> 命令</strong></p>
<p><code>rsync</code> 是一个强大的文件同步工具，可以直接将文件从一台服务器传输到另一台服务器。使用以下命令将文件传输到目标服务器：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rsync -avz torch.tar.gz user@target_server:/path/to/destination
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ol>
<h3 id="导入环境">导入环境</h3>
<ol>
<li>
<p><strong>确保目标服务器不存在同名环境</strong></p>
<p>在目标服务器上，使用 <code>conda env list</code> 查看当前所有的环境。如果存在同名环境，需要先删除它。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda env list
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果存在同名环境，可以使用以下命令删除它：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda env remove -p &lt;环境路径&gt; 
</span></span><span class="line"><span class="cl"><span class="c1"># 或者</span>
</span></span><span class="line"><span class="cl">conda env remove -n &lt;环境名&gt;
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>还原环境</strong></p>
<p>首先，使用 <code>conda env list</code> 列出所有虚拟环境的路径。假设 <code>miniconda3</code> 的环境变量路径为 <code>/mnt/nfs/yuesir/miniconda3/envs</code>。</p>
<p>在该路径下新建一个“虚拟环境名”的文件夹，例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir /mnt/nfs/yuesir/miniconda3/envs/torch
</span></span></code></pre></td></tr></table>
</div>
</div><p>赋予该文件夹所有权限：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">chmod <span class="m">777</span> /mnt/nfs/yuesir/miniconda3/envs/torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>解压环境包</strong></p>
<p>将刚刚上传的压缩包解压到上述目录下，使用如下命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tar -xzvf torch.tar.gz -C /mnt/nfs/yuesir/miniconda3/envs/torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>激活新环境</strong></p>
<p>解压完成后，尝试激活新的环境并验证环境是否成功迁移：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda activate torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ol>
<h2 id="确认">确认</h2>
<p>在完成环境的迁移和导入后，需要进行一些检查以确保环境正确配置。</p>
<ol>
<li>
<p><strong>查看已添加的环境</strong></p>
<p>使用 <code>conda env list</code> 命令，可以查看到刚刚添加进去的环境：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda env list
</span></span></code></pre></td></tr></table>
</div>
</div><p>应该能够在列表中看到新迁移的环境名。</p>
</li>
<li>
<p><strong>激活新环境</strong></p>
<p>使用 <code>conda activate &lt;虚拟环境名&gt;</code> 命令激活该环境。例如，如果环境名是 <code>torch</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda activate torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>检查已安装的库</strong></p>
<p>使用 <code>conda list</code> 命令查看环境中已安装的库，以确认迁移是否成功：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda list
</span></span></code></pre></td></tr></table>
</div>
</div><p>这个命令会列出该环境中所有已安装的包及其版本，确保所有的依赖库都正确安装并在合适的版本。</p>
</li>
</ol>
<h2 id="额外">额外</h2>
<p>如果有安装深度学习相关依赖，例如<code>Pytorch</code>等对系统驱动程序版本有要求的依赖包，注意查看两台服务器之间的cuda驱动版本是否匹配。</p>
<p>因为cuda驱动是向下兼容的，如果不匹配，要么就只能升级目标服务器的cuda驱动（需要root权限），要么就尝试降级pytorch的版本（极其容易出现问题，因为依赖关系复杂）。这种情况下还是建议重新从头开始安装吧。</p>
<p>具体如何选择cuda与pytorch间的版本关系，可以参照我以前的文章。</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/article/cuda-conda-nlp.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            非Root用户安装新版本Cuda以及配置NLP环境
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2024-03-10
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #cuda
                #transformers
                #deep learning
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                非root用户如何在无法修改已安装cuda驱动版本的情况下安装较新版本的transformers套件。
            </div>
        </div>
    </a>
    
    
</div>

<h2 id="感谢">感谢</h2>
<p><a href="https://bbs.huaweicloud.com/blogs/405885" target="_blank" rel="noopener">使用conda pack进行环境迁移</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Hugo图片优化：Fancybox、Webp和水印</title>
      <link>https://vccv.cc/article/hugo-img-watermark.html</link>
      <pubDate>Mon, 08 Apr 2024 11:21:44 +0800</pubDate>
      <guid>https://vccv.cc/article/hugo-img-watermark.html</guid>
      <description>最近将博客从Hexo换到Hugo后，发现了Hugo强大的自定义能力，其中就包括了图片自定义能力。一番摸索后，成功将原图片转换为Webp格式、加上了fancybox画廊和博客水印。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>我以前一直使用Hexo框架。但是随着文章数量的不断增加，自定义项目也是越来越多，加上NPM插件也是冲突不断，已经不敢随意安装新的插件，维护难度大大上升。前Hexo博客项目文件已然是“屎山”一片。</p>
<p>俗话说破而后立，趁着这段时间比较空闲，我直接切换到了Hugo框架。Hugo给我的第一印象也是最深印象便是它的速度非常的快，相比于Hexo快了几倍不止，当然也发现了一些不适应的地方：原博客的webp图片压缩和水印功能都是插件自动生成的，本篇就是利用hugo的高度自定义和丰富的图像处理api还原博客的图片结构。</p>
<h2 id="hugo图片自定义原理">Hugo图片自定义原理</h2>
<p>Hugo有一个<strong>Render Hooks</strong>功能，可以替换部分组件生成样式，其中就包含了images图片资源。下面是官方介绍，有兴趣的可以去仔细了解。</p>
<blockquote>
<p>When rendering Markdown to HTML, render hooks override the conversion. Each render hook is a template, with one template for each supported element type:</p>
<ul>
<li><a href="https://gohugo.io/render-hooks/code-blocks/" target="_blank" rel="noopener">Code blocks</a></li>
<li><a href="https://gohugo.io/render-hooks/headings/" target="_blank" rel="noopener">Headings</a></li>
<li><a href="https://gohugo.io/render-hooks/images/" target="_blank" rel="noopener">Images</a></li>
<li><a href="https://gohugo.io/render-hooks/links/" target="_blank" rel="noopener">Links</a></li>
</ul>
</blockquote>
<p>针对图片而言，我们需要创建或者修改<code>layouts/_default/_markup/render-image.html</code>文件内容，以满足自定义需求。如果你是第一次知道这个概念，请先在你博客根目录下的相应路径创建这个文件，注意不是在主题theme目录下。</p>
<p><a href="/article/hugo-img-watermark/image-20240408115714382_hu_555d39c3798cd2b9.webp" data-fancybox="gallery" data-src="/article/hugo-img-watermark/image-20240408115714382_hu_555d39c3798cd2b9.webp" data-caption="创建图片自定义文件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hugo-img-watermark/image-20240408115714382_hu_5b7f0f2a78357892.webp 480w, /article/hugo-img-watermark/image-20240408115714382_hu_5e267e1ec47a82ab.webp 720w, /article/hugo-img-watermark/image-20240408115714382_hu_555d39c3798cd2b9.webp 956w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="956"
                    height="400"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hugo-img-watermark/image-20240408115714382_hu_5e267e1ec47a82ab.webp"
                    srcset="/article/hugo-img-watermark/image-20240408115714382_hu_5b7f0f2a78357892.webp 480w, /article/hugo-img-watermark/image-20240408115714382_hu_5e267e1ec47a82ab.webp 720w, /article/hugo-img-watermark/image-20240408115714382_hu_555d39c3798cd2b9.webp 956w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="创建图片自定义文件"
                    
                />
            </picture>
        </a></p>
<p>接下来我会针对每一个处理给出参考文章和代码，文章的最后我会给出详细注释的全部代码，每一小节的代码仅供参考，类似于<strong>伪代码</strong>，不能直接使用。</p>
<h2 id="webp压缩">Webp压缩</h2>
<h3 id="效果展示">效果展示</h3>
<p>一个静态博客的博文内存占用中占大头的就是图片了，动辄100kb以上的图片让本就不快的博客雪上加霜（博客托管在免费的Cloudflare上面，国内速度感人）。将常见的png、jpg等图片文件压缩成webp格式可以显著减少占用。</p>
<p>以上图为例，压缩前占用39.35kb，压缩后占用8.87kb。</p>
<p><a href="/article/hugo-img-watermark/image-20240408120854759_hu_e6461a24ef8c74c4.webp" data-fancybox="gallery" data-src="/article/hugo-img-watermark/image-20240408120854759_hu_e6461a24ef8c74c4.webp" data-caption="压缩前后对比">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hugo-img-watermark/image-20240408120854759_hu_a5535acecc8538c0.webp 480w, /article/hugo-img-watermark/image-20240408120854759_hu_b7cc59cc0648158a.webp 720w, /article/hugo-img-watermark/image-20240408120854759_hu_e12b0b33bbc3b624.webp 960w, /article/hugo-img-watermark/image-20240408120854759_hu_27319627b0bcca71.webp 1440w, /article/hugo-img-watermark/image-20240408120854759_hu_e6461a24ef8c74c4.webp 1456w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1456"
                    height="1432"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hugo-img-watermark/image-20240408120854759_hu_b7cc59cc0648158a.webp"
                    srcset="/article/hugo-img-watermark/image-20240408120854759_hu_a5535acecc8538c0.webp 480w, /article/hugo-img-watermark/image-20240408120854759_hu_b7cc59cc0648158a.webp 720w, /article/hugo-img-watermark/image-20240408120854759_hu_e12b0b33bbc3b624.webp 960w, /article/hugo-img-watermark/image-20240408120854759_hu_27319627b0bcca71.webp 1440w, /article/hugo-img-watermark/image-20240408120854759_hu_e6461a24ef8c74c4.webp 1456w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="压缩前后对比"
                    
                />
            </picture>
        </a></p>
<h3 id="原理解析">原理解析</h3>
<p>参考<a href="https://iblog.ren/posts/hugo_img_to_webp/" target="_blank" rel="noopener">Hugo图片自动转webp的方法</a>，主要是利用<code>image.Resize</code>方法，<a href="https://gohugo.io/content-management/image-processing/#target-format" target="_blank" rel="noopener">官方文档</a>表示可以指定具体的长宽以及格式。</p>
<p><a href="/article/hugo-img-watermark/image-20240408121738191_hu_855643dfff590a67.webp" data-fancybox="gallery" data-src="/article/hugo-img-watermark/image-20240408121738191_hu_855643dfff590a67.webp" data-caption="格式转换">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hugo-img-watermark/image-20240408121738191_hu_4c05e3422f76bb3a.webp 480w, /article/hugo-img-watermark/image-20240408121738191_hu_6b5799e0b1e39d50.webp 720w, /article/hugo-img-watermark/image-20240408121738191_hu_289b27129ed6a1c4.webp 960w, /article/hugo-img-watermark/image-20240408121738191_hu_bf37df2fe0b0717f.webp 1440w, /article/hugo-img-watermark/image-20240408121738191_hu_855643dfff590a67.webp 1502w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1502"
                    height="1006"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hugo-img-watermark/image-20240408121738191_hu_6b5799e0b1e39d50.webp"
                    srcset="/article/hugo-img-watermark/image-20240408121738191_hu_4c05e3422f76bb3a.webp 480w, /article/hugo-img-watermark/image-20240408121738191_hu_6b5799e0b1e39d50.webp 720w, /article/hugo-img-watermark/image-20240408121738191_hu_289b27129ed6a1c4.webp 960w, /article/hugo-img-watermark/image-20240408121738191_hu_bf37df2fe0b0717f.webp 1440w, /article/hugo-img-watermark/image-20240408121738191_hu_855643dfff590a67.webp 1502w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="格式转换"
                    
                />
            </picture>
        </a></p>
<p>参考文章加上了识别图片EXIF方向，防止转换格式后图片方向改变。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="err">$</span><span class="nx">rawImage</span><span class="p">.</span><span class="nx">Exif</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp r180&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34; webp r270&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34; webp r90&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="添加水印">添加水印</h2>
<h3 id="方法来源">方法来源</h3>
<p>在中文互联网上基本上没找到我需要的内容，最终在<a href="https://github.com/adityatelange/hugo-PaperMod" target="_blank" rel="noopener">PaperMod</a>主题（也就是本博客使用的主题）作者的blog里找到了一篇三年前的文章：<a href="https://adityatelange.in/blog/hugo-watermarking-images/" target="_blank" rel="noopener">Watermarking images with HUGO</a>。</p>
<p>主要思路是利用<code>image.Filter</code>和<code>image.Overlay</code>方法，将水印图片覆盖到每一张图片上。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="p">{{</span><span class="o">-</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">printf</span><span class="w"> </span><span class="s">&#34;%.0fx jpg&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="o">-</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Overlay</span><span class="w"> </span><span class="err">$</span><span class="nf">logo</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Width</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Height</span><span class="p">)</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>这就要求水印图片结构简单，推荐使用网站logo或者博客网址来制作水印覆盖图。我的水印是通过这个<a href="https://www.logoly.pro/" target="_blank" rel="noopener">工具网站</a>进行制作的。</p>
<h3 id="代码展示">代码展示</h3>
<p>原作者将水印覆盖到图片的右下角，我修改为<strong>居中透明倾斜</strong>放置，既不会过多的影响阅读体验，又能更好的保护自己的图片版权。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nf">Round</span><span class="w"> </span><span class="p">(</span><span class="nx">mul</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="mf">0.80</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nf">cond</span><span class="w"> </span><span class="p">(</span><span class="nx">ge</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="mi">250</span><span class="p">)</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="mf">250.0</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Opacity</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)</span><span class="w">  </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">printf</span><span class="w"> </span><span class="s">&#34;%.0fx png r30&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Overlay</span><span class="w"> </span><span class="err">$</span><span class="nf">logo</span><span class="w"> </span><span class="p">(</span><span class="nf">div</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Width</span><span class="p">)</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">div</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Height</span><span class="p">)</span><span class="w"> </span><span class="mi">2</span><span class="p">))</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>需要计算原图的长宽来确定logo位置，然后使用<code>image.Opacity</code>方法设置透明度，最后居中放置即可。</p>
<h2 id="使用fancybox">使用Fancybox</h2>
<p>我的博客图片通常包含大量的文字信息，如果不能放大查看原图会很影响体验。恰巧<a href="https://fancyapps.com/fancybox/" target="_blank" rel="noopener">fancybox</a>就是解决此类问题的js库。官网介绍如下：</p>
<blockquote>
<p>Fancybox is the ultimate JavaScript lightbox alternative that sets the standard for premium user experience in multimedia display. Supports images, videos, maps, inline content, iframes and any other HTML content.</p>
</blockquote>
<h3 id="参考教程">参考教程</h3>
<p>功能很强大，这里就只展示用于图片画廊gallery功能。这一步恰好可以参考我以前为Hexo Cactus主题编写的教程：</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/article/fancybox-cactus.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Cactus使用上Fancybox图片放大
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2022-02-20
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #cactus
                #beautify
                #fancybox
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                将fancybox安装到hexo主题cactus上的一些经验，供大家参考。fancybox可以解决cactus主题图片不能放大的问题，感谢fancyapps做出的贡献。
            </div>
        </div>
    </a>
    
    
</div>

<h3 id="代码展示-1">代码展示</h3>
<p>特别注意首先需要导入相关的css文件与js文件，然后修改img上层的a标签。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">a</span> <span class="na">data-fancybox</span><span class="o">=</span><span class="s">&#34;gallery&#34;</span> <span class="na">data-src</span><span class="o">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span> <span class="na">data-caption</span><span class="o">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">picture</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">source</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;image/webp&#34;</span> <span class="na">srcset</span><span class="o">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">img</span>
</span></span><span class="line"><span class="cl">            <span class="na">width</span><span class="o">=</span><span class="s">&#34;{{ $rawImage.Width }}px&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">height</span><span class="o">=</span><span class="s">&#34;{{ $rawImage.Height }}px&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">style</span><span class="o">=</span><span class="s">&#34;width: 100%; height: 100%; max-height: 36rem;&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">loading</span><span class="o">=</span><span class="s">&#34;lazy&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">src</span><span class="o">=</span><span class="s">&#34;{{ $rawImage.RelPermalink }}&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">alt</span><span class="o">=</span><span class="s">&#34;{{ .Text }}&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="err">{{</span> <span class="na">with</span> <span class="err">.</span><span class="na">Title</span> <span class="err">}}</span> <span class="na">title</span><span class="o">=</span><span class="s">&#34;{{ . }}&#34;</span> <span class="err">{{</span> <span class="na">end</span> <span class="err">}}</span>
</span></span><span class="line"><span class="cl">        <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">picture</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>添加picture标签是为了适配不能解析webp文件的老设备显示原图，提高代码兼容性。加上width与height参数是为了减少<a href="https://web.dev/articles/cls?hl=zh-cn" target="_blank" rel="noopener">CLS</a>的影响。</p>
<h2 id="总结">总结</h2>
<p>代码不能保证可以百分百直接套用，更好的方法是一步一步学习原理，结合自己的主题特点进行修改。</p>
<h3 id="代码汇总">代码汇总</h3>
<p>下面的代码我会尝试进行详细的注释，使用时删除注释即可。如果还有其他疑问，可以评论区留言。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="p">{{</span><span class="cm">/* 获取当前页面匹配.Destination的资源图像 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">.</span><span class="nx">Page</span><span class="p">.</span><span class="nx">Resources</span><span class="p">.</span><span class="nx">GetMatch</span><span class="w"> </span><span class="p">.</span><span class="nx">Destination</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="cm">/* 从资源中获取logo图像，透明背景图片效果最好 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="cm">/* 该图像需要放置在根目录的assets/images目录下 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">(</span><span class="nx">resources</span><span class="p">.</span><span class="nx">Get</span><span class="w"> </span><span class="s">&#34;images/logo.png&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="cm">/* 检查图像的媒体类型是否不是gif或svg */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nf">not</span><span class="w"> </span><span class="p">(</span><span class="nf">in</span><span class="w"> </span><span class="p">(</span><span class="nx">slice</span><span class="w"> </span><span class="s">&#34;gif&#34;</span><span class="w"> </span><span class="s">&#34;svg&#34;</span><span class="p">)</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">MediaType</span><span class="p">.</span><span class="nx">SubType</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* 保留原始图像的引用 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">rawImage</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* 计算图像高度的80%，并确保最小值为250 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nf">Round</span><span class="w"> </span><span class="p">(</span><span class="nx">mul</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="mf">0.80</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nf">cond</span><span class="w"> </span><span class="p">(</span><span class="nx">ge</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="mi">250</span><span class="p">)</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="mf">250.0</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* 调整logo的透明度为50% */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Opacity</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)</span><span class="w">  </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* 调整logo的大小，高度为计算出的$size，保持纵横比，圆角半径为30 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">printf</span><span class="w"> </span><span class="s">&#34;%.0fx png r30&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* 如果原始图像有EXIF信息 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="err">$</span><span class="nx">rawImage</span><span class="p">.</span><span class="nx">Exif</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="cm">/* 根据图像的方向调整图像的大小和旋转 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp r180&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34; webp r270&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34; webp r90&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="cm">/* 如果没有EXIF信息，则只调整大小，不旋转 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* 在图像上添加logo水印，位置在图像的中心 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Overlay</span><span class="w"> </span><span class="err">$</span><span class="nf">logo</span><span class="w"> </span><span class="p">(</span><span class="nf">div</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Width</span><span class="p">)</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">div</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Height</span><span class="p">)</span><span class="w"> </span><span class="mi">2</span><span class="p">))</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* 创建符合fancybox要求的data属性的链接，展示处理后的图像 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="nx">a</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">fancybox</span><span class="p">=</span><span class="s">&#34;gallery&#34;</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">src</span><span class="p">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">caption</span><span class="p">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">&lt;</span><span class="nx">picture</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">&lt;</span><span class="nx">source</span><span class="w"> </span><span class="kd">type</span><span class="p">=</span><span class="s">&#34;image/webp&#34;</span><span class="w"> </span><span class="nx">srcset</span><span class="p">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">&lt;</span><span class="nx">img</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">width</span><span class="p">=</span><span class="s">&#34;{{ $rawImage.Width }}px&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">height</span><span class="p">=</span><span class="s">&#34;{{ $rawImage.Height }}px&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">style</span><span class="p">=</span><span class="s">&#34;width: 100%; height: 100%; max-height: 36rem;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">loading</span><span class="p">=</span><span class="s">&#34;lazy&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">src</span><span class="p">=</span><span class="s">&#34;{{ $rawImage.RelPermalink }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">alt</span><span class="p">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">{{</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="p">.</span><span class="nx">Title</span><span class="w"> </span><span class="p">}}</span><span class="w"> </span><span class="nx">title</span><span class="p">=</span><span class="s">&#34;{{ . }}&#34;</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="o">/</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">&lt;</span><span class="o">/</span><span class="nx">picture</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="o">/</span><span class="nx">a</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* 对于gif或svg图像，不进行webp压缩处理 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="nx">a</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">fancybox</span><span class="p">=</span><span class="s">&#34;gallery&#34;</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">src</span><span class="p">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">caption</span><span class="p">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">&lt;</span><span class="nx">img</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">width</span><span class="p">=</span><span class="s">&#34;{{ $image.Width }}px&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">height</span><span class="p">=</span><span class="s">&#34;{{ $image.Height }}px&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">style</span><span class="p">=</span><span class="s">&#34;width: 100%; height: 100%; max-height: 36rem;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">loading</span><span class="p">=</span><span class="s">&#34;lazy&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">src</span><span class="p">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">alt</span><span class="p">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="p">.</span><span class="nx">Title</span><span class="w"> </span><span class="p">}}</span><span class="w"> </span><span class="nx">title</span><span class="p">=</span><span class="s">&#34;{{ . }}&#34;</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="o">/</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="o">/</span><span class="nx">a</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="致谢">致谢</h2>
<p><a href="https://gohugo.io/render-hooks/images/" target="_blank" rel="noopener">Hugo: Image render hooks</a></p>
<p><a href="https://iblog.ren/posts/hugo_img_to_webp/" target="_blank" rel="noopener">Hugo图片自动转webp的方法</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>读Hugging Face文档有感</title>
      <link>https://vccv.cc/article/llm-transformers.html</link>
      <pubDate>Mon, 11 Mar 2024 19:17:56 +0000</pubDate>
      <guid>https://vccv.cc/article/llm-transformers.html</guid>
      <description>简单记录一下hugging face官方文档中出现的结论和方法。顺便记载一些个人思考与困惑之处，方便以后回溯解决。欢迎评论区大佬留言交流。</description>
      <content:encoded><![CDATA[<h2 id="单gpu优化">单GPU优化</h2>
<p>Resource: <a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one" target="_blank" rel="noopener">Hugging Face Doc</a></p>
<table>
  <thead>
      <tr>
          <th>Method/tool</th>
          <th>Improves training speed</th>
          <th>Optimizes memory utilization</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#batch-size-choice" target="_blank" rel="noopener">Batch size choice</a></td>
          <td>Yes</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#gradient-accumulation" target="_blank" rel="noopener">Gradient accumulation</a></td>
          <td>No</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#gradient-checkpointing" target="_blank" rel="noopener">Gradient checkpointing</a></td>
          <td>No</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#mixed-precision-training" target="_blank" rel="noopener">Mixed precision training</a></td>
          <td>Yes</td>
          <td>(<strong>No</strong>)</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#optimizer-choice" target="_blank" rel="noopener">Optimizer choice</a></td>
          <td>Yes</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#data-preloading" target="_blank" rel="noopener">Data preloading</a></td>
          <td>Yes</td>
          <td>No</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#deepspeed-zero" target="_blank" rel="noopener">DeepSpeed Zero</a></td>
          <td>No</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#using-torchcompile" target="_blank" rel="noopener">torch.compile</a></td>
          <td>Yes</td>
          <td>No</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#using--peft" target="_blank" rel="noopener">Parameter-Efficient Fine Tuning (PEFT)</a></td>
          <td>No</td>
          <td>Yes</td>
      </tr>
  </tbody>
</table>
<h3 id="fp16">FP16</h3>
<blockquote>
<p>If your model doesn’t work well with mixed precision, for example if it wasn’t pretrained in mixed precision, you may encounter overflow or underflow issues which can cause NaN loss. For these cases, you should use full fp32 precision by explicitly disabling the default fp16 mode.</p>
</blockquote>
<h3 id="zero">ZERO</h3>
<p>stage 1 优化器状态</p>
<p>stage 2 优化器状态 + 梯度</p>
<p>stage 3 优化器状态 + 梯度 + 模型参数（权重）</p>
<p>推理阶段 zero-1 zero-2 没什么作用，只能设置zero-3（推理阶段不需要优化器，也不会产生梯度）。另外如果 Transformers&lt;4.28 ，生成时需要设置<code>synced_gpus=True</code>。</p>
<blockquote>
<p>Using multiple GPUs with ZeRO-3 for generation requires synchronizing the GPUs by setting <code>synced_gpus=True</code> in the <a href="https://huggingface.co/docs/transformers/main/en/model_doc/phi#transformers.PhiForCausalLM.generate" target="_blank" rel="noopener">generate()</a> method. Otherwise, if one GPU is finished generating before another one, the whole system hangs because the remaining GPUs haven’t received the weight shard from the GPU that finished first.</p>
<p>For Transformers&gt;=4.28, if <code>synced_gpus</code> is automatically set to <code>True</code> if multiple GPUs are detected during generation.</p>
</blockquote>
<p>如果配置了offload 则需要选择对CPU和GPU同时适配的优化器，常用的Adam不能使用。</p>
<blockquote>
<p>DeepSpeed and Transformers optimizer and scheduler can be mixed and matched as long as you don’t enable <code>offload_optimizer</code>. When <code>offload_optimizer</code> is enabled, you could use a <u>non-DeepSpeed optimizer</u> (except for LAMB) as long as it has <u>both a CPU and GPU implementation</u>.</p>
</blockquote>
<h2 id="多gpu优化">多GPU优化</h2>
<p>Resource: <a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_many" target="_blank" rel="noopener">Hugging Face Doc</a></p>
<p>主要就是几个纬度的并行：Data + Pipeline + Tensor。</p>
<h2 id="混淆点">混淆点</h2>
<h3 id="fp16-1">FP16</h3>
<p>只能加速训练过程，<strong>不一定</strong>能减少显存占用（甚至可能会占用1.5倍）。</p>
<blockquote>
<p>While mixed precision training results in faster computations, it can also lead to more GPU memory being utilized, especially for small batch sizes. <u>This is because the model is now present on the GPU in both 16-bit and 32-bit precision</u> (1.5x the original model on the GPU). From: <a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#mixed-precision-training" target="_blank" rel="noopener">Hugging Face Doc</a></p>
<p><u>Note</u>: when using mixed precision with a small model and a large batch size, there will be some memory savings but with a large model and a small batch size, the memory use will be larger.</p>
</blockquote>
<h4 id="小模型大批量大小">小模型，大批量大小</h4>
<ul>
<li><strong>内存节省</strong>：对于小型模型，模型参数和权重占用的内存相对较少。当采用大批量大小进行训练时，激活和梯度占用的内存成为主要的内存使用部分。在这种情况下，将激活和梯度转换为FP16可以显著减少这部分的内存占用，因为FP16占用的内存是FP32的一半。即使考虑到保留FP32精度的模型权重副本，整体内存使用量仍然会减少，因为激活和梯度的内存节省超过了额外权重副本的内存开销。</li>
<li><strong>效率和节省</strong>：大批量大小意味着每次迭代处理更多的数据，这增加了计算激活和梯度所需的内存量。由于这部分现在使用FP16，所以相比仅使用FP32，总体内存需求降低。</li>
</ul>
<h4 id="大模型小批量大小">大模型，小批量大小</h4>
<ul>
<li><strong>内存使用增加</strong>：对于大型模型，模型参数和权重本身就占用大量内存。在混合精度训练中，即使将激活和梯度存储为FP16，仍需保留一份FP32精度的权重副本以保证更新的准确性。这意味着相对于模型本身大小，额外的内存开销（由于FP32的权重副本）在总内存占用中占比较大。当批量大小较小时，激活和梯度占用的内存相对较少，因此FP16带来的内存节省效果不足以抵消因保持FP32权重副本而增加的额外内存使用。</li>
<li><strong>权重副本的影响</strong>：在这种情况下，由于模型本身大，所以FP32权重副本占用的额外内存成为了一个重要因素。即使激活和梯度使用了FP16，总内存使用量仍可能因为FP32的权重副本而增加。</li>
</ul>
<h3 id="梯度累计">梯度累计</h3>
<p>有效批次 = 梯度累计数 * 实际batch。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">training_args</span> <span class="o">=</span> <span class="n">TrainingArguments</span><span class="p">(</span><span class="n">per_device_train_batch_size</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">gradient_accumulation_steps</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="o">**</span><span class="n">default_args</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>In the above example, your effective batch size becomes 4.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">for</span> <span class="n">epoch</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">):</span>  <span class="c1"># 假设训练2个epoch</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="n">inputs</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">dataloader</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">inputs</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">inputs</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">torch</span><span class="o">.</span><span class="n">float32</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">labels</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">labels</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">torch</span><span class="o">.</span><span class="n">long</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 前向传播</span>
</span></span><span class="line"><span class="cl">        <span class="n">outputs</span> <span class="o">=</span> <span class="n">model</span><span class="p">(</span><span class="n">inputs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">loss</span> <span class="o">=</span> <span class="n">criterion</span><span class="p">(</span><span class="n">outputs</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span> <span class="o">/</span> <span class="n">accumulation_steps</span>  <span class="c1"># 注意这里除以了累计步骤数</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 反向传播</span>
</span></span><span class="line"><span class="cl">        <span class="n">loss</span><span class="o">.</span><span class="n">backward</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 每accumulation_steps次更新一次模型参数</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">accumulation_steps</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">dataloader</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="n">optimizer</span><span class="o">.</span><span class="n">step</span><span class="p">()</span>  <span class="c1"># 更新参数</span>
</span></span><span class="line"><span class="cl">            <span class="n">optimizer</span><span class="o">.</span><span class="n">zero_grad</span><span class="p">()</span>  <span class="c1"># 清除梯度</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>每次都需要BP，但是只有达到累计梯度步数，优化器才更新参数。</p>
<blockquote>
<p>optimizer.step() vs optimizer.zero_grad()</p>
<p>正常训练流程：先zero_grad再step 避免以前的batch计算出的梯度对本次优化器状态造成影响。</p>
<p>梯度累计流程：先step再zero_grad 顾名思义就是要让梯度累计生效 最后再更新参数。</p>
</blockquote>
<p>优先保证达到GPU极限的<code>per_device_train_batch_size</code>设置时再考虑累计。</p>
<blockquote>
<p>While it is advised to max out GPU usage as much as possible, a high number of gradient accumulation steps can result in a more pronounced training slowdown. Consider the following example. Let’s say, the <code>per_device_train_batch_size=4</code> without gradient accumulation hits the GPU’s limit. If you would like to train with batches of size 64, do not set the <code>per_device_train_batch_size</code> to 1 and <code>gradient_accumulation_steps</code> to 64. Instead, keep <code>per_device_train_batch_size=4</code> and set <code>gradient_accumulation_steps=16</code>. This results in the same effective batch size while making better use of the available GPU resources.</p>
</blockquote>
<p>梯度累计是否会造成多余的显存占用，尚不得而知。或者说我认为不会，我认为梯度只是由一个数字变成了多次累计后得出的另外一个数字，数据格式没有改变，占用的字节数也不会改变。实际操作过程中似乎有影响，但我无法找到原因来对其进行合理解释。</p>
<h2 id="模型输入">模型输入</h2>
<p>对数据进行处理，huggingface提供的api主要是各种<code>DataCollator</code>。这其实就是一个数据预处理函数，后面也可以自己编写类似的函数。</p>
<ul>
<li>
<p>token分类</p>
<p>包括常见的NER，input_ids是tokenize后的tokens id，labels是等长的input_ids，但是需要将特殊token标记为-100（交叉熵忽略的标签值）。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">align_labels_with_tokens</span><span class="p">(</span><span class="n">labels</span><span class="p">,</span> <span class="n">word_ids</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">new_labels</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="n">current_word</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">word_id</span> <span class="ow">in</span> <span class="n">word_ids</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">word_id</span> <span class="o">!=</span> <span class="n">current_word</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># Start of a new word!</span>
</span></span><span class="line"><span class="cl">            <span class="n">current_word</span> <span class="o">=</span> <span class="n">word_id</span>
</span></span><span class="line"><span class="cl">            <span class="n">label</span> <span class="o">=</span> <span class="o">-</span><span class="mi">100</span> <span class="k">if</span> <span class="n">word_id</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">labels</span><span class="p">[</span><span class="n">word_id</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="n">new_labels</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">label</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="n">word_id</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># Special token</span>
</span></span><span class="line"><span class="cl">            <span class="n">new_labels</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="o">-</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># Same word as previous token</span>
</span></span><span class="line"><span class="cl">            <span class="n">label</span> <span class="o">=</span> <span class="n">labels</span><span class="p">[</span><span class="n">word_id</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="c1"># If the label is B-XXX we change it to I-XXX</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">label</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">label</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">            <span class="n">new_labels</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">label</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">new_labels</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">###### OUTPUT ######</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">]</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>为了使input_ids与labels长度一致，可以手动处理，也可以使用<code>DataCollatorForTokenClassification</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">transformers</span> <span class="kn">import</span> <span class="n">DataCollatorForTokenClassification</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">data_collator</span> <span class="o">=</span> <span class="n">DataCollatorForTokenClassification</span><span class="p">(</span><span class="n">tokenizer</span><span class="o">=</span><span class="n">tokenizer</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">batch</span> <span class="o">=</span> <span class="n">data_collator</span><span class="p">([</span><span class="n">tokenized_datasets</span><span class="p">[</span><span class="s2">&#34;train&#34;</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">)])</span>
</span></span><span class="line"><span class="cl"><span class="n">batch</span><span class="p">[</span><span class="s2">&#34;labels&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">###### OUTPUT ######</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="c1">###### VS ######</span>
</span></span><span class="line"><span class="cl"><span class="n">tensor</span><span class="p">([[</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span>    <span class="mi">3</span><span class="p">,</span>    <span class="mi">0</span><span class="p">,</span>    <span class="mi">7</span><span class="p">,</span>    <span class="mi">0</span><span class="p">,</span>    <span class="mi">0</span><span class="p">,</span>    <span class="mi">0</span><span class="p">,</span>    <span class="mi">7</span><span class="p">,</span>    <span class="mi">0</span><span class="p">,</span>    <span class="mi">0</span><span class="p">,</span>    <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span><span class="o">-</span><span class="mi">100</span><span class="p">,</span>    <span class="mi">1</span><span class="p">,</span>    <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">,</span> <span class="o">-</span><span class="mi">100</span><span class="p">]])</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>mask</p>
<p>继续预训练mask模型，input_ids需要将原文本进行随机mask然后tokenize（这一步可以借助<code>DataCollatorForLanguageModeling</code>），然后labels是除了[MASK]代表的原文本id之外全是-100。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># result[&#34;labels&#34;] = result[&#34;input_ids&#34;].copy()</span>
</span></span><span class="line"><span class="cl"><span class="n">input_ids</span> <span class="o">=</span> <span class="n">feature</span><span class="p">[</span><span class="s2">&#34;input_ids&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">labels</span> <span class="o">=</span> <span class="n">feature</span><span class="p">[</span><span class="s2">&#34;labels&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="n">new_labels</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">100</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">labels</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">word_id</span> <span class="ow">in</span> <span class="n">np</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">mask</span><span class="p">)[</span><span class="mi">0</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">    <span class="n">word_id</span> <span class="o">=</span> <span class="n">word_id</span><span class="o">.</span><span class="n">item</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">idx</span> <span class="ow">in</span> <span class="n">mapping</span><span class="p">[</span><span class="n">word_id</span><span class="p">]:</span>
</span></span><span class="line"><span class="cl">        <span class="n">new_labels</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">=</span> <span class="n">labels</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="n">input_ids</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">=</span> <span class="n">tokenizer</span><span class="o">.</span><span class="n">mask_token_id</span>
</span></span><span class="line"><span class="cl"><span class="n">feature</span><span class="p">[</span><span class="s2">&#34;labels&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_labels</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>casual</p>
<p>Seq2Seq类型任务，包括Chat、Translate等。使用<code>DataCollatorForSeq2Seq</code>。</p>
</li>
<li>
<p>from scratch</p>
<p>从头预训练或者继续预训练，输入也用作标签（只是移动了一个元素），并且这个数据应该在训练期间实时生成，所以我们不需要复制 <code>input_ids</code>，而是使用<code>DataCollatorForLanguageModeling</code>。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">transformers</span> <span class="kn">import</span> <span class="n">DataCollatorForLanguageModeling</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 默认是mlm</span>
</span></span><span class="line"><span class="cl"><span class="n">data_collator</span> <span class="o">=</span> <span class="n">DataCollatorForLanguageModeling</span><span class="p">(</span><span class="n">tokenizer</span><span class="p">,</span> <span class="n">mlm</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>other</p>
</li>
</ul>
<h2 id="参考">参考</h2>
<p><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one" target="_blank" rel="noopener">Hugging Face Doc</a></p>
<p><a href="https://huggingface.co/learn/nlp-course/zh-CN" target="_blank" rel="noopener">Hugging Face NLP Course</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>非Root用户安装新版本Cuda以及配置NLP环境</title>
      <link>https://vccv.cc/article/cuda-conda-nlp.html</link>
      <pubDate>Sun, 10 Mar 2024 16:13:14 +0000</pubDate>
      <guid>https://vccv.cc/article/cuda-conda-nlp.html</guid>
      <description>非root用户如何在无法修改已安装cuda驱动版本的情况下安装较新版本的transformers套件。</description>
      <content:encoded><![CDATA[<p>非ROOT用户配置远程CUDA服务器的深度学习环境，下面以Pytorch为例。</p>
<h2 id="cuda驱动">CUDA驱动</h2>
<p>查看服务器已经安装的CUDA版本：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nvcc -V
</span></span></code></pre></td></tr></table>
</div>
</div><p>我这里显示11.4版本，但这并不重要。接下来查看驱动版本，这关系着我们在conda虚拟环境所能够安装的最新CUDA版本。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nvidia-smi
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">### Output</span>
</span></span><span class="line"><span class="cl"><span class="c1">### Driver Version: 535.129.03   CUDA Version: 12.2</span>
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>提示：</p>
<p>这里的 CUDA Version 显示12.2，其实是服务器安装的CUDA驱动支持安装的最新的CUDA版本，也就是说我们接下来可以安装的CUDA版本最高为12.2，本机已经安装的CUDA版本为11.4。</p>
<p>因为我们是非ROOT用户，使用不能改变<u>已安装驱动版本</u>，但是可以通过Conda虚拟环境安装新的CUDA版本。</p>
</blockquote>
<h2 id="conda">Conda</h2>
<p>非root用户配置python相关环境时，我极其推荐使用conda包管理器来实现依赖管理（其实使用R语言的用户也推荐使用）。</p>
<p>我这里安装的是miniconda版本（最小化版本），也可以安装anaconda（完整版）。</p>
<p>博客里以前也写过<a href="https://vccv.cc/article/conda-r-jupyter.html" target="_blank" rel="noopener">相关内容</a>。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 我安装环境时选择的是3.10版本python</span>
</span></span><span class="line"><span class="cl">conda create -n torch <span class="nv">python</span><span class="o">=</span>3.10
</span></span><span class="line"><span class="cl">conda activate torch
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="pytorch">Pytorch</h2>
<p>可以在 <a href="https://pytorch.org/get-started/previous-versions/" target="_blank" rel="noopener">Pytorch History Release</a> 查询Pytorch历史发布版本，结合自己的需求（例如<a href="https://colossalai.org/zh-Hans/docs/get_started/installation/" target="_blank" rel="noopener">Colossal-AI</a>需要PyTorch &gt;= 1.11 并且 PyTorch &lt;= 2.1）。最终我选择的就是pytorch==2.1.0 并且 CUDA==11.8 。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># CUDA 11.8</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 小于驱动最高支持版本 12.2 但是大于已安装CUDA版本 11.4</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 尽量不要跳大版本安装</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 比如我本机安装的是11.4 那我就选择cuda=11.8安装 安装12.1似乎有点问题？</span>
</span></span><span class="line"><span class="cl">conda install <span class="nv">pytorch</span><span class="o">==</span>2.1.0 <span class="nv">torchvision</span><span class="o">==</span>0.16.0 <span class="nv">torchaudio</span><span class="o">==</span>2.1.0 pytorch-cuda<span class="o">=</span>11.8 -c pytorch -c nvidia
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#### 使用pip镜像源</span>
</span></span><span class="line"><span class="cl"><span class="c1">#### 链接最后的cu121按需更改</span>
</span></span><span class="line"><span class="cl">pip3 install torch torchvision torchaudio --index-url https://mirror.sjtu.edu.cn/pytorch-wheels/cu121
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>题外话：</p>
<p>至于为什么pytorch针对有些cuda版本不会重新发布，在这个<a href="https://github.com/pytorch/pytorch/issues/75992" target="_blank" rel="noopener">issue</a>中pytorch的一位开发者解释到pytorch-cuda113能够在cuda114版本使用，简单来说就是没有必要重新发布，114版本直接使用113的就可以了。</p>
<p><a href="/article/cuda-conda-nlp/image-20240310181358683_hu_9eded2ef2122ef6d.webp" data-fancybox="gallery" data-src="/article/cuda-conda-nlp/image-20240310181358683_hu_9eded2ef2122ef6d.webp" data-caption="pytorch-cuda">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/cuda-conda-nlp/image-20240310181358683_hu_3a061dabc4b08a2f.webp 480w, /article/cuda-conda-nlp/image-20240310181358683_hu_f19a41cbd90fdf1c.webp 720w, /article/cuda-conda-nlp/image-20240310181358683_hu_9aab27c2a1b42bac.webp 960w, /article/cuda-conda-nlp/image-20240310181358683_hu_dc2bef92e49c5a29.webp 1440w, /article/cuda-conda-nlp/image-20240310181358683_hu_9eded2ef2122ef6d.webp 2002w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2002"
                    height="442"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/cuda-conda-nlp/image-20240310181358683_hu_f19a41cbd90fdf1c.webp"
                    srcset="/article/cuda-conda-nlp/image-20240310181358683_hu_3a061dabc4b08a2f.webp 480w, /article/cuda-conda-nlp/image-20240310181358683_hu_f19a41cbd90fdf1c.webp 720w, /article/cuda-conda-nlp/image-20240310181358683_hu_9aab27c2a1b42bac.webp 960w, /article/cuda-conda-nlp/image-20240310181358683_hu_dc2bef92e49c5a29.webp 1440w, /article/cuda-conda-nlp/image-20240310181358683_hu_9eded2ef2122ef6d.webp 2002w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="pytorch-cuda"
                    
                />
            </picture>
        </a></p>
</blockquote>
<p>检查CUDA可用性</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 方法一：</span>
</span></span><span class="line"><span class="cl">python -c <span class="s2">&#34;import torch; print(torch.cuda.is_available())&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 方法二：</span>
</span></span><span class="line"><span class="cl"><span class="o">(</span>torch<span class="o">)</span> <span class="o">[</span>username/pwd<span class="o">]</span>$ python
</span></span><span class="line"><span class="cl">Python 3.10.13 <span class="o">(</span>main, Sep <span class="m">11</span> 2023, 13:44:35<span class="o">)</span> <span class="o">[</span>GCC 11.2.0<span class="o">]</span> on linux
</span></span><span class="line"><span class="cl">Type <span class="s2">&#34;help&#34;</span>, <span class="s2">&#34;copyright&#34;</span>, <span class="s2">&#34;credits&#34;</span> or <span class="s2">&#34;license&#34;</span> <span class="k">for</span> more information.
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; import torch
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; torch.cuda.is_available<span class="o">()</span>
</span></span><span class="line"><span class="cl">True
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; exit<span class="o">()</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="cuda">CUDA</h2>
<p>在 <a href="https://anaconda.org/nvidia/cuda" target="_blank" rel="noopener">Nvidia-Cuda</a> 查找已安装的Pytorch对应的CUDA版本，我这里是11.8。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 在nvidia官方channel下载包不会显示进度条 下载速度慢</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 国内推荐使用镜像站 编辑 .condarc 文件 或者执行下面的 conda config --set 命令</span>
</span></span><span class="line"><span class="cl"><span class="c1"># nvidia: https://mirrors.sustech.edu.cn/anaconda-extra/cloud</span>
</span></span><span class="line"><span class="cl">conda config --set custom_channels.nvidia https://mirrors.sustech.edu.cn/anaconda-extra/cloud
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 官方命令：conda install nvidia/label/cuda-11.8.0::cuda</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 上述命令经过测试 可能会导致cuda版本错误匹配 感谢评论区老哥</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">conda install cuda -c nvidia/label/cuda-11.8.0
</span></span></code></pre></td></tr></table>
</div>
</div><p>此时输入 <code>nvcc -V</code> 命令可以发现已安装版本已经是11.8了。</p>
<p><a href="/article/cuda-conda-nlp/image-20240310192306099_hu_6805f613f1d6bb40.webp" data-fancybox="gallery" data-src="/article/cuda-conda-nlp/image-20240310192306099_hu_6805f613f1d6bb40.webp" data-caption="nvcc -V">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/cuda-conda-nlp/image-20240310192306099_hu_ddb2ea133a6f7da9.webp 480w, /article/cuda-conda-nlp/image-20240310192306099_hu_77533de7f074319e.webp 720w, /article/cuda-conda-nlp/image-20240310192306099_hu_6805f613f1d6bb40.webp 916w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="916"
                    height="198"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/cuda-conda-nlp/image-20240310192306099_hu_77533de7f074319e.webp"
                    srcset="/article/cuda-conda-nlp/image-20240310192306099_hu_ddb2ea133a6f7da9.webp 480w, /article/cuda-conda-nlp/image-20240310192306099_hu_77533de7f074319e.webp 720w, /article/cuda-conda-nlp/image-20240310192306099_hu_6805f613f1d6bb40.webp 916w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="nvcc -V"
                    
                />
            </picture>
        </a></p>
<h3 id="使用conda安装的cuda">使用conda安装的cuda</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 可以避免一些程序找不到conda安装的CUDA（11.8） 而去使用系统自带的CUDA（11.4）</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CUDA_HOME</span><span class="o">=</span><span class="nv">$CONDA_PREFIX</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="额外">额外</h2>
<h3 id="zsh">zsh</h3>
<p>参考<a href="https://vccv.cc/article/omz-terminal.html" target="_blank" rel="noopener">Unix终端安装配置Oh My Zsh</a>教程中非root用户编译安装部分。</p>
<blockquote>
<p>如果在编译过程中遇到报错，可以尝试升级gcc等编译组件再尝试安装。</p>
<p>点击查看进一步安装<a href="https://vccv.cc/article/omz-terminal.html" target="_blank" rel="noopener">Oh My Zsh</a>教程。</p>
</blockquote>
<h3 id="gcc-clang-g-clang">gcc clang g++ clang++</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 服务器自带gcc版本太低 甚至不支持g++ 使用conda安装后直接生效</span>
</span></span><span class="line"><span class="cl">conda install -c conda-forge cxx-compiler cmake clang
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="xformers">xformers</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 官方仓库建议命令</span>
</span></span><span class="line"><span class="cl">conda install xformers -c xformers
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 确认安装之前一定要仔细核对包变更记录</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 存在替换已安装pytorch版本的可能 此时一定不要安装</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 尝试加上 -c nvidia -c pytorch 应该就没问题了</span>
</span></span><span class="line"><span class="cl">conda install xformers -c xformers -c nvidia -c pytorch
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="transformers--datasets--accelerate">transformers &amp; datasets &amp; accelerate</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 使用conda安装可能不会是最新版本 pip最好</span>
</span></span><span class="line"><span class="cl">pip install transformers datasets accelerate -U
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="查看显卡计算能力">查看显卡计算能力</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nvidia-smi --query-gpu<span class="o">=</span>compute_cap --format<span class="o">=</span>csv
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="参考">参考</h2>
<p><a href="https://anaconda.org/nvidia/cuda" target="_blank" rel="noopener">Nvidia-Cuda</a></p>
<p><a href="https://pytorch.org/get-started/previous-versions/" target="_blank" rel="noopener">Pytorch History Release</a></p>
<p><a href="https://github.com/pytorch/pytorch/issues/75992" target="_blank" rel="noopener">Pytorch Github Issue</a></p>
<p><a href="http://dong.sh/posts/researchenvnonroot/" target="_blank" rel="noopener">无Root配置科研环境：zsh插件、conda/python环境等</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>安卓Root抓包星穹铁道抽卡链接</title>
      <link>https://vccv.cc/article/hkrpg-android-httpcanary.html</link>
      <pubDate>Sat, 06 May 2023 17:13:20 +0000</pubDate>
      <guid>https://vccv.cc/article/hkrpg-android-httpcanary.html</guid>
      <description>在编辑本文内容之前，我已经看到有一些介绍如何在安卓抓包获取星穹铁道抽卡链接的文章，需要通过ADB或者电脑辅助进行。本文面向的主要是有一定基础的Root搞机用户，可以直接在本机进行操作。并且本文教程属于通用型安卓抓包教程，抓包对象不止于星穹铁道APP。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>在编辑本文内容之前，看到发现有一些介绍如何在安卓抓包获取星穹铁道抽卡链接的文章（通过ADB或者电脑辅助进行），感谢微信公众号 <em><a href="https://mp.weixin.qq.com/s/HS7TD189krbUJr4VbhWZCw" target="_blank" rel="noopener">星穹铁道工坊</a></em> 分享。</p>
<blockquote>
<p>针对星穹铁道抓包：</p>
<p>目前看来最简单的应该是直接在PC上或者iOS设备上抓包。如果只有安卓设备，使用上述文章中的ADB方法应该也是相对来说最简单的（针对不搞机用户）。</p>
<p>本文分享的方法其实并不简单，甚至可以说是很繁琐，但毕竟搞机，贵在坚持了哈哈。</p>
</blockquote>
<p>本文提供的方法面向的是有一定基础的Root搞机用户，可以直接在本机进行操作。并且教程属于通用型安卓抓包教程，抓包对象不止于星穹铁道APP。</p>
<h2 id="准备">准备</h2>
<blockquote>
<p>前提条件：</p>
<p>安装有<a href="https://github.com/topjohnwu/Magisk" target="_blank" rel="noopener">Magisk</a>（不确定KernelSU是否可行，因为需要安装Magisk模块）</p>
<p>安装有<a href="https://github.com/LSPosed/LSPosed" target="_blank" rel="noopener">LSPosed</a>（不确定Xposed是否可行）</p>
</blockquote>
<p>需要安装以下应用：</p>
<ul>
<li>Http Canary （ver 3.3.6）：抓包软件主体，俗称小黄鸟；</li>
<li>爱玩机工具箱：小黄鸟证书修复；</li>
<li>TrustMeAlready &amp; JustTrustMe：<strong>部分解决</strong>抓包软件使用固定证书不受信任问题；</li>
<li>抓包CA证书补齐模块。</li>
</ul>
<p>我已经打包分享在了蓝奏云，<a href="https://yuesir.lanzoum.com/b03k88ype" target="_blank" rel="noopener">点击下载</a>（密码: <strong>ft5q</strong>）。接下来将对环境配置等步骤逐步进行介绍。</p>
<h2 id="http-canary">Http Canary</h2>
<p>本小节介绍如何在高安卓版本设备上安装Http Canary证书到系统证书目录，可以直接<a href="https://www.coolapk1s.com/feed/40140406" target="_blank" rel="noopener">点击链接</a>查看原文进行操作，感谢酷安用户密西根碎冰蓝的分享，我简要总结一下步骤。</p>
<ul>
<li>
<p>提示：Shamiko选择<strong>黑名单</strong>模式（默认），不要对Http Canary软件有任何隐藏Root的行为，即使你已经给它获取了Root权限；</p>
</li>
<li>
<p>使用Magisk刷入<strong>抓包CA证书补齐_18002.zip</strong>，然后重启手机使其生效；</p>
</li>
<li>
<p>安装Http Canary并打开，如果提示安装证书，点击<strong>跳过</strong>；</p>
<blockquote>
<p>注意我们并没有也并不需要按照软件提示进行证书安装，而是通过上一步刷入抓包证书补全模块进行证书安装。</p>
</blockquote>
</li>
<li>
<p>重新打开Http Cnary，仍然提示证书未安装：</p>
<p>再次停止运行，然后安装爱玩机工具箱（允许获取root，通过Magisk模块模式）并运行修复功能。</p>
<p>路径：应用相关 -&gt; 第三方应用辅助 -&gt; 小黄鸟证书修复。</p>
<p><a href="/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_ff7a9939e7c169d9.webp" data-fancybox="gallery" data-src="/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_ff7a9939e7c169d9.webp" data-caption="证书修复">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_dfd2adf4bb9db0cb.webp 480w, /article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_bb061566a262e711.webp 720w, /article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_7bd191d2c9b7bb1.webp 960w, /article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_ff7a9939e7c169d9.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="880"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_bb061566a262e711.webp"
                    srcset="/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_dfd2adf4bb9db0cb.webp 480w, /article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_bb061566a262e711.webp 720w, /article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_7bd191d2c9b7bb1.webp 960w, /article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_ff7a9939e7c169d9.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="证书修复"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>打开Http Canary左上角菜单，点击设置，点击 <strong>HttpCanary根证书</strong> 选项，此时 <strong>安装HttpCanary根证书</strong> 选项下面小字应该提示<strong>已安装</strong>，如果提示未安装请卸载软件重装或者重复上一步。</p>
<p><a href="/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_af5e12dea7c34ce5.webp" data-fancybox="gallery" data-src="/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_af5e12dea7c34ce5.webp" data-caption="提示证书已安装">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_5b19a10905da0fd4.webp 480w, /article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_cbcd39549101103a.webp 720w, /article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_d47522c3b8f471c8.webp 960w, /article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_af5e12dea7c34ce5.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="432"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_cbcd39549101103a.webp"
                    srcset="/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_5b19a10905da0fd4.webp 480w, /article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_cbcd39549101103a.webp 720w, /article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_d47522c3b8f471c8.webp 960w, /article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_af5e12dea7c34ce5.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="提示证书已安装"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>继续点击 <strong>添加根证书至系统（Root）</strong>，点击移动按钮，此时需要授予root权限。</p>
<blockquote>
<p>我在点击移动按钮后提示失败，但确保授予了Root权限。</p>
<p>经过测试，抓包功能正常。</p>
</blockquote>
<p><a href="/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_a7eb34704bd468fb.webp" data-fancybox="gallery" data-src="/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_a7eb34704bd468fb.webp" data-caption="添加证书至系统">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_5ff767bc2374a9ce.webp 480w, /article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_95c72bee45c1b685.webp 720w, /article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_10679293244fbf59.webp 960w, /article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_a7eb34704bd468fb.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="279"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_95c72bee45c1b685.webp"
                    srcset="/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_5ff767bc2374a9ce.webp 480w, /article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_95c72bee45c1b685.webp 720w, /article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_10679293244fbf59.webp 960w, /article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_a7eb34704bd468fb.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="添加证书至系统"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>下载并刷入链接中的LSPosed模块 <strong>JustTrustMe</strong> 和 <strong>TrustMeAlready</strong> 并勾选你要抓包的软件（两个模块都需要勾选）。</p>
<p><a href="/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_79b3951fa54d5244.webp" data-fancybox="gallery" data-src="/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_79b3951fa54d5244.webp" data-caption="JustTrustMe">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_140a48d6fa66e0b8.webp 480w, /article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_2600d8f2d40a9148.webp 720w, /article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_129553bd58c29c79.webp 960w, /article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_79b3951fa54d5244.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="934"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_2600d8f2d40a9148.webp"
                    srcset="/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_140a48d6fa66e0b8.webp 480w, /article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_2600d8f2d40a9148.webp 720w, /article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_129553bd58c29c79.webp 960w, /article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_79b3951fa54d5244.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="JustTrustMe"
                    
                />
            </picture>
        </a></p>
<p><a href="/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_dd75299bcbab9386.webp" data-fancybox="gallery" data-src="/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_dd75299bcbab9386.webp" data-caption="TrustMeAlready">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_36f02f5742230ddc.webp 480w, /article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_af4520d166811373.webp 720w, /article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_6fd5e63b01b04844.webp 960w, /article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_dd75299bcbab9386.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="913"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_af4520d166811373.webp"
                    srcset="/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_36f02f5742230ddc.webp 480w, /article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_af4520d166811373.webp 720w, /article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_6fd5e63b01b04844.webp 960w, /article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_dd75299bcbab9386.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="TrustMeAlready"
                    
                />
            </picture>
        </a></p>
</li>
</ul>
<p>环境配置工作到此已全部完成。</p>
<h2 id="星穹铁道">星穹铁道</h2>
<p>本节只针对于星穹铁道APP，其实其他软件同理也可以抓包。</p>
<blockquote>
<p>注意：</p>
<p>到这里我们还是不能百分百保证能够对所有的应用进行抓包，因为各种软件会因为安全（银行软件）等因素对APP网络通信进行限制。这种情况下还是无法抓包的。</p>
<p><a href="/article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_d5bef73349ddf505.webp" data-fancybox="gallery" data-src="/article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_d5bef73349ddf505.webp" data-caption="网络通信安全级别高">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_c2ce3243bea5df9f.webp 480w, /article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_1b639b9b4948e9ec.webp 720w, /article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_5a2c6dc5de19357a.webp 960w, /article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_d5bef73349ddf505.webp 1049w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1049"
                    height="614"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_1b639b9b4948e9ec.webp"
                    srcset="/article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_c2ce3243bea5df9f.webp 480w, /article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_1b639b9b4948e9ec.webp 720w, /article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_5a2c6dc5de19357a.webp 960w, /article/hkrpg-android-httpcanary/6705379e1ff76bbd1a6a074f98de7367_hu_d5bef73349ddf505.webp 1049w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="网络通信安全级别高"
                    
                />
            </picture>
        </a></p>
<p>例如抖音系列app都无法正常抓包，此时可以通过逆向应用APK文件等方式寻求解决办法，<a href="https://bbs.kanxue.com/thread-276015.htm" target="_blank" rel="noopener">查看参照</a>。</p>
</blockquote>
<p>星穹铁道其实也是进行了诸如此类的限制的，如果你直接开着抓包打开游戏，还是会提示网络异常。</p>
<p>但是你可以在正常进入游戏后，先点击进入跃迁，再打开Http Canary进行抓包，然后回到跃迁界面，点击查看详情，再点击历史记录即可抓到需要的数据。</p>
<p><a href="/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_4e802951b1f0b1fd.webp" data-fancybox="gallery" data-src="/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_4e802951b1f0b1fd.webp" data-caption="抽卡历史记录链接">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_3f3b9deee64890d.webp 480w, /article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_2658f1e2c9874df6.webp 720w, /article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_d07712a9351d22a9.webp 960w, /article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_22311d46e5b56c1d.webp 1440w, /article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_4e802951b1f0b1fd.webp 2712w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2712"
                    height="1220"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_2658f1e2c9874df6.webp"
                    srcset="/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_3f3b9deee64890d.webp 480w, /article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_2658f1e2c9874df6.webp 720w, /article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_d07712a9351d22a9.webp 960w, /article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_22311d46e5b56c1d.webp 1440w, /article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_4e802951b1f0b1fd.webp 2712w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="抽卡历史记录链接"
                    
                />
            </picture>
        </a></p>
<p>回到Http Canary，找到 <strong>api-takumi.mihoyo.com</strong> 开头的链接，点击进入，长按下图所示区域即可进行复制。</p>
<p><a href="/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_fb83179d5098b799.webp" data-fancybox="gallery" data-src="/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_fb83179d5098b799.webp" data-caption="长按复制">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_40a9d29deb314144.webp 480w, /article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_93999977f5914ff7.webp 720w, /article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_d83b63099bb4db9f.webp 960w, /article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_fb83179d5098b799.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="659"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_93999977f5914ff7.webp"
                    srcset="/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_40a9d29deb314144.webp 480w, /article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_93999977f5914ff7.webp 720w, /article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_d83b63099bb4db9f.webp 960w, /article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_fb83179d5098b799.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="长按复制"
                    
                />
            </picture>
        </a></p>
<h2 id="总结">总结</h2>
<p>本文更多的是关于 Http Canary 这一抓包环境如何正常安装使用的说明，对于其他未做更多网络通信安全性限制的APP这一切都已经够了，其他的APP需要对症下药。</p>
]]></content:encoded>
    </item>
    <item>
      <title>切换Xcode以编译未适配的Theos插件</title>
      <link>https://vccv.cc/article/switch-xcode-theos.html</link>
      <pubDate>Mon, 24 Apr 2023 22:52:25 +0000</pubDate>
      <guid>https://vccv.cc/article/switch-xcode-theos.html</guid>
      <description>在最近更换新设备后，我正打算重新编译一个名为PassBy的iOS越狱插件，发现频频报错。结果一阵排查与搜索，确定了切换Xcode到老版本为最简单的解决方法，于是记录了下来。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>最近需要重新编译一个名为 <a href="https://github.com/giorgioiavicoli/PassBy" target="_blank" rel="noopener">PassBy</a> 的iOS越狱插件，发现在我的新设备上频频报错，于是将探索经过与解决过程记录在下。</p>
<p>由于我并不专业，甚至对iOS开发并不了解，完全是以学习的态度进行的探索记录。如有纰漏，欢迎大家在评论区批评指正。</p>
<blockquote>
<p>顺便给自己的另外一篇相关文章打打广告哈哈：</p>
<p><a href="https://vccv.cc/article/passby-fix.html" target="_blank" rel="noopener">iOS越狱插件PassBy定制</a>，记录了我尝试解决PassBy不识别Apple Watch之外的其他蓝牙穿戴设备的经过。</p>
</blockquote>
<h2 id="尝试编译">尝试编译</h2>
<h3 id="第一次编译">第一次编译</h3>
<blockquote>
<p>系统：macOS Monterey 12.6.5</p>
<p>芯片类型：Intel芯片，非M系列</p>
<p>Xcode版本：14.2</p>
</blockquote>
<p>我先是尝试直接编译，输入<code>make package</code>，结果提示openURL已经被淘汰。</p>
<p><a href="/article/switch-xcode-theos/image-20230425125957865_hu_c5f919f04345e0d0.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425125957865_hu_c5f919f04345e0d0.webp" data-caption="openURL已被淘汰">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425125957865_hu_e365cfdc20a7c501.webp 480w, /article/switch-xcode-theos/image-20230425125957865_hu_67c8b62d4a3c7733.webp 720w, /article/switch-xcode-theos/image-20230425125957865_hu_e1367ead4f58da76.webp 960w, /article/switch-xcode-theos/image-20230425125957865_hu_68f840973dd62db9.webp 1440w, /article/switch-xcode-theos/image-20230425125957865_hu_c5f919f04345e0d0.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="714"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425125957865_hu_67c8b62d4a3c7733.webp"
                    srcset="/article/switch-xcode-theos/image-20230425125957865_hu_e365cfdc20a7c501.webp 480w, /article/switch-xcode-theos/image-20230425125957865_hu_67c8b62d4a3c7733.webp 720w, /article/switch-xcode-theos/image-20230425125957865_hu_e1367ead4f58da76.webp 960w, /article/switch-xcode-theos/image-20230425125957865_hu_68f840973dd62db9.webp 1440w, /article/switch-xcode-theos/image-20230425125957865_hu_c5f919f04345e0d0.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="openURL已被淘汰"
                    
                />
            </picture>
        </a></p>
<p>此时我便猜测是Xcode版本太高导致的不适配，我打算先去GitHub的<a href="https://github.com/giorgioiavicoli/PassBy" target="_blank" rel="noopener">源代码</a>地址去看看作者有没有进行更新。结果很可惜，没有办法，我只能尝试修改一下代码。</p>
<p>根据报错信息我先是找到了相关c文件，搜索openURL关键词后，注释了相关代码。</p>
<p><a href="/article/switch-xcode-theos/image-20230425130026558_hu_dfdae32419d3d8dd.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425130026558_hu_dfdae32419d3d8dd.webp" data-caption="注释openURL代码">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425130026558_hu_6e704889c8ec55eb.webp 480w, /article/switch-xcode-theos/image-20230425130026558_hu_f9f2eb4dfce65af0.webp 720w, /article/switch-xcode-theos/image-20230425130026558_hu_24e680bd665d5ee8.webp 960w, /article/switch-xcode-theos/image-20230425130026558_hu_7de06ef5bd85d8fc.webp 1440w, /article/switch-xcode-theos/image-20230425130026558_hu_dfdae32419d3d8dd.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="934"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425130026558_hu_f9f2eb4dfce65af0.webp"
                    srcset="/article/switch-xcode-theos/image-20230425130026558_hu_6e704889c8ec55eb.webp 480w, /article/switch-xcode-theos/image-20230425130026558_hu_f9f2eb4dfce65af0.webp 720w, /article/switch-xcode-theos/image-20230425130026558_hu_24e680bd665d5ee8.webp 960w, /article/switch-xcode-theos/image-20230425130026558_hu_7de06ef5bd85d8fc.webp 1440w, /article/switch-xcode-theos/image-20230425130026558_hu_dfdae32419d3d8dd.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="注释openURL代码"
                    
                />
            </picture>
        </a></p>
<p>继续寻找，可以发现这是并不影响主要功能的代码，应该是执行一个打开捐赠和源代码网址的操作，由于我并不熟悉Objective-C语言，最简单的方式便是直接注释掉，所幸也不影响插件主体功能。两个网址我粘贴在下面：</p>
<ul>
<li>捐赠(Donate)：https://paypal.me/giorgioiavicoli</li>
<li>源代码(Source Code)：https://github.com/giorgioiavicoli/PassBy</li>
</ul>
<p><a href="/article/switch-xcode-theos/image-20230425130055545_hu_4cb9f381a8c42340.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425130055545_hu_4cb9f381a8c42340.webp" data-caption="注释openURL代码">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425130055545_hu_970de69b88fc6f91.webp 480w, /article/switch-xcode-theos/image-20230425130055545_hu_1525860c695110e2.webp 720w, /article/switch-xcode-theos/image-20230425130055545_hu_405ca1aa82dfc4a1.webp 960w, /article/switch-xcode-theos/image-20230425130055545_hu_4cb9f381a8c42340.webp 1388w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1388"
                    height="344"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425130055545_hu_1525860c695110e2.webp"
                    srcset="/article/switch-xcode-theos/image-20230425130055545_hu_970de69b88fc6f91.webp 480w, /article/switch-xcode-theos/image-20230425130055545_hu_1525860c695110e2.webp 720w, /article/switch-xcode-theos/image-20230425130055545_hu_405ca1aa82dfc4a1.webp 960w, /article/switch-xcode-theos/image-20230425130055545_hu_4cb9f381a8c42340.webp 1388w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="注释openURL代码"
                    
                />
            </picture>
        </a></p>
<h3 id="第二次编译">第二次编译</h3>
<p>尝试继续编译，不出所料，新的问题又出现了。</p>
<p>这次的问题则更为棘手，theos在调用Xcode编译工具时直接提示找不到Message框架。</p>
<p><a href="/article/switch-xcode-theos/image-20230425125903111_hu_535af8652e729a74.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425125903111_hu_535af8652e729a74.webp" data-caption="找不到Message框架">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425125903111_hu_d9611c7a4082079c.webp 480w, /article/switch-xcode-theos/image-20230425125903111_hu_9fdc990c4cdb4fe9.webp 720w, /article/switch-xcode-theos/image-20230425125903111_hu_6f23ded2c10eb603.webp 960w, /article/switch-xcode-theos/image-20230425125903111_hu_1b36bcc550c86fa4.webp 1440w, /article/switch-xcode-theos/image-20230425125903111_hu_535af8652e729a74.webp 2164w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2164"
                    height="730"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425125903111_hu_9fdc990c4cdb4fe9.webp"
                    srcset="/article/switch-xcode-theos/image-20230425125903111_hu_d9611c7a4082079c.webp 480w, /article/switch-xcode-theos/image-20230425125903111_hu_9fdc990c4cdb4fe9.webp 720w, /article/switch-xcode-theos/image-20230425125903111_hu_6f23ded2c10eb603.webp 960w, /article/switch-xcode-theos/image-20230425125903111_hu_1b36bcc550c86fa4.webp 1440w, /article/switch-xcode-theos/image-20230425125903111_hu_535af8652e729a74.webp 2164w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="找不到Message框架"
                    
                />
            </picture>
        </a></p>
<p>这个问题就不是我简单修改能够解决的了。我猜测是新版本的Xcode舍弃了这个框架，这是摆在我眼前的就只有两条路：要么重构相关代码（难度对我来说确实是太大了），要么就只能更换到Xcode的旧版本（在我实践之前其实也是个未知数，不能保证一定能解决）。</p>
<p>我只能尝试更换Xcode版本这条路了。</p>
<h2 id="尝试更换xcode版本">尝试更换Xcode版本</h2>
<p>先查看一下目前的版本，可以看到是14.2版本的。</p>
<p><a href="/article/switch-xcode-theos/image-20230425193709252_hu_1ec2e371565ba1a5.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425193709252_hu_1ec2e371565ba1a5.webp" data-caption="查看版本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425193709252_hu_87f0c569945233ee.webp 480w, /article/switch-xcode-theos/image-20230425193709252_hu_1ea760faee46f840.webp 720w, /article/switch-xcode-theos/image-20230425193709252_hu_81ec99dffb4ca0e7.webp 960w, /article/switch-xcode-theos/image-20230425193709252_hu_27709981de171d69.webp 1440w, /article/switch-xcode-theos/image-20230425193709252_hu_1ec2e371565ba1a5.webp 1480w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1480"
                    height="530"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425193709252_hu_1ea760faee46f840.webp"
                    srcset="/article/switch-xcode-theos/image-20230425193709252_hu_87f0c569945233ee.webp 480w, /article/switch-xcode-theos/image-20230425193709252_hu_1ea760faee46f840.webp 720w, /article/switch-xcode-theos/image-20230425193709252_hu_81ec99dffb4ca0e7.webp 960w, /article/switch-xcode-theos/image-20230425193709252_hu_27709981de171d69.webp 1440w, /article/switch-xcode-theos/image-20230425193709252_hu_1ec2e371565ba1a5.webp 1480w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="查看版本"
                    
                />
            </picture>
        </a></p>
<p>在<a href="https://developer.apple.com/support/xcode/" target="_blank" rel="noopener">Xcode的支持页面</a>可以清楚的看到每个Xcode版本的最低系统要求以及包含的SDK等信息。</p>
<p><a href="/article/switch-xcode-theos/image-20230425194451808_hu_35c102dffec9904c.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425194451808_hu_35c102dffec9904c.webp" data-caption="Xcode版本区别">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425194451808_hu_6fb004ee24f4d441.webp 480w, /article/switch-xcode-theos/image-20230425194451808_hu_72c7fd7162d801b1.webp 720w, /article/switch-xcode-theos/image-20230425194451808_hu_a8fd321dab3244a4.webp 960w, /article/switch-xcode-theos/image-20230425194451808_hu_46471bab49d58bfe.webp 1440w, /article/switch-xcode-theos/image-20230425194451808_hu_35c102dffec9904c.webp 1654w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1654"
                    height="290"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425194451808_hu_72c7fd7162d801b1.webp"
                    srcset="/article/switch-xcode-theos/image-20230425194451808_hu_6fb004ee24f4d441.webp 480w, /article/switch-xcode-theos/image-20230425194451808_hu_72c7fd7162d801b1.webp 720w, /article/switch-xcode-theos/image-20230425194451808_hu_a8fd321dab3244a4.webp 960w, /article/switch-xcode-theos/image-20230425194451808_hu_46471bab49d58bfe.webp 1440w, /article/switch-xcode-theos/image-20230425194451808_hu_35c102dffec9904c.webp 1654w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Xcode版本区别"
                    
                />
            </picture>
        </a></p>
<p>接下来去Apple官方关于<a href="https://developer.apple.com/download/all/?q=xcode" target="_blank" rel="noopener">Xcode所有版本的下载页面</a>，下载一个旧版本即可。我下载的是12.5.1版本。</p>
<p><a href="/article/switch-xcode-theos/image-20230425194524276_hu_2d101527363b0cd3.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425194524276_hu_2d101527363b0cd3.webp" data-caption="下载12.5.1版本Xcode">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425194524276_hu_b1aa277a8f45c7e3.webp 480w, /article/switch-xcode-theos/image-20230425194524276_hu_b50482f6b0327468.webp 720w, /article/switch-xcode-theos/image-20230425194524276_hu_1ff03dcd471df7ce.webp 960w, /article/switch-xcode-theos/image-20230425194524276_hu_9da855de5fc2f5b7.webp 1440w, /article/switch-xcode-theos/image-20230425194524276_hu_2d101527363b0cd3.webp 2392w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2392"
                    height="1144"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425194524276_hu_b50482f6b0327468.webp"
                    srcset="/article/switch-xcode-theos/image-20230425194524276_hu_b1aa277a8f45c7e3.webp 480w, /article/switch-xcode-theos/image-20230425194524276_hu_b50482f6b0327468.webp 720w, /article/switch-xcode-theos/image-20230425194524276_hu_1ff03dcd471df7ce.webp 960w, /article/switch-xcode-theos/image-20230425194524276_hu_9da855de5fc2f5b7.webp 1440w, /article/switch-xcode-theos/image-20230425194524276_hu_2d101527363b0cd3.webp 2392w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="下载12.5.1版本Xcode"
                    
                />
            </picture>
        </a></p>
<p>接下来就是解压.xip文件，将解压出来的Xcode.app更改一个名字，比如Xcode_12.5.app，最后将其移动到/Application目录下即可。</p>
<p><a href="/article/switch-xcode-theos/image-20230425194956911_hu_39826ceb05389ef7.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425194956911_hu_39826ceb05389ef7.webp" data-caption="解压并改名">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425194956911_hu_42695a99e749e09c.webp 480w, /article/switch-xcode-theos/image-20230425194956911_hu_39826ceb05389ef7.webp 642w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="642"
                    height="160"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425194956911_hu_39826ceb05389ef7.webp"
                    srcset="/article/switch-xcode-theos/image-20230425194956911_hu_42695a99e749e09c.webp 480w, /article/switch-xcode-theos/image-20230425194956911_hu_39826ceb05389ef7.webp 642w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="解压并改名"
                    
                />
            </picture>
        </a></p>
<p>上图可以看到我的老版本Xcode是并不能直接打开的，但是对本章来说是丝毫没有影响的，我们并不需要直接打开老版本Xcode进行操作。具体缘由请继续看下去。</p>
<blockquote>
<p>这里解压的时间比较久，需要耐心等待一下。</p>
<p>另外平时下载更新Xcode也可以这样操作。配合多线程下载工具的话，基本上可以跑满宽带速度，同时避免App Store下载失败等问题。缺点就是解压比较耗时。</p>
</blockquote>
<h2 id="切换xcode开发工具版本">切换Xcode开发工具版本</h2>
<p>注意本节的小标题并不是“切换Xcode版本”，因为对我们来说，仅仅需要的只是Xcode老版本软件自带的开发目录下的那些脚本工具而已，比如gcc等。</p>
<p><a href="/article/switch-xcode-theos/image-20230425195518729_hu_56a6b9bf26d7cb97.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425195518729_hu_56a6b9bf26d7cb97.webp" data-caption="开发者工具目录">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425195518729_hu_25ff8ccb828c1ce0.webp 480w, /article/switch-xcode-theos/image-20230425195518729_hu_18a25fd760e3ec9d.webp 720w, /article/switch-xcode-theos/image-20230425195518729_hu_63de961a4a350280.webp 960w, /article/switch-xcode-theos/image-20230425195518729_hu_56a6b9bf26d7cb97.webp 1426w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1426"
                    height="536"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425195518729_hu_18a25fd760e3ec9d.webp"
                    srcset="/article/switch-xcode-theos/image-20230425195518729_hu_25ff8ccb828c1ce0.webp 480w, /article/switch-xcode-theos/image-20230425195518729_hu_18a25fd760e3ec9d.webp 720w, /article/switch-xcode-theos/image-20230425195518729_hu_63de961a4a350280.webp 960w, /article/switch-xcode-theos/image-20230425195518729_hu_56a6b9bf26d7cb97.webp 1426w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="开发者工具目录"
                    
                />
            </picture>
        </a></p>
<p>接下来只需要使用该命令切换xcode-select目录即可：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo xcode-select -s /Applications/<span class="o">{</span>这里修改成具体的文件名<span class="o">}</span>/Contents/Developer/
</span></span></code></pre></td></tr></table>
</div>
</div><p>修改成自己的老版本文件名即可，输入密码不显示。</p>
<p><a href="/article/switch-xcode-theos/image-20230425195747550_hu_83e406e4325579aa.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425195747550_hu_83e406e4325579aa.webp" data-caption="切换路径">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425195747550_hu_db77e6fc44eb80cb.webp 480w, /article/switch-xcode-theos/image-20230425195747550_hu_33e411312bcb432e.webp 720w, /article/switch-xcode-theos/image-20230425195747550_hu_573389fd3d886b60.webp 960w, /article/switch-xcode-theos/image-20230425195747550_hu_83e406e4325579aa.webp 1078w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1078"
                    height="142"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425195747550_hu_33e411312bcb432e.webp"
                    srcset="/article/switch-xcode-theos/image-20230425195747550_hu_db77e6fc44eb80cb.webp 480w, /article/switch-xcode-theos/image-20230425195747550_hu_33e411312bcb432e.webp 720w, /article/switch-xcode-theos/image-20230425195747550_hu_573389fd3d886b60.webp 960w, /article/switch-xcode-theos/image-20230425195747550_hu_83e406e4325579aa.webp 1078w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="切换路径"
                    
                />
            </picture>
        </a></p>
<p>此时再输入命令验证一下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">xcodebuild -version
</span></span><span class="line"><span class="cl">xcode-select -p
</span></span><span class="line"><span class="cl">gcc -v
</span></span><span class="line"><span class="cl">g++ -v
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/switch-xcode-theos/image-20230425200003721_hu_8981dc30cc383260.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425200003721_hu_8981dc30cc383260.webp" data-caption="老版本的gcc">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425200003721_hu_7a77f00558e214e2.webp 480w, /article/switch-xcode-theos/image-20230425200003721_hu_482f1c64dfcf4e54.webp 720w, /article/switch-xcode-theos/image-20230425200003721_hu_55d740bccae06e30.webp 960w, /article/switch-xcode-theos/image-20230425200003721_hu_c6778e189c44eb41.webp 1440w, /article/switch-xcode-theos/image-20230425200003721_hu_8981dc30cc383260.webp 3176w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3176"
                    height="542"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425200003721_hu_482f1c64dfcf4e54.webp"
                    srcset="/article/switch-xcode-theos/image-20230425200003721_hu_7a77f00558e214e2.webp 480w, /article/switch-xcode-theos/image-20230425200003721_hu_482f1c64dfcf4e54.webp 720w, /article/switch-xcode-theos/image-20230425200003721_hu_55d740bccae06e30.webp 960w, /article/switch-xcode-theos/image-20230425200003721_hu_c6778e189c44eb41.webp 1440w, /article/switch-xcode-theos/image-20230425200003721_hu_8981dc30cc383260.webp 3176w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="老版本的gcc"
                    
                />
            </picture>
        </a></p>
<p>以上命令的输出结果都可以看到你选择的老版本Xcode文件名称的字样，类似 <strong>Xcode_12.5</strong> 。</p>
<h2 id="第三次编译">第三次编译</h2>
<p>再次尝试编译，问题终于迎刃而解了。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">yuesir at iMac in /Volumes/Data/Xcode/PassBy
</span></span><span class="line"><span class="cl">$ make package
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> tweak PassBy…
</span></span><span class="line"><span class="cl">make<span class="o">[</span>2<span class="o">]</span>: Nothing to be <span class="k">done</span> <span class="k">for</span> <span class="s1">&#39;internal-library-compile&#39;</span>.
</span></span><span class="line"><span class="cl">&gt; Making all in passbyprefs…
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> bundle PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Copying resource directories into the bundle wrapper…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling PassByRootListController.m <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling PassByRootListController.m <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByPrefs <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByPrefs <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByPrefs <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByPrefs <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Merging bundle PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Signing PassByPrefs…
</span></span><span class="line"><span class="cl">&gt; Making all in passbyflipswitch…
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> bundle PassByFlipswitch…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Copying resource directories into the bundle wrapper…
</span></span><span class="line"><span class="cl">make<span class="o">[</span>3<span class="o">]</span>: Nothing to be <span class="k">done</span> <span class="k">for</span> <span class="s1">&#39;internal-bundle-compile&#39;</span>.
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> tweak PassBy…
</span></span><span class="line"><span class="cl">&gt; Making stage in passbyprefs…
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> bundle PassByPrefs…
</span></span><span class="line"><span class="cl">&gt; Making stage in passbyflipswitch…
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> bundle PassByFlipswitch…
</span></span><span class="line"><span class="cl">dm.pl: building package <span class="sb">`</span>com.giorgioiavicoli.passby:iphoneos-arm<span class="s1">&#39; in `./packages/com.giorgioiavicoli.passby_1.9.5_iphoneos-arm.deb&#39;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>其实之后我还尝试过将上面注释掉的代码恢复正常，没想到还是报一样的错误</p>
<p>这里我怀疑可能是安装的 Command Line Tools 的版本问题。由于不知道安装低版本的Tools会造成什么影响，我就没有进行尝试。</p>
</blockquote>
<h2 id="切换回原版本">切换回原版本</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo xcode-select -s /Applications/Xcode.app/Contents/Developer/
</span></span></code></pre></td></tr></table>
</div>
</div><p>还是验证一下：</p>
<p><a href="/article/switch-xcode-theos/image-20230425201635817_hu_ce1e831a1af96d20.webp" data-fancybox="gallery" data-src="/article/switch-xcode-theos/image-20230425201635817_hu_ce1e831a1af96d20.webp" data-caption="切换回原版本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/switch-xcode-theos/image-20230425201635817_hu_8a6a9db08834231c.webp 480w, /article/switch-xcode-theos/image-20230425201635817_hu_50f56ae46a3cd14d.webp 720w, /article/switch-xcode-theos/image-20230425201635817_hu_fbb99a66c2aec6c7.webp 960w, /article/switch-xcode-theos/image-20230425201635817_hu_b64e48f9d475761b.webp 1440w, /article/switch-xcode-theos/image-20230425201635817_hu_ce1e831a1af96d20.webp 1584w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1584"
                    height="502"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/switch-xcode-theos/image-20230425201635817_hu_50f56ae46a3cd14d.webp"
                    srcset="/article/switch-xcode-theos/image-20230425201635817_hu_8a6a9db08834231c.webp 480w, /article/switch-xcode-theos/image-20230425201635817_hu_50f56ae46a3cd14d.webp 720w, /article/switch-xcode-theos/image-20230425201635817_hu_fbb99a66c2aec6c7.webp 960w, /article/switch-xcode-theos/image-20230425201635817_hu_b64e48f9d475761b.webp 1440w, /article/switch-xcode-theos/image-20230425201635817_hu_ce1e831a1af96d20.webp 1584w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="切换回原版本"
                    
                />
            </picture>
        </a></p>
<h2 id="一键脚本">一键脚本</h2>
<p>这里再提供一个大佬分享的一键脚本，但我并没有亲自尝试，于是我将链接贴在这里，以示感谢。</p>
<p>文章链接：https://www.cnblogs.com/zndxall/p/12463744.html</p>
<h2 id="感谢">感谢</h2>
<p><a href="https://developer.apple.com/download/all/?q=xcode%2012.5.1" target="_blank" rel="noopener">Apple Xcode</a></p>
<p><a href="https://www.cnblogs.com/zndxall/p/12463744.html" target="_blank" rel="noopener">Xcode安装多个版本并自动切换版本</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Brew安装R内核的Notebook</title>
      <link>https://vccv.cc/article/brew-r-jupyter.html</link>
      <pubDate>Mon, 16 Jan 2023 11:40:36 +0000</pubDate>
      <guid>https://vccv.cc/article/brew-r-jupyter.html</guid>
      <description>我在另一篇文章介绍了在Linux远程服务器上使用conda配置r内核的jupyter notebook，但我发现conda对于各种依赖冲突处理不好，经常导致安装不成功。在macOS系统下本机使用brew进行安装更加简单快捷，总结出来步骤供大家以及将来的我参考。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>我的另一篇文章介绍了在Linux远程服务器上使用<a href="https://vccv.cc/article/conda-r-jupyter.html" target="_blank" rel="noopener">conda配置r内核的jupyter notebook</a>，但我发现conda对于各种依赖冲突处理得并不好，经常导致安装不成功。</p>
<p>后来我也在本机的macOS系统下使用brew进行安装，发现更加的简单快捷，于是总结出来步骤供大家以及将来的我参考。</p>
<blockquote>
<p>系统：macOS Venture 13.1 (22C65)</p>
<p>机型：Intel机型MacBook</p>
</blockquote>
<h2 id="准备">准备</h2>
<p>安装<a href="https://brew.sh/" target="_blank" rel="noopener">Homebrew</a>。</p>
<p>Homebrew是macOS平台下使用最多的包管理器，这是它的<a href="https://docs.brew.sh/Installation" target="_blank" rel="noopener">官方安装教程</a>。但是通常来说，我们只需要在确保网络畅通的情况下输入以下命令即可：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/bin/bash -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="安装r">安装R</h2>
<p>很简单：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install r
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="安装jupyter">安装Jupyter</h2>
<p>同样是一行命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install jupyterlab
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="安装r内核">安装R内核</h2>
<p>使用r安装<a href="https://github.com/IRkernel/IRkernel" target="_blank" rel="noopener">IRkernel</a>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 先进入r控制台</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 也可以安装RStudio</span>
</span></span><span class="line"><span class="cl">R
</span></span><span class="line"><span class="cl"><span class="c1"># 安装devtools</span>
</span></span><span class="line"><span class="cl">install.packages<span class="o">(</span><span class="s1">&#39;IRkernel&#39;</span><span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 这时候或许会叫你选择镜像 选择一个国内的就行 比如16</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 注册内核到R</span>
</span></span><span class="line"><span class="cl">IRkernel::installspec<span class="o">()</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 安装RStudio的快捷方式</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 如果安装了RStudio可以选择安装 只用notebook就不安装了</span>
</span></span><span class="line"><span class="cl">jupyter labextension install @techrah/text-shortcuts
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="启动notebook">启动Notebook</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">jupyter notebook
</span></span></code></pre></td></tr></table>
</div>
</div><p>点击创建，发现可以创建r内核的notebook了。</p>
<p><a href="/article/brew-r-jupyter/image-20230116115826253_hu_15b3d652285b41ee.webp" data-fancybox="gallery" data-src="/article/brew-r-jupyter/image-20230116115826253_hu_15b3d652285b41ee.webp" data-caption="R内核">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/brew-r-jupyter/image-20230116115826253_hu_a255ac3cd9899dad.webp 480w, /article/brew-r-jupyter/image-20230116115826253_hu_149627a7d861aeb1.webp 720w, /article/brew-r-jupyter/image-20230116115826253_hu_256d66456756f11.webp 960w, /article/brew-r-jupyter/image-20230116115826253_hu_3c85246230919e66.webp 1440w, /article/brew-r-jupyter/image-20230116115826253_hu_15b3d652285b41ee.webp 2424w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2424"
                    height="668"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/brew-r-jupyter/image-20230116115826253_hu_149627a7d861aeb1.webp"
                    srcset="/article/brew-r-jupyter/image-20230116115826253_hu_a255ac3cd9899dad.webp 480w, /article/brew-r-jupyter/image-20230116115826253_hu_149627a7d861aeb1.webp 720w, /article/brew-r-jupyter/image-20230116115826253_hu_256d66456756f11.webp 960w, /article/brew-r-jupyter/image-20230116115826253_hu_3c85246230919e66.webp 1440w, /article/brew-r-jupyter/image-20230116115826253_hu_15b3d652285b41ee.webp 2424w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="R内核"
                    
                />
            </picture>
        </a></p>
<h2 id="美化">美化</h2>
<p>这部分内容不是必要的，仅做记录。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 配置主题</span>
</span></span><span class="line"><span class="cl">pip install jupyterthemes
</span></span><span class="line"><span class="cl"><span class="c1"># 个人喜欢并且已经习惯了的一套主题设置</span>
</span></span><span class="line"><span class="cl">jt -t monokai -f fira -fs <span class="m">13</span> -cellw 90% -ofs <span class="m">11</span> -dfs <span class="m">11</span> -T -N
</span></span><span class="line"><span class="cl"><span class="c1"># 恢复默认主题</span>
</span></span><span class="line"><span class="cl">jt -r
</span></span><span class="line"><span class="cl"><span class="c1"># 配置插件</span>
</span></span><span class="line"><span class="cl">pip install jupyter_contrib_nbextensions
</span></span><span class="line"><span class="cl">jupyter contrib nbextension install --user
</span></span><span class="line"><span class="cl"><span class="c1"># 安装插件管理器 这一步可能会失败 详见后文更新1</span>
</span></span><span class="line"><span class="cl">pip install jupyter_nbextensions_configurator
</span></span><span class="line"><span class="cl"><span class="c1"># 建议配置项</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Hinterland 代码补全</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Collapsible headings 折叠标题</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Notify 通知机制，跑一些耗时较久的任务，完成后通知</span>
</span></span><span class="line"><span class="cl"><span class="c1"># zenmode 隐藏活动状态栏，方便注意代码</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ExecuteTime 显示运行的时间</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/brew-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp" data-fancybox="gallery" data-src="/article/brew-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp" data-caption="插件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/brew-r-jupyter/image-20221010205123146_hu_a41617526a284565.webp 480w, /article/brew-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp 720w, /article/brew-r-jupyter/image-20221010205123146_hu_a76e43c7eebd5b78.webp 960w, /article/brew-r-jupyter/image-20221010205123146_hu_cb4dcb98a38176df.webp 1440w, /article/brew-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2760"
                    height="1576"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/brew-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp"
                    srcset="/article/brew-r-jupyter/image-20221010205123146_hu_a41617526a284565.webp 480w, /article/brew-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp 720w, /article/brew-r-jupyter/image-20221010205123146_hu_a76e43c7eebd5b78.webp 960w, /article/brew-r-jupyter/image-20221010205123146_hu_cb4dcb98a38176df.webp 1440w, /article/brew-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="插件"
                    
                />
            </picture>
        </a></p>
<h2 id="后记">后记</h2>
<p>此次安装我并没有遇到任何阻碍，如果你遇到其他问题，欢迎评论区留言。</p>
<h2 id="更新1">更新1</h2>
<p>我在2023.03.20重复此教程时发现 <strong>Nbextensions</strong> 标签不会出现，经查阅，是插件未更新适配依赖包 nbclassic 的新版本导致。</p>
<p>详见GitHub的<a href="https://github.com/Jupyter-contrib/jupyter_nbextensions_configurator/issues/151" target="_blank" rel="noopener">issue</a>。</p>
<p>解决方法：降级依赖包版本即可。后续官方可能会更新适配。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install <span class="s2">&#34;nbclassic&lt;0.5&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="更新2">更新2</h2>
<p>2024.03.15 更新：早在几个月前notebook官方已经升级至7.x版本。新版本我已经没有进行过任何第三方的操作了。可以直接在设置里面进行修改，自定义程度很高。</p>
<p><a href="/article/brew-r-jupyter/image-20240315140159203_hu_5d447b0f666c2bce.webp" data-fancybox="gallery" data-src="/article/brew-r-jupyter/image-20240315140159203_hu_5d447b0f666c2bce.webp" data-caption="notebook-setting">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/brew-r-jupyter/image-20240315140159203_hu_ae6f509b005b588d.webp 480w, /article/brew-r-jupyter/image-20240315140159203_hu_5e7e909fe76520ff.webp 720w, /article/brew-r-jupyter/image-20240315140159203_hu_c169a3dc8c4989d4.webp 960w, /article/brew-r-jupyter/image-20240315140159203_hu_f413b848ae2c2d64.webp 1440w, /article/brew-r-jupyter/image-20240315140159203_hu_5d447b0f666c2bce.webp 1938w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1938"
                    height="1136"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/brew-r-jupyter/image-20240315140159203_hu_5e7e909fe76520ff.webp"
                    srcset="/article/brew-r-jupyter/image-20240315140159203_hu_ae6f509b005b588d.webp 480w, /article/brew-r-jupyter/image-20240315140159203_hu_5e7e909fe76520ff.webp 720w, /article/brew-r-jupyter/image-20240315140159203_hu_c169a3dc8c4989d4.webp 960w, /article/brew-r-jupyter/image-20240315140159203_hu_f413b848ae2c2d64.webp 1440w, /article/brew-r-jupyter/image-20240315140159203_hu_5d447b0f666c2bce.webp 1938w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="notebook-setting"
                    
                />
            </picture>
        </a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Unix终端安装配置Oh My Zsh</title>
      <link>https://vccv.cc/article/omz-terminal.html</link>
      <pubDate>Wed, 07 Dec 2022 10:04:46 +0000</pubDate>
      <guid>https://vccv.cc/article/omz-terminal.html</guid>
      <description>macOS系统目前已经将默认shell换成了zsh，正好可以配合oh my zsh这个项目实现超乎想象的终端体验。再搭配上其多彩的主题、强大的插件功能、活跃的社区生态，面对的“黑窗口”再也不是以前的那个冷冰冰的终端界面了，而是一个属于你自己的、独一无二的my zsh！</description>
      <content:encoded><![CDATA[<h2 id="介绍">介绍</h2>
<h3 id="oh-my-zsh-是什么">Oh My Zsh 是什么</h3>
<ul>
<li><strong>Oh My Zsh</strong> 是一款社区驱动的命令行工具，正如它的主页上说的，<strong>Oh My Zsh</strong> 是一种生活方式。它基于 <strong>zsh</strong> 命令行，提供了主题配置，插件机制，已经内置的便捷操作。给我们一种全新的方式使用命令行。</li>
<li><strong>Oh My Zsh</strong> 是基于 <strong>zsh</strong> 命令行的一个扩展工具集，提供了丰富的扩展功能。</li>
</ul>
<h3 id="官网">官网</h3>
<p><a href="https://ohmyz.sh/" target="_blank" rel="noopener">Oh My Zsh 官网</a></p>
<p>如果你有更多的兴趣，可以去官网了解详细情况。</p>
<h2 id="准备">准备</h2>
<ul>
<li>
<p>安装<strong>zsh</strong>替换默认shell。macOS系统目前默认的shell就是zsh，其他Linux系统可能需要先安装zsh。</p>
<h3 id="检查是否安装zsh">检查是否安装zsh</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">which zsh
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果显示为一个路径，例如<code>/bin/zsh</code>说明本地安装有zsh，且路径如上。可以跳过本节与下一节，进行oh-my-zsh的安装。如果显示<code>zsh not found</code>则需要安装<code>zsh</code>。</p>
<h3 id="root-用户直接安装">root 用户直接安装</h3>
<p>Ubuntu：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">apt install zsh <span class="c1">#安装zsh</span>
</span></span><span class="line"><span class="cl">chsh -s /bin/zsh <span class="c1">#将zsh设置成默认shell（不设置的话直接输入zsh命令启动即可）</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Centos：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">yum install zsh
</span></span><span class="line"><span class="cl">chsh -s /bin/zsh
</span></span></code></pre></td></tr></table>
</div>
</div><p>其他操作系统同理。</p>
<h3 id="非-root-用户编译安装">非 root 用户编译安装</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">wget -O zsh.tar.xz https://sourceforge.net/projects/zsh/files/latest/download --no-check-certificate
</span></span><span class="line"><span class="cl">mkdir zsh <span class="o">&amp;&amp;</span> unxz zsh.tar.xz <span class="o">&amp;&amp;</span> tar -xvf zsh.tar -C zsh --strip-components <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> zsh
</span></span><span class="line"><span class="cl">./configure --prefix<span class="o">=</span><span class="nv">$HOME</span>/zsh
</span></span><span class="line"><span class="cl">make <span class="o">&amp;&amp;</span> make install
</span></span></code></pre></td></tr></table>
</div>
</div><p>此处<code>$HOME/zsh</code>可以换成其他位置，例如<code>$HOME/software/zsh</code>。</p>
<blockquote>
<p>如果在<code>./configure</code>出现问题，提示缺少<code>ncurses</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">configure: error: <span class="s2">&#34;No terminal handling library was found on your system.
</span></span></span><span class="line"><span class="cl"><span class="s2">This is probably a library called &#39;curses&#39; or &#39;ncurses&#39;.  You may
</span></span></span><span class="line"><span class="cl"><span class="s2">need to install a package called &#39;curses-devel&#39; or &#39;ncurses-devel&#39; on your
</span></span></span><span class="line"><span class="cl"><span class="s2">system.&#34;</span>
</span></span><span class="line"><span class="cl">See <span class="sb">`</span>config.log<span class="err">&#39;</span> <span class="k">for</span> more details
</span></span></code></pre></td></tr></table>
</div>
</div><p>则需要再编译安装<code>ncurses</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CXXFLAGS</span><span class="o">=</span><span class="s2">&#34;-fPIC&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CFLAGS</span><span class="o">=</span><span class="s2">&#34;-fPIC&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">NCURSES_HOME</span><span class="o">=</span><span class="nv">$HOME</span>/ncurses <span class="c1"># 这里表示家目录的ncurses目录，可以自己设置</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PATH</span><span class="o">=</span><span class="nv">$NCURSES_HOME</span>/bin:<span class="nv">$PATH</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">LD_LIBRARY_PATH</span><span class="o">=</span><span class="nv">$NCURSES_HOME</span>/lib:<span class="nv">$LD_LIBRARY_PATH</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CPPFLAGS</span><span class="o">=</span><span class="s2">&#34;-I</span><span class="nv">$NCURSES_HOME</span><span class="s2">/include&#34;</span> <span class="nv">LDFLAGS</span><span class="o">=</span><span class="s2">&#34;-L</span><span class="nv">$NCURSES_HOME</span><span class="s2">/lib&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mkdir ncurses <span class="o">&amp;&amp;</span> <span class="nb">cd</span> ncurses
</span></span><span class="line"><span class="cl"><span class="c1"># 按时间倒序，下载最新版本ncurses</span>
</span></span><span class="line"><span class="cl">wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-XXX.tar.gz
</span></span><span class="line"><span class="cl">tar -xzvf ncurses-XXX.tar.gz
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> ncurses-XXX
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># --prefix目录同上NCURSES_HOME</span>
</span></span><span class="line"><span class="cl">./configure --prefix<span class="o">=</span><span class="nv">$HOME</span>/ncurses --with-shared --without-debug --enable-widec
</span></span><span class="line"><span class="cl">make <span class="o">&amp;&amp;</span> make install
</span></span></code></pre></td></tr></table>
</div>
</div><p>安装完成后回到zsh目录，再次运行<code>./configure --prefix=$HOME/zsh</code>和<code>make &amp;&amp; make install</code>即可。</p>
</blockquote>
<p>安装完成后，在当前shell的配置文件（对<code>bash</code>是<code>.bashrc</code>；<code>sh</code>则是<code>.profile</code>）中加入环境变量，注意环境变量中<code>zsh/bin</code>位置应该和安装位置匹配：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">PATH</span><span class="o">=</span><span class="nv">$HOME</span>/zsh/bin:<span class="nv">$PATH</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>并且使当前环境变量生效（以<code>.bashrc</code>为例）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> ~/.bashrc
</span></span></code></pre></td></tr></table>
</div>
</div><p>此时可以通过<code>zsh</code>命令启动并切换到<code>zsh</code>，且<code>which zsh</code>也应该返回<code>zsh</code>的安装路径。</p>
<h3 id="将-zsh-设定为默认-shell">将 zsh 设定为默认 shell</h3>
<p>通常，如果zsh为内置安装，可以通过<code>chsh -s /bin/zsh</code>在输入密码后修改默认 shell。</p>
<p>但如果<code>zsh</code>是编译安装，<code>chsh</code>无法成功执行，则可以通过添加以下语句到默认 shell 配置文件例如 .bashrc 中（先确保zsh配置正确，<code>which zsh</code>能找到），从而实现登陆后自动启动切换：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[[</span> <span class="o">(</span><span class="nv">$-</span> <span class="o">==</span> *i*<span class="o">)</span> <span class="o">&amp;&amp;</span> <span class="o">(</span><span class="nv">$SSH_TTY</span><span class="o">)</span> <span class="o">]]</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">then</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">SHELL</span><span class="o">=</span><span class="sb">`</span>which zsh<span class="sb">`</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span> -z <span class="s2">&#34;</span><span class="nv">$ZSH_VERSION</span><span class="s2">&#34;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">exec</span> <span class="s2">&#34;</span><span class="nv">$SHELL</span><span class="s2">&#34;</span> -l
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>以上语句只对 ssh 访问生效，因此不会影响 SFTP 和远程调试等功能。</p>
</li>
<li>
<p>安装<strong>git</strong>，同理使用apt或者yum包管理器安装即可。</p>
</li>
<li>
<p>最后需要<strong>curl</strong>或者<strong>wget</strong>，安装方法同上。</p>
</li>
</ul>
<h2 id="安装">安装</h2>
<h3 id="curl安装">curl安装</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="wget安装">wget安装</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>wget https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>两种安装方式并没有什么不同。</p>
<h2 id="主题">主题</h2>
<p>我通常是使用自带的 <strong>steeef</strong> 主题，还算简洁好用。</p>
<p>如果想要更换主题，只需要编辑<code>~/.zshrc</code>文件，把ZSH_THEME后面换成你喜欢的主题即可。</p>
<p><a href="/article/omz-terminal/image-20221209104217575_hu_5e1d6ed8fb16d72c.webp" data-fancybox="gallery" data-src="/article/omz-terminal/image-20221209104217575_hu_5e1d6ed8fb16d72c.webp" data-caption="更换主题">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/omz-terminal/image-20221209104217575_hu_aebdba3056600f52.webp 480w, /article/omz-terminal/image-20221209104217575_hu_96d69bc5a1e59098.webp 720w, /article/omz-terminal/image-20221209104217575_hu_5e1d6ed8fb16d72c.webp 960w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="960"
                    height="202"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/omz-terminal/image-20221209104217575_hu_96d69bc5a1e59098.webp"
                    srcset="/article/omz-terminal/image-20221209104217575_hu_aebdba3056600f52.webp 480w, /article/omz-terminal/image-20221209104217575_hu_96d69bc5a1e59098.webp 720w, /article/omz-terminal/image-20221209104217575_hu_5e1d6ed8fb16d72c.webp 960w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="更换主题"
                    
                />
            </picture>
        </a></p>
<p>使主题生效的方法也很简单，重新打开一个终端窗口或者输入以下命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> ~/.zshrc
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>.zshrc文件：</p>
<p><code>.zshrc</code>文件与<code>.bashrc</code>文件作用是一样的。以前多数的unix系统默认shell都是bash，.bashrc文件就是bash的配置文件。</p>
<p>使用man bash命令查看到的联机帮助文件中的相关解释如下：
.bashrc - The individual per-interactive-shell startup file.</p>
<p>这个文件主要保存个人的一些个性化设置，如命令别名、路径等。</p>
<p>每次修改.bashrc后，使用source ~/.bashrc（或者 . ~/.bashrc）就可以立刻加载修改后的设置，使之生效。一般会在.bash_profile文件中显式调用.bashrc。</p>
<p>登陆linux启动bash时首先会去读取~/.bash_profile文件，这样~/.bashrc也就得到执行了，你的个性化设置也就生效了。</p>
</blockquote>
<h2 id="插件">插件</h2>
<p>omz插件的管理是很简单的，有两个插件目录，其中 <strong>user</strong> 为你的用户名：</p>
<ul>
<li>
<p><strong>/Users/user/.oh-my-zsh/plugins</strong></p>
<p>官方插件目录。该目录已经预装了很多实用的插件，只需要手动激活；</p>
</li>
<li>
<p><strong>/Users/user/.oh-my-zsh/custom/plugins</strong></p>
<p>第三方插件目录，快捷命令：<code>$ZSH_CUSTOM/plugins</code>。</p>
</li>
</ul>
<p>安装插件时只需要把插件下载到第三方插件目录即可，然后在 <code>~/.zshrc</code> 配置文件中的 <code>plugins</code> 变量中添加对应插件的名称即可。</p>
<h3 id="下载插件">下载插件</h3>
<h4 id="zsh-syntax-highlighting">zsh-syntax-highlighting</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 命令语法高亮</span>
</span></span><span class="line"><span class="cl">git clone https://github.com/zsh-users/zsh-syntax-highlighting.git <span class="si">${</span><span class="nv">ZSH_CUSTOM</span><span class="k">:-</span><span class="p">~/.oh-my-zsh/custom</span><span class="si">}</span>/plugins/zsh-syntax-highlighting
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/omz-terminal/image-20221207141425504_hu_9fda11391ad302f2.webp" data-fancybox="gallery" data-src="/article/omz-terminal/image-20221207141425504_hu_9fda11391ad302f2.webp" data-caption="高亮效果">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/omz-terminal/image-20221207141425504_hu_6e13f04f14dbcd91.webp 480w, /article/omz-terminal/image-20221207141425504_hu_6abb72c853d42629.webp 720w, /article/omz-terminal/image-20221207141425504_hu_ac57e4cb25cb9153.webp 960w, /article/omz-terminal/image-20221207141425504_hu_9fda11391ad302f2.webp 996w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="996"
                    height="424"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/omz-terminal/image-20221207141425504_hu_6abb72c853d42629.webp"
                    srcset="/article/omz-terminal/image-20221207141425504_hu_6e13f04f14dbcd91.webp 480w, /article/omz-terminal/image-20221207141425504_hu_6abb72c853d42629.webp 720w, /article/omz-terminal/image-20221207141425504_hu_ac57e4cb25cb9153.webp 960w, /article/omz-terminal/image-20221207141425504_hu_9fda11391ad302f2.webp 996w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="高亮效果"
                    
                />
            </picture>
        </a></p>
<h4 id="zsh-autosuggestions">zsh-autosuggestions</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 命令自动补全</span>
</span></span><span class="line"><span class="cl">git clone https://github.com/zsh-users/zsh-autosuggestions <span class="si">${</span><span class="nv">ZSH_CUSTOM</span><span class="k">:-</span><span class="p">~/.oh-my-zsh/custom</span><span class="si">}</span>/plugins/zsh-autosuggestions
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp" data-fancybox="gallery" data-src="/article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp" data-caption="补全效果">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/omz-terminal/image-20221207141800253_hu_ab07db22097dda02.webp 480w, /article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp 492w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="492"
                    height="188"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp"
                    srcset="/article/omz-terminal/image-20221207141800253_hu_ab07db22097dda02.webp 480w, /article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp 492w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="补全效果"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>如果感觉 <em>Tab键</em> 补全不方便，还可以自定义补全的快捷键。
比如设置逗号补全，只需要在 <code>~/.zshrc</code> 文件添加下面这句即可：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">bindkey &#39;,&#39; autosuggest-accept
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h4 id="zlua">z.lua</h4>
<p>z.lua 是一个快速路径切换工具，它会跟踪你在 shell 下访问过的路径，通过一套称为 Frecent 的机制（源自 FireFox），经过一段简短的学习之后，z.lua 会帮你跳转到所有匹配正则关键字的路径里 Frecent 值最高的那条路径去。</p>
<p>项目地址：<a href="https://github.com/skywind3000/z.lua" target="_blank" rel="noopener">GitHub z.lua</a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/skywind3000/z.lua <span class="si">${</span><span class="nv">ZSH_CUSTOM</span><span class="k">:-</span><span class="p">~/.oh-my-zsh/custom</span><span class="si">}</span>/plugins/z.lua
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/omz-terminal/image-20240122165106636_hu_7b8ff3231ffab131.webp" data-fancybox="gallery" data-src="/article/omz-terminal/image-20240122165106636_hu_7b8ff3231ffab131.webp" data-caption="z.lua">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/omz-terminal/image-20240122165106636_hu_61805fa6a7d44843.webp 480w, /article/omz-terminal/image-20240122165106636_hu_b0d0b79e9e0c014c.webp 720w, /article/omz-terminal/image-20240122165106636_hu_7b8ff3231ffab131.webp 748w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="748"
                    height="302"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/omz-terminal/image-20240122165106636_hu_b0d0b79e9e0c014c.webp"
                    srcset="/article/omz-terminal/image-20240122165106636_hu_61805fa6a7d44843.webp 480w, /article/omz-terminal/image-20240122165106636_hu_b0d0b79e9e0c014c.webp 720w, /article/omz-terminal/image-20240122165106636_hu_7b8ff3231ffab131.webp 748w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="z.lua"
                    
                />
            </picture>
        </a></p>
<h3 id="启用插件">启用插件</h3>
<p>在 <strong>.zshrc</strong> 文件中设置：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">plugins</span><span class="o">=(</span>git zsh-syntax-highlighting zsh-autosuggestions z.lua<span class="o">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>启用其他插件同理。</p>
<h2 id="配置生效">配置生效</h2>
<p>一种方法就是退出终端再重新打开，另一种更常用的方法就是使用我在前面所说的<code>source</code>命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> ~/.zshrc
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="感谢">感谢</h2>
<p><a href="https://ohmyz.sh/" target="_blank" rel="noopener">Oh My Zsh</a></p>
<p><a href="https://segmentfault.com/a/1190000018093021" target="_blank" rel="noopener">安装oh my zsh插件</a></p>
<p><a href="https://www.cnblogs.com/XiiX/p/14618799.html" target="_blank" rel="noopener">Linux 以非root用户安装zsh&amp;配置on my zsh</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>macOS环境下的轻量化Docker安装</title>
      <link>https://vccv.cc/article/docker-macos.html</link>
      <pubDate>Mon, 05 Dec 2022 14:49:31 +0000</pubDate>
      <guid>https://vccv.cc/article/docker-macos.html</guid>
      <description>如果你像博主一样不喜欢docker官方客户端的“臃肿”，或是单纯想要尝试一下新事物、折腾一下新方法，那么欢迎你打开本篇文章。由于博主使用的是macOS，所以仅有Mac下的一篇探索记录。如有遗漏错误，欢迎评论区批评指出。</description>
      <content:encoded><![CDATA[<blockquote>
<p>2024.01.26 更新：</p>
<p>最近了解到一个新的软件 <a href="https://orbstack.dev/" target="_blank" rel="noopener">OrbStack</a> 可以替代 Docker Desktop，官方介绍：OrbStack is the fast, light, and easy way to run Docker containers and Linux. Develop at lightspeed with our Docker Desktop alternative.</p>
<p>基本上不需要多余的配置就可以直接使用docker和创建Linux虚拟机（命令行版本），UI美观，操作比较无脑，占用也较小，值得尝试。</p>
<p><a href="/article/docker-macos/image-20240126130632366_hu_b25cd78da41ac489.webp" data-fancybox="gallery" data-src="/article/docker-macos/image-20240126130632366_hu_b25cd78da41ac489.webp" data-caption="OrbStack">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-macos/image-20240126130632366_hu_4a62ebe388ad7b09.webp 480w, /article/docker-macos/image-20240126130632366_hu_b751603efddc1e49.webp 720w, /article/docker-macos/image-20240126130632366_hu_8a415c9a9546ffca.webp 960w, /article/docker-macos/image-20240126130632366_hu_598a6dc15bf64c6c.webp 1440w, /article/docker-macos/image-20240126130632366_hu_b25cd78da41ac489.webp 1832w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1832"
                    height="1148"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-macos/image-20240126130632366_hu_b751603efddc1e49.webp"
                    srcset="/article/docker-macos/image-20240126130632366_hu_4a62ebe388ad7b09.webp 480w, /article/docker-macos/image-20240126130632366_hu_b751603efddc1e49.webp 720w, /article/docker-macos/image-20240126130632366_hu_8a415c9a9546ffca.webp 960w, /article/docker-macos/image-20240126130632366_hu_598a6dc15bf64c6c.webp 1440w, /article/docker-macos/image-20240126130632366_hu_b25cd78da41ac489.webp 1832w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="OrbStack"
                    
                />
            </picture>
        </a></p>
<p>最大的优点其实是Apple M系列芯片原生使用，并且可以模拟X86_64设备；要说缺点的话，就是不开源，企业用户付费，但个人用户免费。</p>
</blockquote>
<h2 id="前言">前言</h2>
<p>如果你像博主一样不喜欢docker官方客户端的“臃肿”，仅仅想要一个单独且纯粹的docker服务而不需要图形化界面；或是单纯想要尝试一下新事物、折腾一下新方法，那么欢迎你阅读本篇文章。</p>
<p>由于博主使用的是macOS，所以仅有Mac下的一篇探索记录。如有遗漏错误，欢迎评论区批评指出。</p>
<blockquote>
<p>本文电脑环境：</p>
<p>系统：macOS Ventura 13.0.1 (22A400)</p>
<p>处理器：Intel Core i5（不确定 <em>Apple M系列</em> 处理器是否通用）</p>
</blockquote>
<h2 id="准备工作">准备工作</h2>
<ul>
<li>
<p>安装<a href="https://brew.sh/" target="_blank" rel="noopener">Homebrew</a>。</p>
<p>Homebrew是macOS平台下使用最多的包管理器，这是它的<a href="https://docs.brew.sh/Installation" target="_blank" rel="noopener">官方安装教程</a>。但是通常来说，我们只需要在确保网络畅通的情况下输入以下命令即可：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/bin/bash -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="安装软件包">安装软件包</h2>
<ul>
<li>
<p>使用Homebrew安装docker。</p>
<p>安装最基础的docker服务，也很简单，一句命令搞定：</p>
<p>切记不要使用 <code>brew install docker --cask</code> 命令，这将安装docker在macOS平台下的图形化软件！！！</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install docker
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>使用Homebrew安装Colima</p>
<p><a href="https://github.com/abiosoft/colima" target="_blank" rel="noopener">Colima</a> 的名字取自 Container on Lima。<a href="https://github.com/lima-vm/lima" target="_blank" rel="noopener">Lima</a> 是一个虚拟机工具，可以实现自动的文件共享、端口转发以及 containerd。</p>
<p>Colima 实际上是通过 Lima 启动了名为 <strong>colima</strong> 的虚拟机。它帮我们简化了使用流程，当然也少了一些可定制性。如果你有兴趣，当然也可以使用 Lima 自己手动来完成这一过程，可定制性更高，但更复杂。</p>
<p>安装同样很简单，也是一句命令搞定：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install colima
</span></span></code></pre></td></tr></table>
</div>
</div><p>这个下载时间应该会长很多，是正常情况。通过命令查询可以看到Colima的依赖就比较多。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ brew deps colima
</span></span><span class="line"><span class="cl">bdw-gc
</span></span><span class="line"><span class="cl">ca-certificates
</span></span><span class="line"><span class="cl">capstone
</span></span><span class="line"><span class="cl">gettext
</span></span><span class="line"><span class="cl">glib
</span></span><span class="line"><span class="cl">gmp
</span></span><span class="line"><span class="cl">gnutls
</span></span><span class="line"><span class="cl">guile
</span></span><span class="line"><span class="cl">jpeg-turbo
</span></span><span class="line"><span class="cl">libevent
</span></span><span class="line"><span class="cl">libidn2
</span></span><span class="line"><span class="cl">libnghttp2
</span></span><span class="line"><span class="cl">libpng
</span></span><span class="line"><span class="cl">libslirp
</span></span><span class="line"><span class="cl">libssh
</span></span><span class="line"><span class="cl">libtasn1
</span></span><span class="line"><span class="cl">libtool
</span></span><span class="line"><span class="cl">libunistring
</span></span><span class="line"><span class="cl">libusb
</span></span><span class="line"><span class="cl">lima
</span></span><span class="line"><span class="cl">lz4
</span></span><span class="line"><span class="cl">lzo
</span></span><span class="line"><span class="cl">m4
</span></span><span class="line"><span class="cl">ncurses
</span></span><span class="line"><span class="cl">nettle
</span></span><span class="line"><span class="cl">openssl@1.1
</span></span><span class="line"><span class="cl">p11-kit
</span></span><span class="line"><span class="cl">pcre2
</span></span><span class="line"><span class="cl">pixman
</span></span><span class="line"><span class="cl">pkg-config
</span></span><span class="line"><span class="cl">qemu
</span></span><span class="line"><span class="cl">readline
</span></span><span class="line"><span class="cl">snappy
</span></span><span class="line"><span class="cl">unbound
</span></span><span class="line"><span class="cl">vde
</span></span><span class="line"><span class="cl">xz
</span></span><span class="line"><span class="cl">zstd
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="启动colima">启动Colima</h2>
<p>安装官方文档介绍，创建docker运行环境只需要一句最简单的命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">colima start
</span></span></code></pre></td></tr></table>
</div>
</div><p>或许这也是作者专门对docker做了流程优化，这也是我推荐使用colima的原因，足够简单。</p>
<p><a href="/article/docker-macos/image-20221205160750680_hu_c85422a993811e16.webp" data-fancybox="gallery" data-src="/article/docker-macos/image-20221205160750680_hu_c85422a993811e16.webp" data-caption="Colima运行">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-macos/image-20221205160750680_hu_e3ed76cda5baa397.webp 480w, /article/docker-macos/image-20221205160750680_hu_ce292810ed12db23.webp 720w, /article/docker-macos/image-20221205160750680_hu_cbea94180668f26f.webp 960w, /article/docker-macos/image-20221205160750680_hu_c85422a993811e16.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="338"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-macos/image-20221205160750680_hu_ce292810ed12db23.webp"
                    srcset="/article/docker-macos/image-20221205160750680_hu_e3ed76cda5baa397.webp 480w, /article/docker-macos/image-20221205160750680_hu_ce292810ed12db23.webp 720w, /article/docker-macos/image-20221205160750680_hu_cbea94180668f26f.webp 960w, /article/docker-macos/image-20221205160750680_hu_c85422a993811e16.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Colima运行"
                    
                />
            </picture>
        </a></p>
<h2 id="开机自启">开机自启</h2>
<blockquote>
<p>2023.12.20 更新：</p>
<p>根据评论区老哥反馈，Colima已经支持开机自启。</p>
<p>方法也很简单，由于我们是使用brew安装的colima，直接使用<code>brew service</code>接管即可。</p>
<p><a href="/article/docker-macos/image-20231220215607833_hu_6f95cdf5a48ccc0e.webp" data-fancybox="gallery" data-src="/article/docker-macos/image-20231220215607833_hu_6f95cdf5a48ccc0e.webp" data-caption="开机自启">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-macos/image-20231220215607833_hu_186dfc3bfe614db5.webp 480w, /article/docker-macos/image-20231220215607833_hu_3a2328186c2a696c.webp 720w, /article/docker-macos/image-20231220215607833_hu_6f95cdf5a48ccc0e.webp 958w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="958"
                    height="172"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-macos/image-20231220215607833_hu_3a2328186c2a696c.webp"
                    srcset="/article/docker-macos/image-20231220215607833_hu_186dfc3bfe614db5.webp 480w, /article/docker-macos/image-20231220215607833_hu_3a2328186c2a696c.webp 720w, /article/docker-macos/image-20231220215607833_hu_6f95cdf5a48ccc0e.webp 958w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="开机自启"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew services start colima
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果你是使用其他方式进行安装，请善用搜索引擎。或者安装评论区老哥的提示，添加<code>–foreground</code>参数进行设置（<em>未测试</em>）。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">colima start –foreground
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<p><del>虽然 Colima 到目前为止仍没有提供这样的功能，但<a href="https://github.com/abiosoft/colima/issues/96" target="_blank" rel="noopener">正在开发中</a>。</del></p>
<p><del>另外，对于简单的单容器docker使用，我们也可以自己创建shell脚本并设置启动项来达到一样的效果：</del></p>
<ul>
<li>
<p><del>创建shell脚本：</del></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch colima.sh
</span></span><span class="line"><span class="cl">chmod +x colima.sh
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><del>修改脚本内容：</del></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">vim colima.sh
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 将启动命令写到colima.sh中即可</span>
</span></span><span class="line"><span class="cl">colima start
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><del>添加到登录项：</del></p>
<p><del><a href="/article/docker-macos/image-20221213120548391_hu_72f0c58ec4ebc493.webp" data-fancybox="gallery" data-src="/article/docker-macos/image-20221213120548391_hu_72f0c58ec4ebc493.webp" data-caption="登录项">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-macos/image-20221213120548391_hu_d55e12072a00333b.webp 480w, /article/docker-macos/image-20221213120548391_hu_b967e8e3b153bd3c.webp 720w, /article/docker-macos/image-20221213120548391_hu_ab749c64f61848b8.webp 960w, /article/docker-macos/image-20221213120548391_hu_72f0c58ec4ebc493.webp 990w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="990"
                    height="550"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-macos/image-20221213120548391_hu_b967e8e3b153bd3c.webp"
                    srcset="/article/docker-macos/image-20221213120548391_hu_d55e12072a00333b.webp 480w, /article/docker-macos/image-20221213120548391_hu_b967e8e3b153bd3c.webp 720w, /article/docker-macos/image-20221213120548391_hu_ab749c64f61848b8.webp 960w, /article/docker-macos/image-20221213120548391_hu_72f0c58ec4ebc493.webp 990w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="登录项"
                    
                />
            </picture>
        </a></del></p>
</li>
<li>
<p><del>设置默认打开方式，设置成你的终端程序：</del></p>
<p><del><a href="/article/docker-macos/image-20221213121901639_hu_c7b53f85fb758a35.webp" data-fancybox="gallery" data-src="/article/docker-macos/image-20221213121901639_hu_c7b53f85fb758a35.webp" data-caption="默认iterm2打开">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-macos/image-20221213121901639_hu_b9784d0adc4ae390.webp 480w, /article/docker-macos/image-20221213121901639_hu_6548563fce583dd0.webp 720w, /article/docker-macos/image-20221213121901639_hu_37e806338b1d0bc7.webp 960w, /article/docker-macos/image-20221213121901639_hu_d8a7ae63a5208d35.webp 1440w, /article/docker-macos/image-20221213121901639_hu_c7b53f85fb758a35.webp 1850w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1850"
                    height="972"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-macos/image-20221213121901639_hu_6548563fce583dd0.webp"
                    srcset="/article/docker-macos/image-20221213121901639_hu_b9784d0adc4ae390.webp 480w, /article/docker-macos/image-20221213121901639_hu_6548563fce583dd0.webp 720w, /article/docker-macos/image-20221213121901639_hu_37e806338b1d0bc7.webp 960w, /article/docker-macos/image-20221213121901639_hu_d8a7ae63a5208d35.webp 1440w, /article/docker-macos/image-20221213121901639_hu_c7b53f85fb758a35.webp 1850w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="默认iterm2打开"
                    
                />
            </picture>
        </a></del></p>
</li>
</ul>
<h2 id="享受">享受</h2>
<p>就是如此简单，docker服务就运行起来了。输入 <code>docker ps -a</code> 简单测试一下就知道运行成功没有。如果仍有错误，请继续看下去。</p>
<p><a href="/article/docker-macos/image-20221205160832483_hu_7f666cfe506ee63f.webp" data-fancybox="gallery" data-src="/article/docker-macos/image-20221205160832483_hu_7f666cfe506ee63f.webp" data-caption="docker运行正常">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-macos/image-20221205160832483_hu_8c17874b518583bf.webp 480w, /article/docker-macos/image-20221205160832483_hu_15e72e63a2f6d581.webp 720w, /article/docker-macos/image-20221205160832483_hu_490a2af54ecb5cfb.webp 960w, /article/docker-macos/image-20221205160832483_hu_7f666cfe506ee63f.webp 1110w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1110"
                    height="150"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-macos/image-20221205160832483_hu_15e72e63a2f6d581.webp"
                    srcset="/article/docker-macos/image-20221205160832483_hu_8c17874b518583bf.webp 480w, /article/docker-macos/image-20221205160832483_hu_15e72e63a2f6d581.webp 720w, /article/docker-macos/image-20221205160832483_hu_490a2af54ecb5cfb.webp 960w, /article/docker-macos/image-20221205160832483_hu_7f666cfe506ee63f.webp 1110w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="docker运行正常"
                    
                />
            </picture>
        </a></p>
<h2 id="排错">排错</h2>
<p><a href="/article/docker-macos/image-20221205153421353_hu_64e1642e091ed315.webp" data-fancybox="gallery" data-src="/article/docker-macos/image-20221205153421353_hu_64e1642e091ed315.webp" data-caption="docker无服务">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-macos/image-20221205153421353_hu_aaeffb07028a25b5.webp 480w, /article/docker-macos/image-20221205153421353_hu_ccbf2adf077fb7d9.webp 720w, /article/docker-macos/image-20221205153421353_hu_cac7d65a031c6088.webp 960w, /article/docker-macos/image-20221205153421353_hu_64e1642e091ed315.webp 1396w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1396"
                    height="118"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-macos/image-20221205153421353_hu_ccbf2adf077fb7d9.webp"
                    srcset="/article/docker-macos/image-20221205153421353_hu_aaeffb07028a25b5.webp 480w, /article/docker-macos/image-20221205153421353_hu_ccbf2adf077fb7d9.webp 720w, /article/docker-macos/image-20221205153421353_hu_cac7d65a031c6088.webp 960w, /article/docker-macos/image-20221205153421353_hu_64e1642e091ed315.webp 1396w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="docker无服务"
                    
                />
            </picture>
        </a></p>
<p>图中表示docker服务并没有运行起来，这是colima配置有问题。可以尝试重新安装Colima，或者重新运行 <code>colima start</code> 检查是否解决。</p>
<h2 id="额外">额外</h2>
<ul>
<li>
<p>可以进一步安装 <strong>docker-compose</strong> 使用。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install docker-compose
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>如果要运行多个容器，可以对Colima创建的容器进行配置修改：</p>
<p>Colima 的默认资源配置是 2 CPU / 2 G 内存，某些情况下会不够用。比如用 docker-compose 启动三个 mysql 实例，就会发生至少有一个实例无法正常启动的情况。</p>
<p>这时可以用 <code>-c</code> 及 <code>-m</code> 的启动参数，或是 <code>colima start --edit</code> 修改默认配置。</p>
</li>
</ul>
<h2 id="感谢">感谢</h2>
<p><a href="https://github.com/abiosoft/colima" target="_blank" rel="noopener">Colima</a></p>
<p><a href="https://github.com/lima-vm/lima" target="_blank" rel="noopener">Lima</a></p>
<p><a href="https://www.docker.com/" target="_blank" rel="noopener">Docker</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Conda安装R内核的Notebook</title>
      <link>https://vccv.cc/article/conda-r-jupyter.html</link>
      <pubDate>Mon, 10 Oct 2022 17:27:01 +0000</pubDate>
      <guid>https://vccv.cc/article/conda-r-jupyter.html</guid>
      <description>由于博主多次在Linux远程服务器上使用conda配置r内核的jupyter notebook，但每次时间一久就会忘记某些步骤（最主要是一样的坑每次都会踩出不一样的问题）。在综合网上相关教程以及自己的亲身经验后，总结出一份安装指北，供大家以及将来的我参考。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>由于博主多次在Linux远程服务器上使用conda配置r内核的jupyter notebook，但每次时间一久就会忘记某些步骤（最主要是一样的坑每次都会踩出不一样的问题）。</p>
<p>在综合网上相关教程以及自己的亲身经验后，总结出一份关于 <strong>Conda</strong>、<strong>R</strong>、<strong>Jupyter</strong> <strong>Notebook</strong> 的“<em>安装指北</em>”，供大家以及将来的我参考。</p>
<h2 id="指北">指北</h2>
<h3 id="安装conda">安装Conda</h3>
<blockquote>
<p>首先介绍一下Conda、Anaconda以及两者之间的一些联系：</p>
<p><a href="https://conda.io/" target="_blank" rel="noopener">Conda</a>是个包管理器，可以支持二进制包，所以不需要安装时从源码编译了，而且也可以装原生库。但是，一些 pip 里的 Python 库在 conda 里找不到。</p>
<ul>
<li><a href="https://anaconda.org/anaconda/" target="_blank" rel="noopener">Anaconda</a>是用Conda管理的Python科学计算发行版。</li>
<li><a href="https://conda-forge.org/" target="_blank" rel="noopener">Conda Forge</a>是另一个Python发行版，要比Anaconda的包更丰富。但这里有个坑就是Conda Forge和Anaconda<strong>并不完全兼容</strong>，如果你有一个项目同时用到Anaconda和Conda Forge里的包，有可能会挂。</li>
</ul>
</blockquote>
<p><del>通常我使用的服务器都是事先安装好了Anaconda的，</del></p>
<p><del>下面推荐一下Anaconda官方出品的 <strong><a href="https://docs.anaconda.com/anaconda/install/linux/" target="_blank" rel="noopener">Linux系统安装Anaconda</a></strong> 的文档，有很详细的步骤说明以及命令解释。</del></p>
<p>2022.10.17 更新Linux-Centos7下安装Anaconda流程：</p>
<p>由于国内的特殊环境，还是推荐直接在<a href="https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&amp;O=D" target="_blank" rel="noopener">清华大学镜像源</a>等国内源下载Anaconda安装脚本，通常选择<strong>x86_64版本</strong>：</p>
<p><a href="/article/conda-r-jupyter/image-20221017223737389_hu_96426011afab3f0e.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20221017223737389_hu_96426011afab3f0e.webp" data-caption="镜像源下载脚本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20221017223737389_hu_67526115fbcf0afe.webp 480w, /article/conda-r-jupyter/image-20221017223737389_hu_d0411eba4621dc5e.webp 720w, /article/conda-r-jupyter/image-20221017223737389_hu_6461f068d7524d47.webp 960w, /article/conda-r-jupyter/image-20221017223737389_hu_cb8bfdc0e2d080ae.webp 1440w, /article/conda-r-jupyter/image-20221017223737389_hu_96426011afab3f0e.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2760"
                    height="1572"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20221017223737389_hu_d0411eba4621dc5e.webp"
                    srcset="/article/conda-r-jupyter/image-20221017223737389_hu_67526115fbcf0afe.webp 480w, /article/conda-r-jupyter/image-20221017223737389_hu_d0411eba4621dc5e.webp 720w, /article/conda-r-jupyter/image-20221017223737389_hu_6461f068d7524d47.webp 960w, /article/conda-r-jupyter/image-20221017223737389_hu_cb8bfdc0e2d080ae.webp 1440w, /article/conda-r-jupyter/image-20221017223737389_hu_96426011afab3f0e.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="镜像源下载脚本"
                    
                />
            </picture>
        </a></p>
<p>Chrome可以右键选择复制文件链接地址，然后在centos使用wget下载：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 下载脚本</span>
</span></span><span class="line"><span class="cl">wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2022.05-Linux-x86_64.sh
</span></span><span class="line"><span class="cl"><span class="c1"># 如果提示没有wget 使用yum安装</span>
</span></span><span class="line"><span class="cl">yum install wget
</span></span><span class="line"><span class="cl"><span class="c1"># 执行安装脚本 脚本名自行更改</span>
</span></span><span class="line"><span class="cl">bash Anaconda3-2022.05-Linux-x86_64.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>下面是我自己遇到的一些选项，记录一下。请按照自己的情况，按照脚本提示输入：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 按照提示输入ENTER（回车）</span>
</span></span><span class="line"><span class="cl">Welcome to Anaconda3 2022.05
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">In order to <span class="k">continue</span> the installation process, please review the license
</span></span><span class="line"><span class="cl">agreement.
</span></span><span class="line"><span class="cl">Please, press ENTER to <span class="k">continue</span>
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; ENTER
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 按照提示输入yes</span>
</span></span><span class="line"><span class="cl">Do you accept the license terms? <span class="o">[</span>yes<span class="p">|</span>no<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>no<span class="o">]</span> &gt;&gt;&gt;
</span></span><span class="line"><span class="cl">Please answer <span class="s1">&#39;yes&#39;</span> or <span class="s1">&#39;no&#39;</span>:<span class="s1">&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">&gt;&gt;&gt; yes
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1"># 按照提示输入ENTER（回车）
</span></span></span><span class="line"><span class="cl"><span class="s1"># Anaconda3 will now be installed into this location:
</span></span></span><span class="line"><span class="cl"><span class="s1">/root/anaconda3
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">  - Press ENTER to confirm the location
</span></span></span><span class="line"><span class="cl"><span class="s1">  - Press CTRL-C to abort the installation
</span></span></span><span class="line"><span class="cl"><span class="s1">  - Or specify a different location below
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">[/root/anaconda3] &gt;&gt;&gt; ENTER
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1"># conda初始化 默认no 建议输入yes
</span></span></span><span class="line"><span class="cl"><span class="s1"># 如果选择了no 则需要自行配置环境变量（百度关键词 anaconda 环境变量）
</span></span></span><span class="line"><span class="cl"><span class="s1">installation finished.
</span></span></span><span class="line"><span class="cl"><span class="s1">Do you wish the installer to initialize Anaconda3
</span></span></span><span class="line"><span class="cl"><span class="s1">by running conda init? [yes|no]
</span></span></span><span class="line"><span class="cl"><span class="s1">[no] &gt;&gt;&gt; yes
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1"># 下面是一些提示 简单翻译了一下
</span></span></span><span class="line"><span class="cl"><span class="s1"># 要让conda生效 需要关闭再重新打开当前shell（重新连接ssh）
</span></span></span><span class="line"><span class="cl"><span class="s1"># 如果不需要启动时激活conda基础环境 输入 conda config --set auto_activate_base false
</span></span></span><span class="line"><span class="cl"><span class="s1">==&gt; For changes to take effect, close and re-open your current shell. &lt;==
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">If you&#39;</span>d prefer that conda<span class="err">&#39;</span>s base environment not be activated on startup,
</span></span><span class="line"><span class="cl">   <span class="nb">set</span> the auto_activate_base parameter to false:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">conda config --set auto_activate_base <span class="nb">false</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Anaconda就安装完成了，顺便推荐添加国内源：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 添加中科大源</span>
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/free/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/msys2/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/bioconda/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/menpo/
</span></span><span class="line"><span class="cl"><span class="c1"># 下载时显示源地址</span>
</span></span><span class="line"><span class="cl">conda config --set show_channel_urls yes
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/conda-r-jupyter/image-20221017233347844_hu_3fda9d92640c4dac.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20221017233347844_hu_3fda9d92640c4dac.webp" data-caption="更新国内源">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20221017233347844_hu_db5a4a88af66a656.webp 480w, /article/conda-r-jupyter/image-20221017233347844_hu_ba7b8f85f9f0237c.webp 720w, /article/conda-r-jupyter/image-20221017233347844_hu_803415409bf7b46f.webp 960w, /article/conda-r-jupyter/image-20221017233347844_hu_3fda9d92640c4dac.webp 1052w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1052"
                    height="280"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20221017233347844_hu_ba7b8f85f9f0237c.webp"
                    srcset="/article/conda-r-jupyter/image-20221017233347844_hu_db5a4a88af66a656.webp 480w, /article/conda-r-jupyter/image-20221017233347844_hu_ba7b8f85f9f0237c.webp 720w, /article/conda-r-jupyter/image-20221017233347844_hu_803415409bf7b46f.webp 960w, /article/conda-r-jupyter/image-20221017233347844_hu_3fda9d92640c4dac.webp 1052w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="更新国内源"
                    
                />
            </picture>
        </a></p>
<h3 id="创建环境">创建环境</h3>
<p>本人是直接创建一个新的conda环境来避免依赖冲突，最省事。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 查看已有的conda环境</span>
</span></span><span class="line"><span class="cl">conda env list
</span></span><span class="line"><span class="cl"><span class="c1"># 根据名字创建新环境</span>
</span></span><span class="line"><span class="cl"><span class="c1"># your_new_name_to_conda 替换成 你希望的环境名称</span>
</span></span><span class="line"><span class="cl">conda create -n your_new_name_to_conda
</span></span><span class="line"><span class="cl"><span class="c1"># 激活新环境</span>
</span></span><span class="line"><span class="cl">conda activate your_new_name_to_conda
</span></span><span class="line"><span class="cl"><span class="c1"># 查看已安装的依赖包</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 新环境当然是没有任何东西的</span>
</span></span><span class="line"><span class="cl">conda list
</span></span><span class="line"><span class="cl"><span class="c1"># 退出新环境</span>
</span></span><span class="line"><span class="cl">conda deactivate
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/conda-r-jupyter/image-20221010174813001_hu_a591c99a2b1f6762.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20221010174813001_hu_a591c99a2b1f6762.webp" data-caption="命令行conda">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20221010174813001_hu_3152919ce551edc.webp 480w, /article/conda-r-jupyter/image-20221010174813001_hu_7019c8a703e3466d.webp 720w, /article/conda-r-jupyter/image-20221010174813001_hu_bdef54328209d3a6.webp 960w, /article/conda-r-jupyter/image-20221010174813001_hu_153412c75d27f165.webp 1440w, /article/conda-r-jupyter/image-20221010174813001_hu_a591c99a2b1f6762.webp 2088w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2088"
                    height="1236"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20221010174813001_hu_7019c8a703e3466d.webp"
                    srcset="/article/conda-r-jupyter/image-20221010174813001_hu_3152919ce551edc.webp 480w, /article/conda-r-jupyter/image-20221010174813001_hu_7019c8a703e3466d.webp 720w, /article/conda-r-jupyter/image-20221010174813001_hu_bdef54328209d3a6.webp 960w, /article/conda-r-jupyter/image-20221010174813001_hu_153412c75d27f165.webp 1440w, /article/conda-r-jupyter/image-20221010174813001_hu_a591c99a2b1f6762.webp 2088w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="命令行conda"
                    
                />
            </picture>
        </a></p>
<h3 id="安装r">安装R</h3>
<p>这里需要注意<strong>不能</strong>直接使用 <code>conda install r</code> 来安装R。</p>
<p>直接输入上面的命令的话，安装的将是3.6版本（好像是）的R，此版本太老了，许多R的包都不能使用。截止2022.10.10，R的conda最新版本是4.2.1。</p>
<p>下面将讲解如何安装最新版本的R（4.2.1）。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># conda通过conda-forge安装r-base</span>
</span></span><span class="line"><span class="cl">conda install -c conda-forge r-base
</span></span></code></pre></td></tr></table>
</div>
</div><p>conda-forge在文章开头也介绍了，我感觉可以理解成Linux里面的一个发行版？？？</p>
<p>在确认安装之前（也就是输入y之前），可以事先确定一下r-base的版本是不是4版本以上（目前是4.2.1）。</p>
<p><a href="/article/conda-r-jupyter/image-20221010182224588_hu_979394f244082aa1.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20221010182224588_hu_979394f244082aa1.webp" data-caption="4.2.1版本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20221010182224588_hu_1749abbe2a720ffd.webp 480w, /article/conda-r-jupyter/image-20221010182224588_hu_ac14736517963e83.webp 720w, /article/conda-r-jupyter/image-20221010182224588_hu_5eab3cb009e79080.webp 960w, /article/conda-r-jupyter/image-20221010182224588_hu_fb6b8f7bb19ca795.webp 1440w, /article/conda-r-jupyter/image-20221010182224588_hu_979394f244082aa1.webp 1754w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1754"
                    height="928"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20221010182224588_hu_ac14736517963e83.webp"
                    srcset="/article/conda-r-jupyter/image-20221010182224588_hu_1749abbe2a720ffd.webp 480w, /article/conda-r-jupyter/image-20221010182224588_hu_ac14736517963e83.webp 720w, /article/conda-r-jupyter/image-20221010182224588_hu_5eab3cb009e79080.webp 960w, /article/conda-r-jupyter/image-20221010182224588_hu_fb6b8f7bb19ca795.webp 1440w, /article/conda-r-jupyter/image-20221010182224588_hu_979394f244082aa1.webp 1754w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="4.2.1版本"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>2023.7.18 更新：</p>
<p>如果使用上述命令指定通过conda-forge安装r-base，但最终安装版本仍然不是最新版本（截止本文修改时最新版本是4.3.1），而是3.x.x老版本，可以尝试指定r-base版本号进行安装。</p>
<p><a href="/article/conda-r-jupyter/image-20230718164847016_hu_9d2bf40c798986d4.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20230718164847016_hu_9d2bf40c798986d4.webp" data-caption="查看最新版本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20230718164847016_hu_b23138732df9909.webp 480w, /article/conda-r-jupyter/image-20230718164847016_hu_c871f3e4897d9d98.webp 720w, /article/conda-r-jupyter/image-20230718164847016_hu_9d2bf40c798986d4.webp 932w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="932"
                    height="342"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20230718164847016_hu_c871f3e4897d9d98.webp"
                    srcset="/article/conda-r-jupyter/image-20230718164847016_hu_b23138732df9909.webp 480w, /article/conda-r-jupyter/image-20230718164847016_hu_c871f3e4897d9d98.webp 720w, /article/conda-r-jupyter/image-20230718164847016_hu_9d2bf40c798986d4.webp 932w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="查看最新版本"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 首先通过搜索r-base包版本找到最新</span>
</span></span><span class="line"><span class="cl">conda search -c conda-forge r-base
</span></span><span class="line"><span class="cl"><span class="c1"># 划到最下面可以看到最新的版本号</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 然后指定版本号安装（这里以4.3.1为例）</span>
</span></span><span class="line"><span class="cl">conda install -c conda-forge r-base<span class="o">=</span>4.3.1
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h3 id="安装r内核和jupyter">安装R内核和Jupyter</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 指定使用默认源安装</span>
</span></span><span class="line"><span class="cl"><span class="c1"># r-irkernel是jupyter notebook的r内核</span>
</span></span><span class="line"><span class="cl"><span class="c1"># jupyter包含了jupyter notebook</span>
</span></span><span class="line"><span class="cl">conda install -c defaults r-irkernel jupyter
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>注意：</p>
<p>这里不要使用conda-forge安装r-irkernel和jupyter。</p>
<p>前面也提到，Conda Forge和Anaconda<strong>并不完全兼容</strong>。亲自尝试过使用<code>conda install -c conda-forge r-irkernel jupyter</code>命令安装，jupyter notebook无法正常启动。这时只需要卸载再重新安装即可：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 卸载</span>
</span></span><span class="line"><span class="cl">conda uninstall r-irkernel jupyter
</span></span><span class="line"><span class="cl"><span class="c1"># 安装</span>
</span></span><span class="line"><span class="cl">conda install -c defaults r-irkernel jupyter
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h3 id="启动notebook">启动Notebook</h3>
<p>如果前面一切顺利的话，这里就能够正常启动Jupyter Notebook了，也可以创建R的notebook了；</p>
<p>如果还不能正常启动，请继续往下阅读**【异常处理】**。</p>
<p><a href="/article/conda-r-jupyter/image-20221010201826507_hu_2bb88cefde2f1bc.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20221010201826507_hu_2bb88cefde2f1bc.webp" data-caption="正常运行Notebook">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20221010201826507_hu_dd066c8618eda387.webp 480w, /article/conda-r-jupyter/image-20221010201826507_hu_70de8bb93e791e09.webp 720w, /article/conda-r-jupyter/image-20221010201826507_hu_71616f7a6d47b064.webp 960w, /article/conda-r-jupyter/image-20221010201826507_hu_5d9f5860f0d5079c.webp 1440w, /article/conda-r-jupyter/image-20221010201826507_hu_2bb88cefde2f1bc.webp 2444w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2444"
                    height="598"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20221010201826507_hu_70de8bb93e791e09.webp"
                    srcset="/article/conda-r-jupyter/image-20221010201826507_hu_dd066c8618eda387.webp 480w, /article/conda-r-jupyter/image-20221010201826507_hu_70de8bb93e791e09.webp 720w, /article/conda-r-jupyter/image-20221010201826507_hu_71616f7a6d47b064.webp 960w, /article/conda-r-jupyter/image-20221010201826507_hu_5d9f5860f0d5079c.webp 1440w, /article/conda-r-jupyter/image-20221010201826507_hu_2bb88cefde2f1bc.webp 2444w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="正常运行Notebook"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 启动Jupyter Notebook</span>
</span></span><span class="line"><span class="cl">jupyter notebook
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="异常处理">异常处理</h3>
<h4 id="模块缺失">模块缺失</h4>
<p>如果在启动notebook时提示 <em><strong>ModuleNotFoundError: No module named &lsquo;zmq.backend.cffi._cffi&rsquo;</strong></em> ，如下图类似的情况：</p>
<p><a href="/article/conda-r-jupyter/image-20221018152019887_hu_e4e6e1f4dd061cfa.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20221018152019887_hu_e4e6e1f4dd061cfa.webp" data-caption="模块缺失">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20221018152019887_hu_94bc8bb977b9b635.webp 480w, /article/conda-r-jupyter/image-20221018152019887_hu_5f6b2dabbf598904.webp 720w, /article/conda-r-jupyter/image-20221018152019887_hu_215fca54b3aab7c7.webp 960w, /article/conda-r-jupyter/image-20221018152019887_hu_b17897ea57254799.webp 1440w, /article/conda-r-jupyter/image-20221018152019887_hu_e4e6e1f4dd061cfa.webp 2746w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2746"
                    height="850"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20221018152019887_hu_5f6b2dabbf598904.webp"
                    srcset="/article/conda-r-jupyter/image-20221018152019887_hu_94bc8bb977b9b635.webp 480w, /article/conda-r-jupyter/image-20221018152019887_hu_5f6b2dabbf598904.webp 720w, /article/conda-r-jupyter/image-20221018152019887_hu_215fca54b3aab7c7.webp 960w, /article/conda-r-jupyter/image-20221018152019887_hu_b17897ea57254799.webp 1440w, /article/conda-r-jupyter/image-20221018152019887_hu_e4e6e1f4dd061cfa.webp 2746w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="模块缺失"
                    
                />
            </picture>
        </a></p>
<p>解决方法可以参照<a href="https://github.com/jupyter/notebook/issues/3435#issuecomment-398549304" target="_blank" rel="noopener">官方仓库下的一个issue</a>，使用pip卸载相关模块再重新安装：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 使用pip而不是conda管理pyzmq包</span>
</span></span><span class="line"><span class="cl">pip uninstall pyzmq
</span></span><span class="line"><span class="cl">pip install pyzmq
</span></span></code></pre></td></tr></table>
</div>
</div><p>亲测有效。</p>
<blockquote>
<p>出现类似的 <em>ModuleNotFoundError</em>（模块找不到）问题都可以尝试用以上方法，使用pip替代conda管理那些python包，先卸载再重新安装。</p>
<p>主要是要找到那个准确的包名，可以尝试在<a href="https://pypi.org/" target="_blank" rel="noopener">pypi</a>搜索关键字。</p>
</blockquote>
<h4 id="端口占有">端口占有</h4>
<p>由于是实验室多人共用的服务器，notebook默认的8888端口也被占用了。下面是解决方法：</p>
<blockquote>
<p>2023.10.31 更新</p>
<p>最近notebook升级到了<em>7</em>版本，下面的修改方法会被逐渐弃用：</p>
<p><a href="/article/conda-r-jupyter/image-20231031123709807_hu_8e917882ee191ce5.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20231031123709807_hu_8e917882ee191ce5.webp" data-caption="notebook7 改动">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20231031123709807_hu_bc8c32e62af4af39.webp 480w, /article/conda-r-jupyter/image-20231031123709807_hu_c0c7b61d7e397f6b.webp 720w, /article/conda-r-jupyter/image-20231031123709807_hu_3f8b4f7c4a02e89c.webp 960w, /article/conda-r-jupyter/image-20231031123709807_hu_3a690f033e752e02.webp 1440w, /article/conda-r-jupyter/image-20231031123709807_hu_8e917882ee191ce5.webp 2310w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2310"
                    height="456"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20231031123709807_hu_c0c7b61d7e397f6b.webp"
                    srcset="/article/conda-r-jupyter/image-20231031123709807_hu_bc8c32e62af4af39.webp 480w, /article/conda-r-jupyter/image-20231031123709807_hu_c0c7b61d7e397f6b.webp 720w, /article/conda-r-jupyter/image-20231031123709807_hu_3f8b4f7c4a02e89c.webp 960w, /article/conda-r-jupyter/image-20231031123709807_hu_3a690f033e752e02.webp 1440w, /article/conda-r-jupyter/image-20231031123709807_hu_8e917882ee191ce5.webp 2310w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="notebook7 改动"
                    
                />
            </picture>
        </a></p>
<p>截止更新日期，<em>修改password</em>的原代码已经不能使用，请 notebook 7 版本使用如下方法修改密码：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ipython
</span></span><span class="line"><span class="cl">Python 3.11.5 <span class="o">(</span>main, Sep <span class="m">11</span> 2023, 13:54:46<span class="o">)</span> <span class="o">[</span>GCC 11.2.0<span class="o">]</span>
</span></span><span class="line"><span class="cl">Type <span class="s1">&#39;copyright&#39;</span>, <span class="s1">&#39;credits&#39;</span> or <span class="s1">&#39;license&#39;</span> <span class="k">for</span> more information
</span></span><span class="line"><span class="cl">IPython 8.15.0 -- An enhanced Interactive Python. Type <span class="s1">&#39;?&#39;</span> <span class="k">for</span> help.
</span></span><span class="line"><span class="cl"><span class="c1"># 这里导入有改动</span>
</span></span><span class="line"><span class="cl">In <span class="o">[</span>1<span class="o">]</span>: from jupyter_server.auth import passwd
</span></span><span class="line"><span class="cl">In <span class="o">[</span>2<span class="o">]</span>: passwd<span class="o">()</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>或者直接命令行输入<code>jupyter server password</code>进行设置：</p>
<p><a href="/article/conda-r-jupyter/image-20231031124411574_hu_2974c1e763d7c2cd.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20231031124411574_hu_2974c1e763d7c2cd.webp" data-caption="设置密码">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20231031124411574_hu_7296ec24816d4324.webp 480w, /article/conda-r-jupyter/image-20231031124411574_hu_77ae5b61652cc65a.webp 720w, /article/conda-r-jupyter/image-20231031124411574_hu_8b358398b419a859.webp 960w, /article/conda-r-jupyter/image-20231031124411574_hu_1ef77f7a56860c99.webp 1440w, /article/conda-r-jupyter/image-20231031124411574_hu_2974c1e763d7c2cd.webp 1564w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1564"
                    height="188"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20231031124411574_hu_77ae5b61652cc65a.webp"
                    srcset="/article/conda-r-jupyter/image-20231031124411574_hu_7296ec24816d4324.webp 480w, /article/conda-r-jupyter/image-20231031124411574_hu_77ae5b61652cc65a.webp 720w, /article/conda-r-jupyter/image-20231031124411574_hu_8b358398b419a859.webp 960w, /article/conda-r-jupyter/image-20231031124411574_hu_1ef77f7a56860c99.webp 1440w, /article/conda-r-jupyter/image-20231031124411574_hu_2974c1e763d7c2cd.webp 1564w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="设置密码"
                    
                />
            </picture>
        </a></p>
</blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ipython
</span></span><span class="line"><span class="cl"><span class="c1"># 进入python控制台</span>
</span></span><span class="line"><span class="cl">Python 3.7.13 <span class="o">(</span>default, Mar <span class="m">29</span> 2022, 02:18:16<span class="o">)</span> 
</span></span><span class="line"><span class="cl">Type <span class="s1">&#39;copyright&#39;</span>, <span class="s1">&#39;credits&#39;</span> or <span class="s1">&#39;license&#39;</span> <span class="k">for</span> more information
</span></span><span class="line"><span class="cl">IPython 7.31.1 -- An enhanced Interactive Python. Type <span class="s1">&#39;?&#39;</span> <span class="k">for</span> help.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">In <span class="o">[</span>1<span class="o">]</span>: from notebook.auth import passwd
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">In <span class="o">[</span>2<span class="o">]</span>: passwd<span class="o">()</span>
</span></span><span class="line"><span class="cl">Enter password: 
</span></span><span class="line"><span class="cl">Verify password: 
</span></span><span class="line"><span class="cl">Out<span class="o">[</span>2<span class="o">]</span>: <span class="s1">&#39;argon2:$argon2id$v=19$m=10240,t=10,p=xxxxxxxxx&#39;</span> <span class="c1"># 复制&#39;&#39;之间的内容 后面需要</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">In <span class="o">[</span>2<span class="o">]</span>: <span class="nb">exit</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">jupyter notebook --generate-config <span class="c1"># 这里会提示你生成的文件在哪里</span>
</span></span><span class="line"><span class="cl">vim ~/.jupyter/jupyter_notebook_config.py <span class="c1"># 这里编辑上一步提示的文件</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 新增加或者修改如下内容</span>
</span></span><span class="line"><span class="cl">c.NotebookApp.allow_remote_access <span class="o">=</span> True
</span></span><span class="line"><span class="cl">c.NotebookApp.ip<span class="o">=</span><span class="s1">&#39;*&#39;</span>
</span></span><span class="line"><span class="cl">c.NotebookApp.password <span class="o">=</span> u<span class="s1">&#39;argon2:$argon2id$v=19$m=10240,t=10,p=8$Vc5lLVsXKZLGftp6xrHfEfOkQvIU5YiOhdw&#39;</span> <span class="c1">#粘贴之前复制的密钥</span>
</span></span><span class="line"><span class="cl">c.NotebookApp.open_browser <span class="o">=</span> False
</span></span><span class="line"><span class="cl">c.NotebookApp.allow_root <span class="o">=</span> True <span class="c1"># 允许以root身份运行</span>
</span></span><span class="line"><span class="cl">c.NotebookApp.port <span class="o">=</span> <span class="m">61111</span> <span class="c1"># 设置端口 注意别跟别人的重复了</span>
</span></span><span class="line"><span class="cl">c.NotebookApp.notebook_dir <span class="o">=</span> <span class="s1">&#39;/home/xxx/&#39;</span> <span class="c1"># 非必要 设置jupyter默认目录</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 设置好后 应该就能正常访问了</span>
</span></span><span class="line"><span class="cl">jupyter notebook
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="美化增强">美化增强</h3>
<p>这部分内容不是必要的，仅做记录。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 配置主题</span>
</span></span><span class="line"><span class="cl">pip install jupyterthemes
</span></span><span class="line"><span class="cl"><span class="c1"># 个人喜欢并且已经习惯了的一套主题设置</span>
</span></span><span class="line"><span class="cl">jt -t monokai -f fira -fs <span class="m">13</span> -cellw 90% -ofs <span class="m">11</span> -dfs <span class="m">11</span> -T -N
</span></span><span class="line"><span class="cl"><span class="c1"># 恢复默认主题</span>
</span></span><span class="line"><span class="cl">jt -r
</span></span><span class="line"><span class="cl"><span class="c1"># 配置插件</span>
</span></span><span class="line"><span class="cl">pip install jupyter_contrib_nbextensions
</span></span><span class="line"><span class="cl">jupyter contrib nbextension install --user
</span></span><span class="line"><span class="cl"><span class="c1"># 安装插件管理器 这一步可能会失败 详见后文更新1</span>
</span></span><span class="line"><span class="cl">pip install jupyter_nbextensions_configurator
</span></span><span class="line"><span class="cl"><span class="c1"># 建议配置项</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Hinterland 代码补全</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Collapsible headings 折叠标题</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Notify 通知机制，跑一些耗时较久的任务，完成后通知</span>
</span></span><span class="line"><span class="cl"><span class="c1"># zenmode 隐藏活动状态栏，方便注意代码</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ExecuteTime 显示运行的时间</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/conda-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp" data-fancybox="gallery" data-src="/article/conda-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp" data-caption="插件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/conda-r-jupyter/image-20221010205123146_hu_a41617526a284565.webp 480w, /article/conda-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp 720w, /article/conda-r-jupyter/image-20221010205123146_hu_a76e43c7eebd5b78.webp 960w, /article/conda-r-jupyter/image-20221010205123146_hu_cb4dcb98a38176df.webp 1440w, /article/conda-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2760"
                    height="1576"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/conda-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp"
                    srcset="/article/conda-r-jupyter/image-20221010205123146_hu_a41617526a284565.webp 480w, /article/conda-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp 720w, /article/conda-r-jupyter/image-20221010205123146_hu_a76e43c7eebd5b78.webp 960w, /article/conda-r-jupyter/image-20221010205123146_hu_cb4dcb98a38176df.webp 1440w, /article/conda-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="插件"
                    
                />
            </picture>
        </a></p>
<h2 id="感谢">感谢</h2>
<p>所有热心分享教程经验的网友</p>
<h2 id="更新1">更新1</h2>
<p>我在2023.03.20重复此教程时发现 <strong>Nbextensions</strong> 标签不会出现，经查阅，是插件未更新适配依赖包 nbclassic 的新版本导致。</p>
<p>详见GitHub的<a href="https://github.com/Jupyter-contrib/jupyter_nbextensions_configurator/issues/151" target="_blank" rel="noopener">issue</a>。</p>
<p>解决方法：降级依赖包版本即可。后续官方可能会更新适配。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install <span class="s2">&#34;nbclassic&lt;0.5&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div>]]></content:encoded>
    </item>
    <item>
      <title>青龙面板篇之哔哩哔哩挂机</title>
      <link>https://vccv.cc/article/bilibili-qinglong.html</link>
      <pubDate>Wed, 07 Sep 2022 11:45:10 +0000</pubDate>
      <guid>https://vccv.cc/article/bilibili-qinglong.html</guid>
      <description>继上一篇分享了基础的青龙面板搭建以及京东京豆挂机后，今日我又看到一个有趣的挂机项目bilitools。在对项目的原文档进行一定研究后，我又准备出一篇相应的配置教程。结合我自己的理解，仅供参考！</description>
      <content:encoded><![CDATA[<h2 id="2023101-更新">2023.10.1 更新</h2>
<p>本文内容可能不再适用，请酌情对照参考 <a href="https://github.com/whyour/qinglong" target="_blank" rel="noopener">官方仓库</a> 安装教程。</p>
<blockquote>
<p>温馨提示：</p>
<p>截止目前（2023.10.1），新用户可以选择安装<em>Debian</em>版本<code>docker pull whyour/qinglong:debian</code></p>
<p>优点是兼容更多的python依赖：例如 <a href="https://github.com/sml2h3/ddddocr" target="_blank" rel="noopener">ddddocr</a> 只能在Debian版本安装，而不能在默认版本中安装。</p>
</blockquote>
<h2 id="前言">前言</h2>
<p>继上一篇分享了基础的<a href="https://vccv.cc/article/qinglong-jd.html" target="_blank" rel="noopener">青龙面板搭建以及京东京豆挂机</a>后，今日我又看到一个有趣的挂机项目BiliTools。</p>
<p>在对项目的<a href="https://btdocs.vercel.app/" target="_blank" rel="noopener">原文档</a>进行一定研究后，我又准备水一篇相应的配置教程。</p>
<p>结合我自己的理解，仅供参考！！！</p>
<blockquote>
<p>小提示：</p>
<p>由于vercel服务的主域名vercel.app近日被墙，查阅原文档需自备科学上网条件。</p>
</blockquote>
<h2 id="准备">准备</h2>
<p>一台运行的青龙服务器（本地或者云服务器都可）。</p>
<p>搭建教程：<a href="https://vccv.cc/article/qinglong-jd.html" target="_blank" rel="noopener">点击查看</a>。</p>
<blockquote>
<p>该项目可以运行在多种环境下，包括但不限于本地运行、青龙面板、Docker、云函数等等。</p>
<p>本篇只针对青龙面板进行部署。</p>
</blockquote>
<h2 id="教程">教程</h2>
<h3 id="安装依赖">安装依赖</h3>
<p>在 <strong>青龙面板-&gt;依赖管理-&gt;NodeJs-&gt;新建依赖</strong> ，输入名称 <code>@catlair/bilitools</code> ，点击确定安装即可。</p>
<p><a href="/article/bilibili-qinglong/image-20220907120359433_hu_a33ddff109d29a07.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/image-20220907120359433_hu_a33ddff109d29a07.webp" data-caption="安装依赖">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/image-20220907120359433_hu_4028008303421a3f.webp 480w, /article/bilibili-qinglong/image-20220907120359433_hu_96bdae57856d2a36.webp 720w, /article/bilibili-qinglong/image-20220907120359433_hu_66c5ce72f2028a6a.webp 960w, /article/bilibili-qinglong/image-20220907120359433_hu_a33ddff109d29a07.webp 1038w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1038"
                    height="994"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/image-20220907120359433_hu_96bdae57856d2a36.webp"
                    srcset="/article/bilibili-qinglong/image-20220907120359433_hu_4028008303421a3f.webp 480w, /article/bilibili-qinglong/image-20220907120359433_hu_96bdae57856d2a36.webp 720w, /article/bilibili-qinglong/image-20220907120359433_hu_66c5ce72f2028a6a.webp 960w, /article/bilibili-qinglong/image-20220907120359433_hu_a33ddff109d29a07.webp 1038w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="安装依赖"
                    
                />
            </picture>
        </a></p>
<h3 id="拉取脚本">拉取脚本</h3>
<p>在 <strong>青龙面板-&gt;定时任务-&gt;新建任务</strong> ，输入名称（随意）、命令（<code>ql raw https://gitee.com/Kudouran/BiliTools/raw/main/tools/bilitools_npm.js</code>）、定时规则（0 0 0 * * *），点击确定后手动运行一次即可。</p>
<blockquote>
<p>关于定时规则：</p>
<p>这里使用的是Java类型的cron表达式，**0 0 0 * * *** 表示每日的凌晨定时运行一次。</p>
<p>如果想要自行修改，可以使用<a href="https://tool.lu/crontab/" target="_blank" rel="noopener">在线工具</a>。</p>
<p><a href="/article/bilibili-qinglong/image-20220907121154016_hu_21df22143abe9d1.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/image-20220907121154016_hu_21df22143abe9d1.webp" data-caption="cron表达式">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/image-20220907121154016_hu_fe904c88afef0c14.webp 480w, /article/bilibili-qinglong/image-20220907121154016_hu_20718d16a9abba1e.webp 720w, /article/bilibili-qinglong/image-20220907121154016_hu_13953584f5a5767.webp 960w, /article/bilibili-qinglong/image-20220907121154016_hu_51397d3a9ed22507.webp 1440w, /article/bilibili-qinglong/image-20220907121154016_hu_21df22143abe9d1.webp 1618w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1618"
                    height="1252"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/image-20220907121154016_hu_20718d16a9abba1e.webp"
                    srcset="/article/bilibili-qinglong/image-20220907121154016_hu_fe904c88afef0c14.webp 480w, /article/bilibili-qinglong/image-20220907121154016_hu_20718d16a9abba1e.webp 720w, /article/bilibili-qinglong/image-20220907121154016_hu_13953584f5a5767.webp 960w, /article/bilibili-qinglong/image-20220907121154016_hu_51397d3a9ed22507.webp 1440w, /article/bilibili-qinglong/image-20220907121154016_hu_21df22143abe9d1.webp 1618w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="cron表达式"
                    
                />
            </picture>
        </a></p>
</blockquote>
<p><a href="/article/bilibili-qinglong/image-20220907120800606_hu_80aa88372da57dc2.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/image-20220907120800606_hu_80aa88372da57dc2.webp" data-caption="拉取脚本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/image-20220907120800606_hu_84f39b8744ab70f7.webp 480w, /article/bilibili-qinglong/image-20220907120800606_hu_33dfa0bf2703877d.webp 720w, /article/bilibili-qinglong/image-20220907120800606_hu_35ff513bbd781ab6.webp 960w, /article/bilibili-qinglong/image-20220907120800606_hu_80aa88372da57dc2.webp 1036w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1036"
                    height="1036"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/image-20220907120800606_hu_33dfa0bf2703877d.webp"
                    srcset="/article/bilibili-qinglong/image-20220907120800606_hu_84f39b8744ab70f7.webp 480w, /article/bilibili-qinglong/image-20220907120800606_hu_33dfa0bf2703877d.webp 720w, /article/bilibili-qinglong/image-20220907120800606_hu_35ff513bbd781ab6.webp 960w, /article/bilibili-qinglong/image-20220907120800606_hu_80aa88372da57dc2.webp 1036w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="拉取脚本"
                    
                />
            </picture>
        </a></p>
<h3 id="更新npm包">更新npm包</h3>
<p>自动更新如下所示：</p>
<p><a href="/article/bilibili-qinglong/ql_update_hu_711416eb784b61fe.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/ql_update_hu_711416eb784b61fe.webp" data-caption="更新npm包">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/ql_update_hu_f2d8286ff3ff1083.webp 480w, /article/bilibili-qinglong/ql_update_hu_986ce5571027bc92.webp 720w, /article/bilibili-qinglong/ql_update_hu_3fbe1fc8dad22663.webp 960w, /article/bilibili-qinglong/ql_update_hu_711416eb784b61fe.webp 1308w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1308"
                    height="545"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/ql_update_hu_986ce5571027bc92.webp"
                    srcset="/article/bilibili-qinglong/ql_update_hu_f2d8286ff3ff1083.webp 480w, /article/bilibili-qinglong/ql_update_hu_986ce5571027bc92.webp 720w, /article/bilibili-qinglong/ql_update_hu_3fbe1fc8dad22663.webp 960w, /article/bilibili-qinglong/ql_update_hu_711416eb784b61fe.webp 1308w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="更新npm包"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pnpm remove -g @catlair/bilitools <span class="o">&amp;&amp;</span> pnpm add -g @catlair/bilitools
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>不输入 <code>pnpm remove -g @catlair/bilitools</code> 的话前一个版本的依赖包就会一直保留在磁盘中。</p>
</blockquote>
<h2 id="获取cookie">获取cookie</h2>
<h3 id="pc端浏览器隐私模式推荐">PC端浏览器隐私模式（推荐）</h3>
<p>以 PC 端浏览器举例（推荐使用 Firefox/Chrome/Chromium Edge）</p>
<p>最终 Cookie 是这样的（为了演示方便换了行，实际只有一行）:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">_uuid=D2282D0F-257B-845A-BDF5-C770ED288F4001440infoc; buvid3=BF17608E-FB87-4F49-A922-56FD2E284D6F18534infoc;
</span></span><span class="line"><span class="cl">fingerprint=5502cd4fe9637738de04bd9c3d1bdbc5;
</span></span><span class="line"><span class="cl">buvid_fp=BF17608E-FB87-4F49-A922-56FD2E284D6F18534infoc;
</span></span><span class="line"><span class="cl">SESSDATA=21607773%2C1631089673%2C71a42%2A31; bili_jct=dd92c55a6d67041ce2f3fb1650889ea8;
</span></span><span class="line"><span class="cl">DedeUserID=521268093; DedeUserID__ckMd5=47d541f04b605da9;
</span></span><span class="line"><span class="cl">sid=ivie73r8; fingerprint3=792b32adfecbe31a4aca53ab7be1ad76;
</span></span><span class="line"><span class="cl">fingerprint_s=bb6736758e7344a295c2ed6070cc642e;
</span></span><span class="line"><span class="cl">buvid_fp_plain=BF17608E-FB87-4F49-A922-56FD2E284D6F18534infoc;
</span></span><span class="line"><span class="cl">CURRENT_FNVAL=80; blackside_state=1; rpdid=|(kmJYYJ)lkR0J&#39;uYu)llkJYJ; _dfcaptcha=a46d7562a42065d43a88c053e283e876;
</span></span><span class="line"><span class="cl">LIVE_BUVID=AUTO8016188357987702; bsource=search_baidu; PVID=2
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>为了避免 cookie 被刷新失效</strong>（例如你时常使用浏览器访问 b 站，那就不要直接复制它的 cookie，因为目前存在 cookie 自动刷新的情况，你保留的就会失效了）。</p>
<p>你应该使用<strong>隐私窗口</strong>重新登录b站，并获取新的 cookie。</p>
<p>隐私窗口打开方式（举例）：</p>
<p><a href="/article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp" data-caption="隐私窗口">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/br_ys.29d7da3d_hu_bbcce4de71f1bc46.webp 480w, /article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp 502w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="502"
                    height="558"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp"
                    srcset="/article/bilibili-qinglong/br_ys.29d7da3d_hu_bbcce4de71f1bc46.webp 480w, /article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp 502w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="隐私窗口"
                    
                />
            </picture>
        </a></p>
<p>获取成功后应该<strong>直接关闭隐私窗口</strong>，切记不要退出你的b站账号，那样 cookie 会立马失效。</p>
<h3 id="chrome">Chrome</h3>
<p>打开浏览器隐私窗口，任意方式进入 b 站（搜索，收藏夹，地址访问等），登录账号。
按 F12 （或者右键 &ndash;&gt; 检查）打开开发者工具，切换到 <code>网络</code> ( <code>network</code> )
点击重新载入（或者按 F5，Ctrl + R 等）刷新页面，点击某一个请求（通常是第一个为 nav ）。</p>
<p><a href="/article/bilibili-qinglong/chrome-net-bnav_hu_17886d2f3b02b3b.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/chrome-net-bnav_hu_17886d2f3b02b3b.webp" data-caption="chrome获取cookie">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/chrome-net-bnav_hu_ba4afd0b0722d1c6.webp 480w, /article/bilibili-qinglong/chrome-net-bnav_hu_b5e409a3ebea79d0.webp 720w, /article/bilibili-qinglong/chrome-net-bnav_hu_aab63857d3d8c7c8.webp 960w, /article/bilibili-qinglong/chrome-net-bnav_hu_17886d2f3b02b3b.webp 1127w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1127"
                    height="774"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/chrome-net-bnav_hu_b5e409a3ebea79d0.webp"
                    srcset="/article/bilibili-qinglong/chrome-net-bnav_hu_ba4afd0b0722d1c6.webp 480w, /article/bilibili-qinglong/chrome-net-bnav_hu_b5e409a3ebea79d0.webp 720w, /article/bilibili-qinglong/chrome-net-bnav_hu_aab63857d3d8c7c8.webp 960w, /article/bilibili-qinglong/chrome-net-bnav_hu_17886d2f3b02b3b.webp 1127w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="chrome获取cookie"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>注意：</p>
<p>在使用 Chromium 类的浏览器时复制时一定要选中<strong>复制</strong>，而不是使用自带的<strong>复制值</strong>功能。</p>
</blockquote>
<h3 id="firefox">Firefox</h3>
<p>打开浏览器隐私窗口，任意方式进入 b 站（搜索，收藏夹，地址访问等），登录账号。
按 F12 （或者右键 &ndash;&gt; 检查）打开开发者工具，切换到<code>网络</code> ( <code>network</code> )
点击重新载入（或者按 F5，Ctrl + R 等）刷新页面。</p>
<p><a href="/article/bilibili-qinglong/firefox-network_hu_daee1fcfab95c142.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/firefox-network_hu_daee1fcfab95c142.webp" data-caption="firefox获取cookie">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/firefox-network_hu_686ef5ab639b6640.webp 480w, /article/bilibili-qinglong/firefox-network_hu_9147886ca2eb6caa.webp 720w, /article/bilibili-qinglong/firefox-network_hu_d687112af33b1655.webp 960w, /article/bilibili-qinglong/firefox-network_hu_465c97c053bd5673.webp 1440w, /article/bilibili-qinglong/firefox-network_hu_daee1fcfab95c142.webp 1802w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1802"
                    height="829"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/firefox-network_hu_9147886ca2eb6caa.webp"
                    srcset="/article/bilibili-qinglong/firefox-network_hu_686ef5ab639b6640.webp 480w, /article/bilibili-qinglong/firefox-network_hu_9147886ca2eb6caa.webp 720w, /article/bilibili-qinglong/firefox-network_hu_d687112af33b1655.webp 960w, /article/bilibili-qinglong/firefox-network_hu_465c97c053bd5673.webp 1440w, /article/bilibili-qinglong/firefox-network_hu_daee1fcfab95c142.webp 1802w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="firefox获取cookie"
                    
                />
            </picture>
        </a></p>
<p><a href="/article/bilibili-qinglong/firefox-net-bnav_hu_2dada2f1499db66f.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/firefox-net-bnav_hu_2dada2f1499db66f.webp" data-caption="firefox获取cookie">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/firefox-net-bnav_hu_859a8f6a9593c8.webp 480w, /article/bilibili-qinglong/firefox-net-bnav_hu_87025ddb36af3c96.webp 720w, /article/bilibili-qinglong/firefox-net-bnav_hu_72fb7e541fced3b0.webp 960w, /article/bilibili-qinglong/firefox-net-bnav_hu_820d722bf31b6a3e.webp 1440w, /article/bilibili-qinglong/firefox-net-bnav_hu_2dada2f1499db66f.webp 1919w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1919"
                    height="711"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/firefox-net-bnav_hu_87025ddb36af3c96.webp"
                    srcset="/article/bilibili-qinglong/firefox-net-bnav_hu_859a8f6a9593c8.webp 480w, /article/bilibili-qinglong/firefox-net-bnav_hu_87025ddb36af3c96.webp 720w, /article/bilibili-qinglong/firefox-net-bnav_hu_72fb7e541fced3b0.webp 960w, /article/bilibili-qinglong/firefox-net-bnav_hu_820d722bf31b6a3e.webp 1440w, /article/bilibili-qinglong/firefox-net-bnav_hu_2dada2f1499db66f.webp 1919w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="firefox获取cookie"
                    
                />
            </picture>
        </a></p>
<h3 id="手机端">手机端</h3>
<p>不推荐，有缺陷，暂时不提。</p>
<h2 id="配置文件重点">配置文件（重点）</h2>
<p>配置文件的编写是本文的重点，也是项目的重点。</p>
<p>正确配置该文件才能正常使用，需要各位多花时间认真阅读。</p>
<h3 id="懒人版单人自用请按需修改">懒人版单人自用（请按需修改）</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span><span class="lnt">150
</span><span class="lnt">151
</span><span class="lnt">152
</span><span class="lnt">153
</span><span class="lnt">154
</span><span class="lnt">155
</span><span class="lnt">156
</span><span class="lnt">157
</span><span class="lnt">158
</span><span class="lnt">159
</span><span class="lnt">160
</span><span class="lnt">161
</span><span class="lnt">162
</span><span class="lnt">163
</span><span class="lnt">164
</span><span class="lnt">165
</span><span class="lnt">166
</span><span class="lnt">167
</span><span class="lnt">168
</span><span class="lnt">169
</span><span class="lnt">170
</span><span class="lnt">171
</span><span class="lnt">172
</span><span class="lnt">173
</span><span class="lnt">174
</span><span class="lnt">175
</span><span class="lnt">176
</span><span class="lnt">177
</span><span class="lnt">178
</span><span class="lnt">179
</span><span class="lnt">180
</span><span class="lnt">181
</span><span class="lnt">182
</span><span class="lnt">183
</span><span class="lnt">184
</span><span class="lnt">185
</span><span class="lnt">186
</span><span class="lnt">187
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// 注意 // 开头的是注释，没有实际意义
</span></span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 浏览器用户代理 打开下面网址在线获取：
</span></span></span><span class="line"><span class="cl">    <span class="c1">// http://service.spiritsoft.cn/ua.html
</span></span></span><span class="line"><span class="cl">    <span class="err">userAgent:</span> <span class="err">&#39;&#39;,</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 通用 api 延迟时间（s）
</span></span></span><span class="line"><span class="cl">    <span class="err">apiDelay:</span> <span class="err">[2,</span> <span class="err">6],</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// b 站 cookie
</span></span></span><span class="line"><span class="cl">    <span class="c1">// 获取教程在上面
</span></span></span><span class="line"><span class="cl">    <span class="err">cookie:</span> <span class="nt">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 配置运行的功能
</span></span></span><span class="line"><span class="cl">    <span class="err">function:</span> <span class="err">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 瓜子兑换硬币
</span></span></span><span class="line"><span class="cl">      <span class="err">silver2Coin:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 投币
</span></span></span><span class="line"><span class="cl">      <span class="err">addCoins:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 直播签到
</span></span></span><span class="line"><span class="cl">      <span class="err">liveSignTask:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 分享和观看
</span></span></span><span class="line"><span class="cl">      <span class="err">shareAndWatch:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 漫画任务
</span></span></span><span class="line"><span class="cl">      <span class="err">mangaTask:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 应援团签到
</span></span></span><span class="line"><span class="cl">      <span class="err">supGroupSign:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 使用 b 币券
</span></span></span><span class="line"><span class="cl">      <span class="err">useCouponBp:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 获取 vip 权益
</span></span></span><span class="line"><span class="cl">      <span class="err">getVipPrivilege:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 直播赠送礼物
</span></span></span><span class="line"><span class="cl">      <span class="err">giveGift:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 赛事竞猜
</span></span></span><span class="line"><span class="cl">      <span class="err">matchGame:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 取消关注
</span></span></span><span class="line"><span class="cl">      <span class="err">batchUnfollow:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 直播天选时刻
</span></span></span><span class="line"><span class="cl">      <span class="err">liveLottery:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 直播天选红包
</span></span></span><span class="line"><span class="cl">      <span class="err">liveRedPack:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 粉丝牌等级
</span></span></span><span class="line"><span class="cl">      <span class="err">liveIntimacy:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 大会员大积分
</span></span></span><span class="line"><span class="cl">      <span class="err">bigPoint:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 风纪委员
</span></span></span><span class="line"><span class="cl">      <span class="err">judgement:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 转盘抽奖
</span></span></span><span class="line"><span class="cl">      <span class="err">activityLottery:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 直播天选时刻
</span></span></span><span class="line"><span class="cl">    <span class="err">redPack:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 直播间来源方式 1 活动（活动链接可能更新不及时），2 扫描。其它值 所有方式依次尝试。
</span></span></span><span class="line"><span class="cl">      <span class="err">source:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 活动链接
</span></span></span><span class="line"><span class="cl">      <span class="err">uri:</span> <span class="err">&#39;https:</span><span class="c1">//api.live.bilibili.com/xlive/fuxi-interface/AugRedPacket2022Controller/redPocketPlaying&#39;,
</span></span></span><span class="line"><span class="cl">      <span class="c1">// 【仅使用活动时有效】 每轮抢红包的间隔时间（秒）
</span></span></span><span class="line"><span class="cl">      <span class="err">intervalActive:</span> <span class="err">60,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 中场休息时间，当每参加了几个直播间的时候，休息一下 [参加个数，休息时间（分，小于1为直接结束）]
</span></span></span><span class="line"><span class="cl">      <span class="err">restTime:</span> <span class="err">[-1,</span> <span class="err">-1],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 疑似触发风控时休眠时间，[连续出现次数，休眠时间（分，小于1为直接结束）]
</span></span></span><span class="line"><span class="cl">      <span class="err">riskTime:</span> <span class="err">[-1,</span> <span class="err">-1],</span> <span class="c1">// 与 riskNum 不同，该参数会与 restTime 互相影响重置次数
</span></span></span><span class="line"><span class="cl">      <span class="c1">// 同时参与的直播间数量
</span></span></span><span class="line"><span class="cl">      <span class="err">linkRoomNum:</span> <span class="err">1,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 参与直播时发送的弹幕数量（与内置数量比，min(10，剩余时间/5，配置)）
</span></span></span><span class="line"><span class="cl">      <span class="c1">// [固定值]，[最少,最多]
</span></span></span><span class="line"><span class="cl">      <span class="err">dmNum:</span> <span class="err">[10],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 是否在等待时处理关注用户（读取消息，移动）
</span></span></span><span class="line"><span class="cl">      <span class="err">moveUpInWait:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">天选时刻关注</span> <span class="err">UP</span> <span class="err">移动到分组</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">moveTag:</span> <span class="err">&#39;rp关注&#39;,</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">关注回复处理方式</span>  <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">actFollowMsg:</span> <span class="err">&#39;read&#39;,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 总参与次数，达到后不管结果如何，直接结束
</span></span></span><span class="line"><span class="cl">      <span class="err">totalNum:</span> <span class="err">-1,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 连续超过多少次没有中，直接结束，小于1为不限制
</span></span></span><span class="line"><span class="cl">      <span class="err">noWinNum:</span> <span class="err">10,</span> <span class="c1">// 避免一直运行
</span></span></span><span class="line"><span class="cl">      <span class="c1">// 连续疑似触发风控多少次，直接结束，小于1为不限制
</span></span></span><span class="line"><span class="cl">      <span class="err">riskNum:</span> <span class="err">5,</span> <span class="c1">// 避免一直运行
</span></span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 自动取消关注
</span></span></span><span class="line"><span class="cl">    <span class="err">unFollow:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 单个取消的时间间隔（秒）
</span></span></span><span class="line"><span class="cl">      <span class="err">delay:</span> <span class="err">3,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 中场休息，[取消数量, 休息时间（分）] 取消数量和休息时间都应该为正数（非0），否则无效
</span></span></span><span class="line"><span class="cl">      <span class="err">restTime:</span> <span class="err">[20,</span> <span class="err">-1],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 总数 -1 无限制
</span></span></span><span class="line"><span class="cl">      <span class="err">totalNum:</span> <span class="err">-1,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 取消关注的 tag
</span></span></span><span class="line"><span class="cl">      <span class="err">tags:</span> <span class="err">[&#39;天选时刻&#39;,</span> <span class="err">&#39;rp关注&#39;],</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 消息推送
</span></span></span><span class="line"><span class="cl">    <span class="err">message:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 换行
</span></span></span><span class="line"><span class="cl">      <span class="err">br:</span> <span class="err">&#39;\n&#39;,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 青龙面板专属配置 企业微信通知示例如下：
</span></span></span><span class="line"><span class="cl">      <span class="c1">// 官方说明文档： 
</span></span></span><span class="line"><span class="cl">      <span class="c1">// https://work.weixin.qq.com/api/doc/90000/90136/91770
</span></span></span><span class="line"><span class="cl">      <span class="c1">// 下方填写密钥，企业微信推送 webhook 后面的 key
</span></span></span><span class="line"><span class="cl">      <span class="err">&#39;QYWX_KEY&#39;:</span> <span class="nt">&#34;此处填写你的key&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 投币相关
</span></span></span><span class="line"><span class="cl">    <span class="err">coin:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 目标等级
</span></span></span><span class="line"><span class="cl">      <span class="err">targetLevel:</span> <span class="err">6,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 保留的硬币数
</span></span></span><span class="line"><span class="cl">      <span class="err">stayCoins:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 投币的数量（上限5）
</span></span></span><span class="line"><span class="cl">      <span class="err">targetCoins:</span> <span class="err">5,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 自定义 up
</span></span></span><span class="line"><span class="cl">      <span class="err">customizeUp:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 当获取已投币数量失败，假设已投币数量
</span></span></span><span class="line"><span class="cl">      <span class="err">todayCoins:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 是否只投指定 up
</span></span></span><span class="line"><span class="cl">      <span class="err">upperAccMatch:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 使用b币券
</span></span></span><span class="line"><span class="cl">    <span class="err">couponBalance:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">充电的</span> <span class="err">up</span> <span class="err">默认自己</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">mid:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">预设时间，哪一天？，空数组为每一天</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">presetTime:</span> <span class="err">[10,</span> <span class="err">20],</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">使用的方式，可以是</span> <span class="err">充电/charge</span> <span class="err">电池/battery</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">use:</span> <span class="err">&#39;充电&#39;,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 直播间礼物
</span></span></span><span class="line"><span class="cl">    <span class="err">gift:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 自定义投喂礼物 UP， 在所填中随机选取
</span></span></span><span class="line"><span class="cl">      <span class="err">mids:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 省略部分配置
</span></span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 亲密度
</span></span></span><span class="line"><span class="cl">    <span class="err">intimacy:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 直播弹幕
</span></span></span><span class="line"><span class="cl">      <span class="err">liveSendMessage:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 点赞直播间
</span></span></span><span class="line"><span class="cl">      <span class="err">liveLike:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 每日亲密度上限 （系统 1500）
</span></span></span><span class="line"><span class="cl">      <span class="err">limitFeed:</span> <span class="err">1500,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 耗时很长的直播心跳（默认关闭）
</span></span></span><span class="line"><span class="cl">      <span class="err">liveHeart:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 白名单
</span></span></span><span class="line"><span class="cl">      <span class="err">whiteList:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 黑名单
</span></span></span><span class="line"><span class="cl">      <span class="err">blackList:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 漫画
</span></span></span><span class="line"><span class="cl">    <span class="err">manga:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 签到
</span></span></span><span class="line"><span class="cl">      <span class="err">sign:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 购买漫画
</span></span></span><span class="line"><span class="cl">      <span class="err">buy:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 购买漫画 id（优先级高）
</span></span></span><span class="line"><span class="cl">      <span class="err">mc:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 购买漫画名称（优先级中）
</span></span></span><span class="line"><span class="cl">      <span class="err">name:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 购买追漫（优先级低）
</span></span></span><span class="line"><span class="cl">      <span class="err">love:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 执行购买漫画间隔时间（单位天）
</span></span></span><span class="line"><span class="cl">      <span class="err">buyInterval:</span> <span class="err">2,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 星期几执行购买漫画
</span></span></span><span class="line"><span class="cl">      <span class="err">buyWeek:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 风纪委员
</span></span></span><span class="line"><span class="cl">    <span class="err">jury:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 模式
</span></span></span><span class="line"><span class="cl">      <span class="err">mode:</span> <span class="err">1,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 默认投票 0-3 好-无法判断，从中随机
</span></span></span><span class="line"><span class="cl">      <span class="err">vote:</span> <span class="err">[0,</span> <span class="err">0,</span> <span class="err">1],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 没有案件不退出，运行一次直到完成
</span></span></span><span class="line"><span class="cl">      <span class="err">once:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 参考人数最少满足
</span></span></span><span class="line"><span class="cl">      <span class="err">opinionMin:</span> <span class="err">3,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 没有案件后等待时间（分）
</span></span></span><span class="line"><span class="cl">      <span class="err">waitTime:</span> <span class="err">20,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// 大积分
</span></span></span><span class="line"><span class="cl">    <span class="err">bigPoint:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 是否间隔 5s 再重试一次，或者直接填写等待时间（秒）
</span></span></span><span class="line"><span class="cl">      <span class="err">isRetry:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 是否完成观看视频的任务
</span></span></span><span class="line"><span class="cl">      <span class="err">isWatch:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 正片视频的 epid（集数id）
</span></span></span><span class="line"><span class="cl">      <span class="err">epids:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 领取任务后的观看延时（秒）
</span></span></span><span class="line"><span class="cl">      <span class="err">watchDelay:</span> <span class="err">40,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="err">}</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>如果使用上面的配置，需要修改四个地方：</p>
<ol>
<li>
<p>user agent <em>必填</em>，点击<a href="http://service.spiritsoft.cn/ua.html" target="_blank" rel="noopener">这个网站</a>把红字部分填入引号中。</p>
</li>
<li>
<p>cookie <em>必填</em>，教程在上面。</p>
</li>
<li>
<p>是否投币请按需自行修改。（一般来说Lv6就不需要了）</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">coin:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 目标等级
</span></span></span><span class="line"><span class="cl">      <span class="err">targetLevel:</span> <span class="err">6,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 保留的硬币数
</span></span></span><span class="line"><span class="cl">      <span class="err">stayCoins:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 投币的数量（上限5）
</span></span></span><span class="line"><span class="cl">      <span class="err">targetCoins:</span> <span class="err">5,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 自定义 up
</span></span></span><span class="line"><span class="cl">      <span class="err">customizeUp:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 当获取已投币数量失败，假设已投币数量
</span></span></span><span class="line"><span class="cl">      <span class="err">todayCoins:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 是否只投指定 up
</span></span></span><span class="line"><span class="cl">      <span class="err">upperAccMatch:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>通知配置 <em>建议填写</em>。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">message:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 换行
</span></span></span><span class="line"><span class="cl">      <span class="err">br:</span> <span class="err">&#39;\n&#39;,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 这里建议直接使用你青龙面板的通知方式 以企业微信举例
</span></span></span><span class="line"><span class="cl">      <span class="c1">// 下方填写密钥 企业微信推送 webhook 后面的 key
</span></span></span><span class="line"><span class="cl">      <span class="err">&#39;QYWX_KEY&#39;:</span> <span class="nt">&#34;此处填写你的key&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 还可以使用以下方式
</span></span></span><span class="line"><span class="cl">      <span class="c1">// &#39;GOBOT_URL&#39;,
</span></span></span><span class="line"><span class="cl">      <span class="c1">// &#39;GOBOT_TOKEN&#39;,
</span></span></span><span class="line"><span class="cl">      <span class="c1">// &#39;GOBOT_QQ&#39;,
</span></span></span><span class="line"><span class="cl">      <span class="c1">// &#39;SCKEY&#39;,
</span></span></span><span class="line"><span class="cl">      <span class="c1">// &#39;QQ_SKEY&#39;
</span></span></span><span class="line"><span class="cl">      <span class="c1">//  。。。。。。
</span></span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ol>
</blockquote>
<h3 id="添加环境变量">添加环境变量</h3>
<ul>
<li>
<p>配置使用的 <code>json5</code>，兼容 <code>json</code> 且更加灵活，可以支持 <code>注释</code>。</p>
</li>
<li>
<p>务必使用 <a href="https://verytoolz.com/json5-validator.html" target="_blank" rel="noopener">在线工具</a> 校验 json5 格式（校验不通过无法继续使用）。</p>
</li>
<li>
<p>将检验合格的配置文本 粘贴在 <a href="https://www.baidufe.com/fehelper/en-decode/" target="_blank" rel="noopener">Gzip 在线压缩工具</a> 的输入框中，选择Gzip压缩，将加密结果复制即可。</p>
<p><a href="/article/bilibili-qinglong/image-20220907133801593_hu_e93033f028690156.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/image-20220907133801593_hu_e93033f028690156.webp" data-caption="Gzip压缩配置文本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/image-20220907133801593_hu_a66382664af187e5.webp 480w, /article/bilibili-qinglong/image-20220907133801593_hu_68c06583dee9460e.webp 720w, /article/bilibili-qinglong/image-20220907133801593_hu_bef1daffdb8324bb.webp 960w, /article/bilibili-qinglong/image-20220907133801593_hu_132bfb28a35afce5.webp 1440w, /article/bilibili-qinglong/image-20220907133801593_hu_e93033f028690156.webp 2724w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2724"
                    height="664"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/image-20220907133801593_hu_68c06583dee9460e.webp"
                    srcset="/article/bilibili-qinglong/image-20220907133801593_hu_a66382664af187e5.webp 480w, /article/bilibili-qinglong/image-20220907133801593_hu_68c06583dee9460e.webp 720w, /article/bilibili-qinglong/image-20220907133801593_hu_bef1daffdb8324bb.webp 960w, /article/bilibili-qinglong/image-20220907133801593_hu_132bfb28a35afce5.webp 1440w, /article/bilibili-qinglong/image-20220907133801593_hu_e93033f028690156.webp 2724w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Gzip压缩配置文本"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>青龙面板推荐使用 <strong>环境变量</strong> 的方式配置。</p>
<p>在 <strong>青龙面板-&gt;环境变量-&gt;新建变量</strong> ，名称（<strong>BILITOOLS_CONFIG</strong>）、值（填写你在上一步Gzip压缩得到的文本），点击确定即可。</p>
<p><a href="/article/bilibili-qinglong/image-20220907133920012_hu_cf59e6447650466b.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/image-20220907133920012_hu_cf59e6447650466b.webp" data-caption="添加变量">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/image-20220907133920012_hu_7421b03786c8547b.webp 480w, /article/bilibili-qinglong/image-20220907133920012_hu_436ea7bccc3346cb.webp 720w, /article/bilibili-qinglong/image-20220907133920012_hu_a179b27a01e895d2.webp 960w, /article/bilibili-qinglong/image-20220907133920012_hu_cf59e6447650466b.webp 1016w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1016"
                    height="436"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/image-20220907133920012_hu_436ea7bccc3346cb.webp"
                    srcset="/article/bilibili-qinglong/image-20220907133920012_hu_7421b03786c8547b.webp 480w, /article/bilibili-qinglong/image-20220907133920012_hu_436ea7bccc3346cb.webp 720w, /article/bilibili-qinglong/image-20220907133920012_hu_a179b27a01e895d2.webp 960w, /article/bilibili-qinglong/image-20220907133920012_hu_cf59e6447650466b.webp 1016w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="添加变量"
                    
                />
            </picture>
        </a></p>
</li>
</ul>
<h2 id="手动运行">手动运行</h2>
<p>回到青龙面板任务首页，应该会出现三个关于哔哩哔哩的任务：</p>
<p><a href="/article/bilibili-qinglong/image-20220907134421036_hu_8d98bf70715f7847.webp" data-fancybox="gallery" data-src="/article/bilibili-qinglong/image-20220907134421036_hu_8d98bf70715f7847.webp" data-caption="bilibili任务">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/bilibili-qinglong/image-20220907134421036_hu_43a67087bd3feef1.webp 480w, /article/bilibili-qinglong/image-20220907134421036_hu_4a970c21f7a366e5.webp 720w, /article/bilibili-qinglong/image-20220907134421036_hu_43093c4d992f6cbf.webp 960w, /article/bilibili-qinglong/image-20220907134421036_hu_4fe9c21602c9ee0d.webp 1440w, /article/bilibili-qinglong/image-20220907134421036_hu_8d98bf70715f7847.webp 2362w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2362"
                    height="368"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/bilibili-qinglong/image-20220907134421036_hu_4a970c21f7a366e5.webp"
                    srcset="/article/bilibili-qinglong/image-20220907134421036_hu_43a67087bd3feef1.webp 480w, /article/bilibili-qinglong/image-20220907134421036_hu_4a970c21f7a366e5.webp 720w, /article/bilibili-qinglong/image-20220907134421036_hu_43093c4d992f6cbf.webp 960w, /article/bilibili-qinglong/image-20220907134421036_hu_4fe9c21602c9ee0d.webp 1440w, /article/bilibili-qinglong/image-20220907134421036_hu_8d98bf70715f7847.webp 2362w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="bilibili任务"
                    
                />
            </picture>
        </a></p>
<p>名称是可以自行修改的，主要看命令：</p>
<ul>
<li>第一个：更新依赖；</li>
<li>第三个：拉库任务；</li>
<li>第二个：<strong>主程序任务</strong>，在手动运行拉库任务后刷新可见。</li>
</ul>
<p>在一切准备就绪后，就可以手动运行一次主任务了。</p>
<h2 id="感谢">感谢</h2>
<p><a href="https://btdocs.vercel.app/" target="_blank" rel="noopener">BiliTools</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>iOS旧版APP推荐与降级方法</title>
      <link>https://vccv.cc/article/ios-app.html</link>
      <pubDate>Thu, 01 Sep 2022 13:56:22 +0000</pubDate>
      <guid>https://vccv.cc/article/ios-app.html</guid>
      <description>如果你正在为iPhone频繁杀后台而苦恼，那就改用老版本软件试试叭。一般旧版软件的资源占用会更少，因而更流畅、更省电，而且广告也会更少，甚至某些App在旧版本的时候还没开始收费，如彩云天气Pro、白描。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>如果你正在为 iPhone 频繁杀后台而苦恼，那就改用老版本软件试试叭 ~
一般旧版软件的资源占用会更少，因而更流畅、更省电，而且广告也会更少（哭）~
甚至某些 App 在旧版本的时候还没开始收费喔！如彩云天气Pro、白描！！
还能用上没有被和谐的WiFi万能钥匙！！
所以还不赶快码住！！</p>
<blockquote>
<p>小提示：</p>
<p>推荐PC端访问，快捷搜索🔍：Ctrl + F，快速定位你需要的APP。</p>
<p>macOS快捷键：Command + F。</p>
</blockquote>
<h2 id="更新日志">更新日志</h2>
<p><strong>2022/09/25</strong></p>
<ul>
<li>京东 10.2.0 iOS16发送图片正常最低版本，10.2.4 无双十一图标</li>
<li>小红书 7.4 支持新版 emoji</li>
</ul>
<p><strong>2022/09/12</strong></p>
<ul>
<li>高德地图 9.05.2 以下版本搜索功能失效</li>
</ul>
<p><strong>2022/09/03</strong></p>
<ul>
<li>企业微信 4.0 支持直播会议</li>
<li>QQ 8.5.0 支持群课堂</li>
<li>闲鱼 7.4.10 支持长辈模式，无启动广告，只能使用手机号一键登入</li>
<li>淘宝 10.13.0 无 618 图标的深色模式首版后一版本，建议设置地区为全球减少首页广告</li>
<li>支付宝 10.2.76 支持长辈模式</li>
<li>网易云音乐 4.1.2 支持新 ncm 格式播放下载</li>
<li>贴吧内部版 1.0.8 已下架，若已购仍可下载，无广告，不能搜索</li>
<li>白描 2.1.6 无广告</li>
</ul>
<p><strong>2022/08/31</strong></p>
<ul>
<li>抖音极速版 16.8.0 支持视频倍数</li>
<li>抖音 16.5.0 支持视频倍数</li>
</ul>
<p><strong>2022/08/28</strong></p>
<ul>
<li>豆瓣 6.x.x 版本已和谐，最低可用版本为 7.0.0，请及时更新</li>
<li>淘宝 10.12.20 以前版本全部有更新弹窗，深色模式最低版为 10.12.20</li>
</ul>
<h2 id="福利版本">福利版本</h2>
<p><strong>Halide Mark II</strong></p>
<ul>
<li>支持 RAW 格式拍摄的相机</li>
<li>2020 年 10 月 22 日起由付费下载（￥30）改为订阅制（￥20/月），现可直接下载订阅制前最后一版 1.17.3(850784840) 免费使用全部功能。</li>
</ul>
<p><strong>FiLMiC Pro</strong></p>
<ul>
<li>iPhone 最强大的摄像软件。</li>
<li>2022 年 8 月 25 日起由付费下载（￥99）改为订阅制（￥35/周），现可直接下载订阅制前最后一版 6.19.7(851609129) 免费使用基础功能。</li>
<li>还可越狱后使用「<a href="http://apt.cdalei.com/" target="_blank" rel="noopener">iOSGods iAP内购破解</a>」解锁 Log 等高级功能。</li>
</ul>
<p><strong>Pixelmator Photo</strong></p>
<ul>
<li>iPhone 最强大的修图软件。</li>
<li>2022 年 8 月 18 日起由付费下载（￥30）改为订阅制（￥33/月），现可直接下载订阅制前最后一版 2.0.12(850784840) 免费使用全部功能。</li>
</ul>
<h2 id="版本推荐">版本推荐</h2>
<ul>
<li>iPhone X 于 2017.11.03 上市，此日期后的版本方支持全面屏；</li>
<li>iOS 13.0 Beta 1 于 2019.06.04 上线，此日期后的版本方支持深色模式；</li>
<li>iOS 14.5 Beta 1 于 2021.02.02 上线，此日期后的版本一定支持 iOS 14.5 及以后版本；</li>
<li>ios 15.0 Beta 1 于 2021.06.18 上线，此日期后的版本一定支持 iOS 15.0 及以后版本；</li>
<li>带 ◆ 为自用版本，在 iPhone 11 Pro Max, iOS 14.2 上运行良好；</li>
<li>谨慎更新系统版本，iOS 14.5 及以后大部分旧版应用无法安装，提示安装包不完整；</li>
<li>各版本更新内容及上线时间可在<a href="https://www.qimai.cn/" target="_blank" rel="noopener">七麦数据</a>查询；</li>
<li>如版本失效请留言反馈。</li>
</ul>
<p><strong>社交</strong></p>
<ul>
<li>QQ 6.2.2(启动极快、很少杀后台，气泡显示异常) 6.5.9 6.6.5(云同步正常最低版) 6.7.1(无斜眼笑等表情，此版及以前版本需覆盖安装) 7.1.0(可直接登录最低版) 7.2.5 7.2.8(全面屏) 7.3.2(Apple Watch) 7.3.5 7.5.5 7.7.8 8.0.6 8.1.0(简洁模式首版，空间视频无法加载) 8.1.5(iOS15.5) ◆8.1.8◆(覆盖安装深色模式生效最低版) 8.2.6(iOS14.5) 8.2.8(iOS15.3) 8.4.1(夜间主题可下载最低版) 8.4.2(iOS15.3) 8.4.10(牛转乾坤表情) 8.5.0(群课堂) 8.7.5(菜汪表情，iOS16) 8.8.38(QQ频道) 8.8.50</li>
<li>TIM 1.1.5 ◆2.3.0◆(支持结构化消息，在线文档、全面屏最低版) 2.5.2 2.5.6 3.0.0 3.1.0(此版前需覆盖安装，iOS16无法覆盖安装)</li>
<li>微信 6.5.19 6.6.1 6.7.0(iOS15.6闪退) 6.7.4(iOS14.5，地区可设为中国大陆最后一版，方法参见 <a href="https://qianling.pw/wechat-blank" target="_blank" rel="noopener">https://qianling.pw/wechat-blank</a>) 7.0.5(浮窗首版，朋友圈视频自动播放) 7.0.9 7.0.12(深色模式首版，公众号列表无广告，iOS15.3) 7.0.13(拍一拍、视频号最低版) ◆7.0.14◆(小程序浮窗最后一版，支持iPad、iPhone同时登录，人脸验证失效，836563902) 7.0.15(人脸验证失效) 7.0.18(粤省事最低版本) 7.0.20(iOS14照片权限) 7.0.21(粤康码最低版本) 8.0.3(Apple Watch，表情包999上限最低版本) 8.0.8(换提示音) 8.0.9(自动电脑登录) 8.0.14(折叠群最低版) 8.0.22(iOS16)</li>
<li>企业微信 3.1.8(可登录最低版) 4.0(直播会议)</li>
<li>微博 6.5.1(无广告) 7.3.1(首页直播图标前最后一版、评论页无广告) 8.5.3 8.12.3(iOS14.7) 10.11.0 11.0.0(个人主页无版本过旧提醒最低版) 11.3.0(iPad无bug正常使用最低版)</li>
<li>微博国际版 3.6.8 3.8.4 ◆4.1.5◆(深色模式) 4.2.0(首页无推荐最后一版)</li>
<li>vvebo 3.1.4(改内购前最后一版)</li>
<li>钉钉 4.6.10 ◆5.1.10◆(日志) 6.0.0(iOS15.3) 6.0.26(iOS14.7)</li>
<li>QQ空间 8.6.1</li>
<li>百度贴吧 6.8.5 6.9.6(吧内搜索) 7.1.0(无启动广告) 7.3.0(会员可去广告) 8.9.0(全面屏) 9.2.0(清爽、广告少) 9.3.0 9.3.1(iOS14.5) ◆9.6.0◆(可Safari唤起最低版，搭配Flex去广告) 9.7.1 9.7.11 9.7.5 9.8.4(iOS14.7) 9.9.9(图片不能编辑) 10.3.11(深色模式) 11.0.0(搭配Flex去广告) 11.3.2 12.0.5</li>
<li>贴吧内部版 1.0.8(已下架，若已购仍可下载，无广告，不能搜索)</li>
<li>知乎 ◆6.0.0◆(搜索可用最低版，无启动广告，iOS15.3) 6.5.0 6.7.0(无启动广告最后一版) 6.14.0(深色模式) 6.65.0 6.62.0(iOS14小组件) 6.67.0</li>
<li>豆瓣 ◆7.0.0◆ 7.15.0</li>
<li>虎扑 ◆7.3.2◆</li>
<li>酷安 3.1(无启动广告最后一版，私信失效) 4.5.1(iOS15.3) ◆4.9◆(847456398) 4.9.1(蓝色主题最后一版，848225916)</li>
<li>威锋 5.5.1(无广告最后一版，但网络异常) ◆6.4◆(840909450，搭配Flex去广告) 6.6.5</li>
<li>NGA玩家社区 5.3.0(无启动广告、浏览页广告、切换广告) 6.0.8(iOS14.5、iOS16) 6.3.2</li>
<li>皮皮虾 1.3.2 1.3.9(无广告)</li>
<li>Twitter 7.37.2(可翻译) 7.60(深色模式) 8.44(无Fleets) 8.47.1(iOS14照片权限)</li>
<li>Instagram 124.0(深色模式) 165.0(iOS14照片权限)</li>
<li>Nicegram 8.3.2(强制更新前最后一版)</li>
</ul>
<p><strong>购物</strong></p>
<ul>
<li>淘宝 7.12.20(iOS15) 8.0.0(iOS15.6) 8.6.10 8.8.0(iOS14.3) 9.1.1(iOS14.3闪退) 9.2.0(无法以物搜图) 9.17.0(iOS14小组件) 9.20.0(搜同款) 10.12.20(深色模式，此版以前有更新弹窗) ◆10.13.0◆(无618图标，地区可设置为全球减少广告) 10.14.10(850964824)</li>
<li>淘宝Lite 4.16.4(外区)</li>
<li>点淘 1.7.6</li>
<li>阿里巴巴 7.20.0(iOS14.7) ◆9.4.6◆</li>
<li>京东 ◆9.5.0◆(付款可用最低版) 10.0.6(修复iPhone12购物车推荐错位显示) 10.2.0(iOS16发送图片正常最低版本) 10.2.4(无双十一图标)</li>
<li>拼多多 4.23.0(iOS15.6) 4.56.0 4.76.0(iOS14.5) 5.2.0 5.12.0 ◆5.30.0◆(多多钱包) 5.31.1(iOS14小组件)</li>
<li>微店 5.4.7</li>
<li>什么值得买 9.8.16</li>
<li>慢慢买 ◆3.2.40◆</li>
<li>苏宁 7.7.3.8</li>
<li>识货 6.54.0(iOS14.7)</li>
<li>闲鱼 6.2.5(最低可用版本) 6.2.9(iOS14.7) 6.3.7 6.4.80 6.6.60 ◆6.9.80◆(可出价最低版本，转账失效) 7.1.10(iOS15，以上均需覆盖安装) 7.4.10(长辈模式，只能手机号一键登入，iOS13.7)</li>
<li>转转 5.6.1</li>
<li>小红书 6.63(搭配Flex去广告) ◆6.86◆(iOS14.7) 7.28(浏览记录最低版) 7.40(新版emoji)</li>
<li>美团 11.4.401(美团优选不可用) 11.6.406 11.10.203(iOS15)</li>
<li>淘票票 10.4.1(iOS14小组件)</li>
<li>携程旅行 8.22(覆盖安装)</li>
<li>千牛 8.13.0 9.3.0</li>
</ul>
<p><strong>财务</strong></p>
<ul>
<li>支付宝 10.1.35 10.2.8(银行卡列表可用最低版本) ◆10.2.10◆(iOS14小组件，小程序正常) 10.2.15 10.2.38(冷启动快) 10.2.53(可关闭生活频道入口，可移除所有首页栏目卡片) 10.2.59(可关闭首页活动推荐) 10.2.76(长辈模式)</li>
<li>云闪付 ◆8.0.7◆(转账可用最低版本)</li>
<li>鲨鱼记账Pro 2.0(无社区等冗余功能)</li>
</ul>
<p><strong>娱乐</strong></p>
<ul>
<li>哔哩哔哩 6.1.3 6.61.0(动态头像最低版本，均需爱思助手下载)</li>
<li>哔哩哔哩HD 2.3(可关启动动画最后一版)</li>
<li>哔哩哔哩概念 2.13.2 2.15.4 2.4 6.48.0(全局小窗)</li>
<li>bilibili-彈幕動畫戲劇線上看 2.7.0(台湾区下载，无游戏中心、会员购、直播、启动广告等，首页竖版视频无法打开，837359696) ◆3.0.3◆(支持深色模式热切换，有直播，支持长按倍速，841150268) 3.0.4</li>
<li>抖音 15.0.0(840791014，需覆盖安装) 16.5.0(视频倍速)</li>
<li>抖音极速版 15.0.0 16.8.0(视频倍速)</li>
<li>Tik Tok 1.2.2(未屏蔽地区最后一版，无法注册登录，台湾区823491616)</li>
<li>YouTube 15.28.2 16.05.9(CC字幕按钮)</li>
<li>快手 6.11.8 9.8.50</li>
<li>爱奇艺 5.7.1(无片头广告) 7.0.1(无需短信验证登录账号) 8.12.5(可同时下3个视频) 9.7.0(影吧) 9.8.0(最后可非主设备网页扫码登录版本)</li>
<li>腾讯视频 7.8.0(iOS14.7) 8.2.48</li>
<li>优酷视频 6.12.0(无广告) 7.5.5(iOS14.7)</li>
<li>斗鱼直播 4.920</li>
<li>虎牙直播 6.5.1</li>
<li>云听 ◆5.8.0◆(无广告) 6.0.1(无启动广告)</li>
<li>网易云音乐 2.7.1 3.1.1(不支持无损音质) 3.7.5 4.0.1(iOS14.5) 4.1.2(无视频最后一版，支持新ncm格式播放下载) ◆4.2.2◆(全面屏首版，此版起有启动广告) 4.3.1(哔哩哔哩卡免流最低版本) 4.3.2 4.3.5(换UI前最后一版) 5.5.0(iOS15.6) 5.6.0(经典播放界面最后一版) 5.6.3(iOS14.5) 5.7.0(iOS15.3，iPhone13) 5.8.1(以上需覆盖安装) 6.4.7(深色模式首版) 6.5.2 7.0.0(iOS15) 7.2.0(一起听首版) 7.2.10(歌词注音) 7.3.01(右上角音乐播放转盘) 7.3.20(iOS14小组件) 8.0.10(底栏自定义、视频画中画)</li>
<li>QQ音乐 8.8.5 8.9.9(卸载QQ后可网页登录) 9.2.8(无直播、启动广告) 9.3(iOS14.7) 9.7 10.12(无更新弹窗)</li>
<li>波点音乐 1.2.6(完全免费，可导入外部歌单)</li>
<li>MOO音乐 1.6.5(界面简洁) 2.3.2(iOS15.1，此版之前清除播放历史列表有bug)</li>
<li>酷狗音乐 3.9.4 4.0.7 7.0.6 8.8.6 9.7.6</li>
<li>酷我音乐 4.9.2</li>
<li>虾米音乐 6.1.8</li>
<li>全民K歌 3.7.6</li>
<li>唱吧 8.2</li>
<li>喜马拉雅 ◆6.6.15◆ 7.0.8</li>
<li>蜻蜓FM 6.2.6(无音频广告)</li>
</ul>
<p><strong>阅读</strong></p>
<ul>
<li>今日头条 3.1.1 6.0.3(无广告、iOS11) 6.2.9(首个带聊天表情版本) 6.6.0(可越狱去广告) 7.0.5 7.0.9 7.9.2(深色模式) 7.9.6(长按倍速)</li>
<li>腾讯新闻 5.1.6</li>
<li>澎湃新闻 8.1.7(小组件、无热榜)</li>
<li>微信读书 4.3.0(深色模式) 5.0.4(小组件) 5.4.0(Apple Pencil)</li>
<li>起点读书 4.7.0(可横屏首版，Flex屏蔽更新) 5.0.1</li>
<li>追书神器 2.23.1(无追书币、追更模式) 2.25.1(可换源) 2.24.24(可换源)</li>
<li>爱阅书香 6.3.0</li>
<li>书旗小说 3.9.10(无横版广告)</li>
<li>笔趣阁 5.5(无广告、弹窗)</li>
<li>香色闺阁 2.33.0</li>
<li>网易漫画 4.2.0(可使用Flex3会员补丁)</li>
</ul>
<p><strong>教育</strong></p>
<ul>
<li>Notability 10.6(免费使用最后一版)</li>
<li>学习通 4.5.6</li>
<li>百度汉语 ◆2.0◆(最低可用版本，820243885) 2.1.0</li>
<li>腾讯翻译 3.1(仅基础功能)</li>
<li>50音起源 ◆1.3.5◆(收费前最后一版)</li>
<li>运动世界校园 3.1.2(可拒绝更新最低版本)</li>
<li>完美校园 5.3.1(支付宝充值最低版本)</li>
<li>驾考宝典 7.6.4(iOS14.5)</li>
<li>驾校一点通 6.1.0(图片正常显示最低版) 6.1.7(无更新弹窗，无视频讲解，覆盖安装以更新题库) 8.1.0(答错无付费弹窗) 9.1.0(可更新题库) 9.3.1 10.2.0(无启动广告最后一版)</li>
</ul>
<p><strong>工具</strong></p>
<ul>
<li>百度 12.13.0.10</li>
<li>高德地图 9.05.2(搜索可用最低版本) 10.55.0(旧版语音最后一版) 10.80.0(侧滑返回)</li>
<li>百度地图 8.6.5(无广告) 10.24.5(全面屏) 15.2.5(深色模式)</li>
<li>哈啰出行 5.74(无越狱检测唯一版本，iOS14.5) 6.1.5(支持云闪付) 6.2.0(LOGO无横条)</li>
<li>网易大神 2.5.0 2.8.0(无启动广告，可扫码登录)</li>
<li>百度网盘 6.6.0(免VIP上传视频) 6.7.3(可更改扩展名、打开分享未知文件) 6.9.4 7.0.0 8.13.1(无启动广告) 10.1.70(消息正常)</li>
<li>天翼云盘 4.5.0(免费传视频最后一版，日签可增加空间)</li>
<li>微盘 3.3.2 3.4.3</li>
<li>有道云笔记 5.7.1(广告少) 5.9.8(云笔记、云协作并存)</li>
<li>印象笔记 9.3.9</li>
<li>WPS Office 9.0.0(无广告) 10.14.0(13Pro、iOS15查找替换不闪退最低版本)</li>
<li>Outlook 4.2210.3(无预约会议室等功能)</li>
<li>佳速度 5.16.0(iOS15)</li>
<li>美颜相机 9.4.00(最低可用版本)</li>
<li>美图秀秀 6.0.5 7.0.1</li>
<li>FiLMiC Pro ◆6.19.7◆(订阅制前最后一版，内购破解插件适用，851609129)</li>
<li>Halide Mark II ◆1.17.3◆(付费前最后一版，837845559)</li>
<li>搜狗输入法 2.2.1(无搜索) 4.0.0 4.4.0 5.0.1(有剪贴板) 7.2.6(iOS14.7) 10.22</li>
<li>百度输入法 6.0.2(超级皮肤、无剪贴板) 7.1.1(无语音功能)</li>
<li>讯飞输入法 6.0 8.0.2000</li>
<li>UC浏览器 10.5.5(无头条、可缓存视频) 10.7.11(可缓存视频) 11.3.1(可缓存视频、下载文件)</li>
<li>QQ浏览器 6.1.1(可缓存视频) 6.3(可关头条) 8.2.1(免流首版)</li>
<li>夸克浏览器 2.2.9 2.3.1.913(iOS15.6)</li>
<li>Alook 8.2 9.6 11.5</li>
<li>Speedtest China by Ookla 4.2.10(839306602)</li>
<li>DAMA-图片隐私智能打码 1.1.27(意外解锁高级版BUG版本，850202162)</li>
<li>Pixelmator Photo 2.0.12(订阅制前最后一版，850784840)</li>
<li>Pin 3.2.2(完整实验室最后一版) 3.15.1</li>
<li>Keep 5.18.0 7.5.3</li>
<li>小米运动 4.0.3(最低可登录版本)</li>
<li>Strava：跑步、骑行、远足 23.0.0</li>
<li>Widgy Widgets 1.7(iOS14.5)</li>
<li>汽车之家 9.10.6(无法加载车辆详情页)</li>
<li>滴滴出行 5.1(单车首版) 5.2.20(iOS14.5)</li>
<li>彩云天气 6.0.4(深色模式) 6.0.5(iOS14小组件) 6.0.7 6.1.1</li>
<li>彩云天气Pro 5.0.10(收费前最后一版)</li>
<li>白描 2.1.6(无会员限制，无广告)</li>
<li>文件全能王 5.4(音视频嗅探、m3u8下载)</li>
<li>电视助手 5.5.0(音视频下载、导出文件)</li>
<li>WiFi万能钥匙 ◆4.0.2◆(可连共享WiFi)</li>
<li>WiFi管家 2.0.1(可看WiFi密码)</li>
<li>花生地铁 4.4.3(连地铁WiFi，最低可用版本)</li>
<li>电信营业厅 7.0(最低可用版本，打开时勿联网，会闪退) 7.5.2</li>
<li>中国移动 6.1.5</li>
<li>ZOE视频嗅探 1.8.6(下载YouTube视频无版权限制)</li>
<li>Nplayer 3.10.10(此版本过后均衡器会与锁屏冲突，手机锁屏音频会自动停止，无法后台听音频)</li>
<li>Calculator ∞ 5.2(UI大改前最后一版，831702111)</li>
<li>镜子豪华 ◆5.3◆(点击恢复购买可直接去广告)</li>
</ul>
<h2 id="降级方法">降级方法</h2>
<h3 id="手机端">手机端</h3>
<h4 id="未越狱">未越狱</h4>
<p>使用「爱思极速版」即可安装 App 的主要历史版本，但「爱思极速版」未在 App Store 上架，安装方法如下：<br>
电脑端安装「<a href="https://www.i4.cn/" target="_blank" rel="noopener">爱思助手</a>」，USB 连接手机后将自动安装移动客户端「爱思极速版」。<br>
Apple Watch 用户勿使用「爱思助手」或「爱思极速版」安装 App，在 Apple Watch 上无法启动，只能 iTunes 抓包或使用
AppStore++ 安装旧版应用（反馈用户：⑨RealZJMM怪我丑（Plex），测试设备：Apple Watch Series1，系统：watchOS
6）。</p>
<h4 id="已越狱">已越狱</h4>
<p>安装 AppStore++「应用降级」插件，在 AppStore 中长按「获取」按钮即可降级。</p>
<h4 id="系统版本为-1501511">系统版本为 15.0~15.1.1</h4>
<ol>
<li>微信搜索「新有趣工具箱」在线安装 TrollStore</li>
<li>下载 <a href="https://share.initnil.com/d/With_TorllStore/DowngradeApp%5c%28With_TrollStore%5c%29_1.1-6.ipa" target="_blank" rel="noopener">DowngradeApp</a></li>
<li>打开 TrollStore 安装</li>
</ol>
<h3 id="电脑端">电脑端</h3>
<p>「爱思极速版」中未收录意向版本时，需使用电脑端抓包。<br>
iTunes 下载（v12.6.5.3）：<a href="https://support.apple.com/zh-cn/HT208079" target="_blank" rel="noopener">Apple 支持</a><br>
抓包软件下载（发布页：<a href="https://www.52pojie.cn/thread-1284776-1-1.html" target="_blank" rel="noopener">吾爱破解</a>）：<a href="https://wwx.lanzoui.com/iBE4Emzgbkj" target="_blank" rel="noopener">蓝奏云</a></p>
<p>使用方法：</p>
<ol>
<li>下载并安装旧版 iTunes（v12.6.5.3 内置 App Store）；</li>
<li>打开 iTunes，在 iTunes 内登录 Apple ID；</li>
<li>点击由上至下第三行的「♫ 音乐」矩形框，点击「编辑菜单」，勾选「A 应用」，点击「完成」，再次点击「A 应用」完成界面切换；</li>
<li>下载抓包软件，在程序目录下新建一文件夹，用来存放压缩包内的<code>.exe</code>文件，如：<code>D:\Program Files\iOS旧版应用下载</code>（程序初始化后将在同级目录下生成数据文件，因此特地建立文件夹存放）；</li>
<li>打开抓包软件，输入 App 名称，按下回车键搜索；</li>
<li>双击选择要下载的版本；</li>
<li>点击「开始拦截」按钮；</li>
<li>打开 iTunes，在右上方「🔍」标识处键入应用名称；</li>
<li>点击「商店」按钮，选择「在 iTunes Store中搜索“××”」；</li>
<li>根据设备类型选择「iPhone App」或「iPad App」栏目下的程序，点击「获取」或「下载」按钮开始下载；</li>
<li>下载完成后，点击由上至下第三行的「资料库」；</li>
<li>右键应用图标，选择「在 Windows 资源管理器中显示(H)」，即可查看 <code>.ipa</code> 文件；</li>
<li>将安装包备份到你想存放的位置，以备日后使用；</li>
<li>下载并安装「爱思助手」；</li>
<li>打开「爱思助手」，点击左侧列表中的「应用游戏-导入安装」即可安装 <code>.ipa</code> 到设备。</li>
</ol>
<p>注：<br>
软件安装包均与 Apple ID 绑定，如需共享给他人，对方需在 App Store 内登录下载时绑定的 Apple ID，再用电脑导入安装。<br>
添加到 iTunes 下载列表后即可停止拦截，抓取下一软件了。</p>
<h2 id="屏蔽应用内更新提示">屏蔽应用内更新提示</h2>
<ol>
<li>越狱；</li>
<li>安装 <a href="https://apt.cydiabc.top/" target="_blank" rel="noopener">AppSync Unified</a>、<a href="https://yttxcs.com/" target="_blank" rel="noopener">Filza File Manager</a>；</li>
<li>打开 Filza File Manager；</li>
<li>依地址打开 <code>×××</code> 软件安装目录：<code>/private/var/containers/Bundle/Application/×××</code>；</li>
<li>搜索 <code>info.plist</code>，打开大小最大项；</li>
<li>展开 <code>Root</code>，将当前版本号一律改为最新版本号，若版本号为 <code>x.x.x</code>，字符串为 <code>x.x.x.x</code>，则改动版本号对应前三位，最后一位不动。</li>
</ol>
<h2 id="外区id">外区ID</h2>
<p><a href="https://zhuanlan.zhihu.com/p/133273790" target="_blank" rel="noopener">最新&amp;最详细外区AppleID注册教程 - 知乎</a><br>
<a href="https://h9865.cn/" target="_blank" rel="noopener">糖果ios公众号 - 苹果海外appleid分享</a></p>
<h2 id="常见问题">常见问题</h2>
<h3 id="反复卸载安装软件后存储空间大幅减少">反复卸载安装软件后存储空间大幅减少</h3>
<p>安装「小鸭清理」，反复清理几次「手机空间」即可。</p>
<h3 id="版本过低无法登录">版本过低无法登录</h3>
<p>安装新版并登录后，选择以下一种方法：<br>
(1)手机端：进入「设置-通用-iPhone 存储空间」，点击「卸载 App」后，使用「爱思极速版」安装；<br>
(2)电脑端：使用「爱思助手」覆盖安装旧版本。</p>
<p>例：QQ v6.2.2 版因版本过低无法登录，则先使用「爱思极速版」安装可登录的 v7.3.5 版，登录后不卸载，使用「爱思助手」覆盖安装 v6.2.2
版；</p>
<p>注：<br>
尽量在「爱思极速版」中选择版本相近的可登录版本，避免因跨版本数据结构变动过大以致覆盖安装后应用闪退。</p>
<h3 id="itunes-网络出错">iTunes 网络出错</h3>
<p>下载 0kb：添加下载任务到列表后，停止抓包软件拦截并在 iTunes 内点击「暂停下载」，再点击「继续下载」即可恢复。<br>
无法登录：关闭代理软件、抓包软件。<br>
若 iTunes 出现其它网络问题，请退出代理软件。</p>
<h3 id="抓包软件中部分应用查找版本-id-失败">抓包软件中部分应用查找版本 ID 失败</h3>
<ol>
<li>先不要拦截，直接在 iTunes 商店中下载此 APP，等待下载完成；</li>
<li>在抓包软件「iOS旧版应用下载」的「安装管理」中找到对应 IPA 安装包，右键选择「查找版本ID」，即可列出该应用的所有历史版本 ID，版本号从新到旧排序。</li>
</ol>
<p>注：对于「iOS旧版应用下载」中查找到的版本少于「七麦数据」的应用，也可通过上述方法找到对应版本，但版本号需自行推算。<br>
（反馈用户：某年某月某日）</p>
<h3 id="去除app-store-更新提示">去除「App Store 更新提示」</h3>
<p>解包 <code>.ipa</code> 文件，删除 iTunesMetadata.plist。</p>
<h3 id="关闭自动更新">关闭自动更新</h3>
<p>进入「设置-App Store」，关闭「自动下载：App 更新」。</p>
<h3 id="应用体积比-app-store-安装的大">应用体积比 App Store 安装的大</h3>
<p>电脑端「爱思助手」安装的应用可进入「设置-通用-iPhone 存储空间」，点击「卸载
App」再点击「重新安装」以缩小体积；「爱思极速版」安装的应用及删除了<code>iTunesMetadata.plist</code>的应用无法缩小体积。</p>
<h3 id="停止供货">停止供货</h3>
<p>如果抓包版本显示停止供货，则注册一个新的 AppleID，登录 iTunes 后的首次抓包可以抓到停供版本。</p>
<h3 id="tim-降级至首版104方法">TIM 降级至首版（1.0.4）方法</h3>
<ol>
<li>旧版 iTunes 抓包如下四个版本：3.1.1、2.5.1、1.1.6、1.0.4；</li>
<li>使用爱思助手，依次覆盖安装降级：3.1.1→2.5.1→1.1.6→1.0.4；</li>
<li>每次覆盖后，都需要运行程序一次；</li>
<li>如遇某版本闪退，重复打开几次就能解决；</li>
<li>降级至 1.0.4 版本后，进入「设置-通用-iPhone 存储空间」，点击「卸载 App」再点击「重新安装」以缩小应用体积。</li>
</ol>
<h3 id="贡献用户">贡献用户</h3>
<ul>
<li>⑨RealZJMM怪我丑（Plex）</li>
<li>某年某月某日</li>
<li>Sunshine</li>
<li>1053083281</li>
<li>酌酒饮孤单</li>
<li>康晓锋</li>
<li>iuuan</li>
<li>偏执又可爱的me</li>
<li>那時明月</li>
<li>阿立</li>
<li>启示录</li>
</ul>
<h2 id="转载声明">转载声明</h2>
<p><a href="https://qianling.pw/ios-app/" target="_blank" rel="noopener">点击查看原文</a></p>
<p>注：本文版权归原作者所有，此处仅做转载纪录！</p>
]]></content:encoded>
    </item>
    <item>
      <title>抓取快手极速版账号Cookie教程</title>
      <link>https://vccv.cc/article/ksjsb-cookie.html</link>
      <pubDate>Tue, 02 Aug 2022 10:45:10 +0000</pubDate>
      <guid>https://vccv.cc/article/ksjsb-cookie.html</guid>
      <description>这是一篇关于快手极速版抓账号cookie的教程。适用于未root用户以及iOS用户，如果需要相关软件，请自行首页或者评论区联系我，感谢理解。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>这是一篇纯教程文章，经本人整理实践验证。部分内容如有雷同，纯属巧合。</p>
<p>如果需要相关软件，请自行搜索下载，亦或是联系我（包括但不限于评论区留言）。</p>
<p>下面教程正式开始。</p>
<h2 id="前期准备">前期准备</h2>
<p>如果你从来没注册过快手极速版，或者从来没有提现过，那么建议你先在真机里面注册快手并<strong>绑定微信</strong>（位置：快手极速版设置-&gt;账号与安全-&gt;微信），方便提现。</p>
<p>如果你是第二个号想要绑定支付宝的话，也是建议先在真机上登录。因为支付宝<strong>只能在你提现时绑定</strong>，所以真机里面不要退出账号。等在虚拟机（BlackBox或者VMOS Pro之类）里面抓到数据包并且发给我后，我将你的金币刷到能提现的地步时，你再去真机里面提现，提现方式选择支付宝即可。</p>
<h2 id="安卓教程">安卓教程</h2>
<h2 id="blackbox">BLACKBOX</h2>
<p>下面是利用BlackBox抓包的教程，更加简单方便快捷，我更推荐这个方法。</p>
<h3 id="安装软件">安装软件</h3>
<p>BlackBox64或者BlackBox32、HttpCanary、黄鸡防断网模块。</p>
<p>如果你的快手极速版app是32位，就用BlackBox32，64位就用BlackBox64。</p>
<p>不知道的话就都安装上，看哪个能添加快手极速版app就用哪个。</p>
<h3 id="配置blackbox">配置BlackBox</h3>
<ol>
<li>在真机上安装好快手极速版app，然后打开BlackBox软件，点击右下角加号➕添加应用，添加快手极速版。</li>
</ol>
<blockquote>
<p>选择应用时如果没找到快手极速版app，就换成BlackBox32或者BlackBox64。</p>
</blockquote>
<ol start="2">
<li>
<p>点击右上角的三个点，点击软件设置，开启 <strong>启用Xposed框架、隐藏Xposed框架、隐藏Root</strong> 三个功能。</p>
<p><a href="/article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp" data-caption="软件设置">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220803152512767_hu_c7a9e59184a968c2.webp 480w, /article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp 524w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="524"
                    height="1008"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp"
                    srcset="/article/ksjsb-cookie/image-20220803152512767_hu_c7a9e59184a968c2.webp 480w, /article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp 524w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="软件设置"
                    
                />
            </picture>
        </a></p>
<p><a href="/article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp" data-caption="启用功能">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220803152538456_hu_3d50ab9a96374d90.webp 480w, /article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp 504w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="504"
                    height="922"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp"
                    srcset="/article/ksjsb-cookie/image-20220803152538456_hu_3d50ab9a96374d90.webp 480w, /article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp 504w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="启用功能"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>点击模块管理，点加号添加黄鸡防断网模块并<strong>勾选上</strong>。</p>
<p><a href="/article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp" data-caption="添加模块">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220803152602866_hu_c76e4c558436e29b.webp 480w, /article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp 520w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="520"
                    height="950"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp"
                    srcset="/article/ksjsb-cookie/image-20220803152602866_hu_c76e4c558436e29b.webp 480w, /article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp 520w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="添加模块"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>重启BlackBox两次（打开再关闭BlackBox多几次）。</p>
</li>
</ol>
<h3 id="目标应用">目标应用</h3>
<p>打开抓包软件，点击 <strong>设置-&gt;目标应用</strong>，点击右上角加号➕，选择你的虚拟机应用BlackBox即可。（图是下面步骤拿上来的，这里你只要选对软件就可以了。注意看清楚到底是BlackBox32还是BlackBox64。）</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp" data-caption="目标应用">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_17209a37eb2f3036.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_c193a31b46c665d1.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="418"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_17209a37eb2f3036.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_c193a31b46c665d1.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="目标应用"
                    
                />
            </picture>
        </a></p>
<h3 id="url关键词">Url关键词</h3>
<p>回到抓包软件主页面，点击右上角搜索（放大镜图标🔍），划到最下面，点击 <strong>Url关键词</strong> 并输入 <code>salt</code>。</p>
<p>注意：这一步尤其重要，请务必输入正确。</p>
<blockquote>
<p>抓包软件如果被清除了后台，这一步需要重新进行！！！</p>
</blockquote>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp" data-caption="url关键词salt">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_1fb9e3dab54df35b.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_d46fd542b6617bdd.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="474"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_1fb9e3dab54df35b.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_d46fd542b6617bdd.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="url关键词salt"
                    
                />
            </picture>
        </a></p>
<h3 id="开始抓包">开始抓包</h3>
<p>再次返回到软件主页面，点击 <strong>右下角的小飞机图标</strong> 即可开始抓包。</p>
<p><a href="/article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp" data-caption="开始抓包">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220803153019696_hu_1cf64d0cb37126e7.webp 480w, /article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp 570w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="570"
                    height="1072"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp"
                    srcset="/article/ksjsb-cookie/image-20220803153019696_hu_1cf64d0cb37126e7.webp 480w, /article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp 570w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="开始抓包"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>如果提示需要安装证书，即可以安装也可以不安装。</p>
<p>如果后面你没有抓到数据包或是担心抓不到，这里的话安装上也没问题（我是没有安装也抓到数据包了的）。</p>
</blockquote>
<h3 id="登录快手">登录快手</h3>
<p>进入到BlackBox中，打开快手极速版（注意是打开<strong>BlackBox中的快手极速版</strong>，不是真机的）。请务必确保这是我们<strong>第一次打开</strong>，处于未登录状态。</p>
<p>按照正常流程用<strong>手机号验证码登录</strong>即可。登录成功后，点击快手极速版的设置-&gt;账号与安全-&gt;微信，<strong>绑定微信</strong>，也可以等提现的时候绑定微信或者支付宝。</p>
<blockquote>
<p>注意：</p>
<p>如果<strong>输入手机号没反应</strong>或者<strong>输入验证码没反应</strong>，杀掉BlackBox后台再重新打开。</p>
<p>如果<strong>没抓到数据</strong>或者<strong>安全验证不能通过</strong>的话，建议<strong>卸载BlackBox中的快手极速版</strong>，再杀掉相关软件后台，重新添加快手极速版，打开抓包软件并登录快手。</p>
</blockquote>
<h3 id="抓包成功">抓包成功</h3>
<p>如果前面一切正常的话，这时我们回到抓包软件，就会发现已经有数据了。</p>
<p><a href="/article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp" data-caption="抓到数据包">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220803153132284_hu_d06ff7f2442687ab.webp 480w, /article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp 518w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="518"
                    height="1122"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp"
                    srcset="/article/ksjsb-cookie/image-20220803153132284_hu_d06ff7f2442687ab.webp 480w, /article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp 518w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="抓到数据包"
                    
                />
            </picture>
        </a></p>
<h3 id="保存请求">保存请求</h3>
<p>随便选择一个点击进去，点击请求，右上角保存，选择保存请求。</p>
<p><a href="/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp" data-caption="保存请求">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220802122359062_hu_45f48a2adb5fe56.webp 480w, /article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp 720w, /article/ksjsb-cookie/image-20220802122359062_hu_acbc1c605a5d93a6.webp 960w, /article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1399"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp"
                    srcset="/article/ksjsb-cookie/image-20220802122359062_hu_45f48a2adb5fe56.webp 480w, /article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp 720w, /article/ksjsb-cookie/image-20220802122359062_hu_acbc1c605a5d93a6.webp 960w, /article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="保存请求"
                    
                />
            </picture>
        </a></p>
<h3 id="发送文件">发送文件</h3>
<p>文件被保存在 <code>HttpCanary-&gt;download</code> 目录下，选择时间最新的文件发给我即可（在自带的文件管理器进行都可以，不一定要MT管理器）。</p>
<p>注意：此时可能会出现两个文件，一个header结尾，一个raw结尾，发送给我<strong>header结尾</strong>文件。</p>
<p><a href="/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp" data-caption="找到header文件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220802122429599_hu_86c3c5ba6eaf7407.webp 480w, /article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp 720w, /article/ksjsb-cookie/image-20220802122429599_hu_6334694aeccbb8.webp 960w, /article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="573"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp"
                    srcset="/article/ksjsb-cookie/image-20220802122429599_hu_86c3c5ba6eaf7407.webp 480w, /article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp 720w, /article/ksjsb-cookie/image-20220802122429599_hu_6334694aeccbb8.webp 960w, /article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="找到header文件"
                    
                />
            </picture>
        </a></p>
<h3 id="善后工作">善后工作</h3>
<p>抓到数据包后，这些软件就都可以杀掉后台并关闭了。</p>
<p>切记不要在退出登录快手极速版账号，这会导致数据失效。把这些软件放在一旁不管就可以了。</p>
<h3 id="创第二个虚拟机">创第二个虚拟机</h3>
<p>如果你需要再抓第二个快手极速版账号的包，再次提醒<strong>不要退出登录第一个账号</strong>。</p>
<p>正确的做法是<strong>再添加一个虚拟机空间</strong>并重复以上在BlackBox中进行的操作。</p>
<p>在BlackBox首页左滑即可进入第二个空间：</p>
<p><a href="/article/ksjsb-cookie/image-20220803182922295_hu_e02035aa4a3f6f7f.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220803182922295_hu_e02035aa4a3f6f7f.webp" data-caption="账号1">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220803182922295_hu_b99994bf1b753fdf.webp 480w, /article/ksjsb-cookie/image-20220803182922295_hu_bb35ba13e65d8d69.webp 720w, /article/ksjsb-cookie/image-20220803182922295_hu_e02035aa4a3f6f7f.webp 886w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="886"
                    height="1848"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220803182922295_hu_bb35ba13e65d8d69.webp"
                    srcset="/article/ksjsb-cookie/image-20220803182922295_hu_b99994bf1b753fdf.webp 480w, /article/ksjsb-cookie/image-20220803182922295_hu_bb35ba13e65d8d69.webp 720w, /article/ksjsb-cookie/image-20220803182922295_hu_e02035aa4a3f6f7f.webp 886w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="账号1"
                    
                />
            </picture>
        </a></p>
<p><a href="/article/ksjsb-cookie/image-20220803182943032_hu_60c294744779da46.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220803182943032_hu_60c294744779da46.webp" data-caption="账号2">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220803182943032_hu_65757c6d51e85e4e.webp 480w, /article/ksjsb-cookie/image-20220803182943032_hu_80b150de8f1c3ab6.webp 720w, /article/ksjsb-cookie/image-20220803182943032_hu_60c294744779da46.webp 886w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="886"
                    height="1849"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220803182943032_hu_80b150de8f1c3ab6.webp"
                    srcset="/article/ksjsb-cookie/image-20220803182943032_hu_65757c6d51e85e4e.webp 480w, /article/ksjsb-cookie/image-20220803182943032_hu_80b150de8f1c3ab6.webp 720w, /article/ksjsb-cookie/image-20220803182943032_hu_60c294744779da46.webp 886w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="账号2"
                    
                />
            </picture>
        </a></p>
<p>其他的操作都是差不多的。</p>
<blockquote>
<p>注意：</p>
<p>第二个账号与第一个账号的登录手机号不能相同，提现方式也不能相同。如果你绑定了微信且没有第二个微信号，则可以先抓包到数据发送给我，等我刷完金币，你再在提现时绑定支付宝。</p>
</blockquote>
<h2 id="vmos-pro">VMOS PRO</h2>
<p>下面是利用VMOS Pro抓包的教程，复杂一些，但是与真机隔离效果更好，适合较多账号。</p>
<h3 id="安装软件-1">安装软件</h3>
<p>下载HttpCanary（抓包） VMOS Pro（虚拟机，root权限）MT管理器（文件管理）并安装。</p>
<p>只有抓包软件有版本要求，需要能够导出系统证书。我用的<strong>v9.2.8.1</strong>。</p>
<h3 id="导出证书">导出证书</h3>
<p>打开抓包软件，在 <strong>设置-&gt;SSL证书设置-&gt;导出HttpCanary根证书-&gt;System Trusted(.0)</strong> 可以找到。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e5c24953fade25cf.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e5c24953fade25cf.webp" data-caption="导出证书">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_84e04bb009ad92b7.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e4982c7f459368ad.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_c1a9f8f1f61b0755.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e5c24953fade25cf.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1394"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e4982c7f459368ad.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_84e04bb009ad92b7.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e4982c7f459368ad.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_c1a9f8f1f61b0755.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e5c24953fade25cf.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="导出证书"
                    
                />
            </picture>
        </a></p>
<p>记住下面的路径，通常是在 <code>HttpCanary/cert</code> 目录。</p>
<h3 id="创建虚拟机">创建虚拟机</h3>
<p>打开VMOS Pro，直接选择第二个就可以，它会默认安装安卓7.1.2版本的虚拟机。</p>
<p><a href="/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_b35b2f05e9bded5e.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_b35b2f05e9bded5e.webp" data-caption="创建虚拟机">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_c1c6202bd293b962.webp 480w, /article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_eaad758c0f6a9758.webp 720w, /article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_77c7137508c445f1.webp 960w, /article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_b35b2f05e9bded5e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="2400"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_eaad758c0f6a9758.webp"
                    srcset="/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_c1c6202bd293b962.webp 480w, /article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_eaad758c0f6a9758.webp 720w, /article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_77c7137508c445f1.webp 960w, /article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_b35b2f05e9bded5e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="创建虚拟机"
                    
                />
            </picture>
        </a></p>
<h3 id="导入文件">导入文件</h3>
<p>进入虚拟机，点击最下面dock栏中间的 <strong>添加</strong> 图标，将快手极速版、MT管理器以及上一步的<strong>系统证书文件</strong>导入进虚拟机中。软件会自动安装在虚拟机上。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_3595fccf2ebd974.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_3595fccf2ebd974.webp" data-caption="导入文件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_cb34be6e00d4ac92.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_4812168dfb68cabf.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_5406949d50d1240b.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_3595fccf2ebd974.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="2340"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_4812168dfb68cabf.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_cb34be6e00d4ac92.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_4812168dfb68cabf.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_5406949d50d1240b.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_3595fccf2ebd974.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="导入文件"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>特别注意：</p>
<p>请检查是否导入了证书文件。后面步骤有人反映 <code>VMOSfiletransferstation</code> 目录没有文件，那是因为你没有导入这个证书文件！</p>
<p><a href="/article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp" data-caption="导入证书">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220803112457171_hu_286b39b1cc5501f0.webp 480w, /article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp 540w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="540"
                    height="321"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp"
                    srcset="/article/ksjsb-cookie/image-20220803112457171_hu_286b39b1cc5501f0.webp 480w, /article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp 540w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="导入证书"
                    
                />
            </picture>
        </a></p>
</blockquote>
<h3 id="获取root权限">获取ROOT权限</h3>
<p>继续打开虚拟机中 <strong>设置</strong> 图标，将选项 <strong>超级用户</strong> 打开，与此同时桌面会出现一个名为 <strong>超级用户</strong> 的软件，意味着获取root权限成功。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_25c5754a659f5275.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_25c5754a659f5275.webp" data-caption="获取root权限">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_6345a00d4f97eb06.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_396fde2c2f13d199.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_5f4ca67b647f6b78.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_25c5754a659f5275.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1573"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_396fde2c2f13d199.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_6345a00d4f97eb06.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_396fde2c2f13d199.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_5f4ca67b647f6b78.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_25c5754a659f5275.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="获取root权限"
                    
                />
            </picture>
        </a></p>
<h3 id="授予权限">授予权限</h3>
<p>还是在虚拟机中，打开<strong>MT管理器</strong>，这时候会弹出是否允许超级用户请求。建议勾选永久记住，点击<strong>允许</strong>。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_93380f20826e70fe.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_93380f20826e70fe.webp" data-caption="同意请求">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_d9ba8509921f081d.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_4eb7b4961e0e0aa9.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_1f8fe0800b555f8c.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_93380f20826e70fe.webp 1070w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1070"
                    height="2113"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_4eb7b4961e0e0aa9.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_d9ba8509921f081d.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_4eb7b4961e0e0aa9.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_1f8fe0800b555f8c.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_93380f20826e70fe.webp 1070w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="同意请求"
                    
                />
            </picture>
        </a></p>
<h3 id="移动证书">移动证书</h3>
<p>然后在左边找到 <code>VMOSfiletransferstation</code> 文件夹，右边找到 <code>system</code> 文件夹。如果没有system文件夹，是因为MT管理器没能成功获取到ROOT权限，建议回到上一步，重新操作。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_187659adfe773a22.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_187659adfe773a22.webp" data-caption="选择文件夹">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_10bfc95e1418422c.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_1310ff4feea64b39.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_2d9b105cefb2f3c3.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_187659adfe773a22.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="805"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_1310ff4feea64b39.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_10bfc95e1418422c.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_1310ff4feea64b39.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_2d9b105cefb2f3c3.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_187659adfe773a22.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="选择文件夹"
                    
                />
            </picture>
        </a></p>
<p>右边依次找到 <code>system-&gt;etc-&gt;security-&gt;cacerts</code> 目录。左边点进去，就是我们的系统证书文件。</p>
<p>此时长按左边证书文件，点击 <strong>复制</strong> 即可。右边目录便会多一个证书文件。你的证书文件的文件名与我不同是正常的。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_e854dbb7e0f31a61.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_e854dbb7e0f31a61.webp" data-caption="复制证书">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_c30f1ea2295dbb83.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8519b62f103c0cfe.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8f2c4fe5420cef8f.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_e854dbb7e0f31a61.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1492"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8519b62f103c0cfe.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_c30f1ea2295dbb83.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8519b62f103c0cfe.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8f2c4fe5420cef8f.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_e854dbb7e0f31a61.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="复制证书"
                    
                />
            </picture>
        </a></p>
<h3 id="目标应用-1">目标应用</h3>
<p>这时候我们<strong>回到真机</strong>，打开抓包软件，点击 <strong>设置-&gt;目标应用</strong>，点击右上角加号➕，选择你的虚拟机应用VMOS Pro即可。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp" data-caption="目标应用">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_17209a37eb2f3036.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_c193a31b46c665d1.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="418"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_17209a37eb2f3036.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_c193a31b46c665d1.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="目标应用"
                    
                />
            </picture>
        </a></p>
<h3 id="url关键词-1">Url关键词</h3>
<p>回到抓包软件主页面，点击右上角搜索（放大镜图标🔍），划到最下面，点击 <strong>Url关键词</strong> 并输入 <code>salt</code>。</p>
<p>注意：这一步尤其重要，请务必输入正确。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp" data-caption="url关键词salt">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_1fb9e3dab54df35b.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_d46fd542b6617bdd.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="474"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_1fb9e3dab54df35b.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_d46fd542b6617bdd.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="url关键词salt"
                    
                />
            </picture>
        </a></p>
<h3 id="开始抓包-1">开始抓包</h3>
<p>再次返回到软件主页面，点击 <strong>右下角的小飞机图标</strong> 即可开始抓包。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_2251f3ddbbc94688.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_2251f3ddbbc94688.webp" data-caption="开始抓包">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_5a5fad7fddf3d30.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_3b5e1780ac1be344.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_f9da78105dad4773.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_2251f3ddbbc94688.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="2254"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_3b5e1780ac1be344.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_5a5fad7fddf3d30.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_3b5e1780ac1be344.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_f9da78105dad4773.webp 960w, /article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_2251f3ddbbc94688.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="开始抓包"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>这里提一句，如果你是root用户，就可以直接在真机里面移动证书，不需要虚拟机里面操作，甚至虚拟机都不需要安装。</p>
<p>另外，软件最上面提示 安装根证书抓取SSL数据包 对于非root用户是正常的，无需理会。</p>
</blockquote>
<h3 id="登录快手-1">登录快手</h3>
<p>进入到虚拟机中，打开快手极速版。请务必确保这是我们<strong>第一次打开</strong>，处于未登录状态。</p>
<p>按照正常流程用<strong>手机号验证码登录</strong>即可。登录成功后，点击快手极速版的设置-&gt;账号与安全-&gt;微信，<strong>绑定微信</strong>即可。也可以等提现的时候绑定微信或者支付宝。</p>
<blockquote>
<p>注意：</p>
<p>如果出现登录不成功、点击登录无反应、登录验证失败等异常情况，</p>
<p>建议彻底杀掉所有相关软件后台重试，或者换个时间段再尝试登录抓包。</p>
<p>还有种方法，随缘能抓到：登录状态下，关闭虚拟机。等一段时间（半个小时都行），打开抓包，开启虚拟机，打开快手极速版软件的一瞬间就抓到了。</p>
</blockquote>
<h3 id="抓包成功-1">抓包成功</h3>
<p>如果前面一切正常的话，这时我们回到抓包软件，就会发现已经显示了3行数据，每个差不多2.8kB左右。</p>
<p><a href="/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_e7d56485bcebf894.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_e7d56485bcebf894.webp" data-caption="抓到数据包">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_7b18d82d048f1b03.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_40777dac2f12c60c.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_e7d56485bcebf894.webp 864w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="864"
                    height="633"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_40777dac2f12c60c.webp"
                    srcset="/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_7b18d82d048f1b03.webp 480w, /article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_40777dac2f12c60c.webp 720w, /article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_e7d56485bcebf894.webp 864w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="抓到数据包"
                    
                />
            </picture>
        </a></p>
<h3 id="保存请求-1">保存请求</h3>
<p>随便选择一个点击进去，点击请求，右上角保存，选择保存请求。</p>
<p><a href="/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp" data-caption="保存请求">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220802122359062_hu_45f48a2adb5fe56.webp 480w, /article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp 720w, /article/ksjsb-cookie/image-20220802122359062_hu_acbc1c605a5d93a6.webp 960w, /article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1399"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp"
                    srcset="/article/ksjsb-cookie/image-20220802122359062_hu_45f48a2adb5fe56.webp 480w, /article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp 720w, /article/ksjsb-cookie/image-20220802122359062_hu_acbc1c605a5d93a6.webp 960w, /article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="保存请求"
                    
                />
            </picture>
        </a></p>
<h3 id="发送文件-1">发送文件</h3>
<p>文件被保存在 <code>HttpCanary-&gt;download</code> 目录下，选择时间最新的文件发给我即可。</p>
<p>注意：此时可能会出现两个文件，一个header结尾，一个raw结尾，发送给我<strong>header结尾</strong>文件。</p>
<p><a href="/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp" data-fancybox="gallery" data-src="/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp" data-caption="找到header文件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ksjsb-cookie/image-20220802122429599_hu_86c3c5ba6eaf7407.webp 480w, /article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp 720w, /article/ksjsb-cookie/image-20220802122429599_hu_6334694aeccbb8.webp 960w, /article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="573"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp"
                    srcset="/article/ksjsb-cookie/image-20220802122429599_hu_86c3c5ba6eaf7407.webp 480w, /article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp 720w, /article/ksjsb-cookie/image-20220802122429599_hu_6334694aeccbb8.webp 960w, /article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="找到header文件"
                    
                />
            </picture>
        </a></p>
<h2 id="ios教程">iOS教程</h2>
<blockquote>
<p>本人环境 iOS：</p>
<p>已越狱，系统版本：iOS14.2.1</p>
<p>软件：Crane（越狱插件，类似多开）Thor（抓包，付费）Stream（抓包，免费）</p>
</blockquote>
<p>待续</p>
]]></content:encoded>
    </item>
    <item>
      <title>Twikoo评论区图片使用Fancybox</title>
      <link>https://vccv.cc/article/fancybox-twikoo.html</link>
      <pubDate>Wed, 13 Jul 2022 14:38:25 +0000</pubDate>
      <guid>https://vccv.cc/article/fancybox-twikoo.html</guid>
      <description>今年年初我写下了一遍文章介绍cactus主题如何引用fancybox插件，后面我又将博客的评论系统换成了twikoo。恰巧今天升级版本，读到文档里的一篇博文：集成 Twikoo 与 lightGallery 插件，实现评论图片的点击放大。一想自己刚好安装有fancybox，于是决定集成twikoo与fancybox。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>今年年初我写下了<a href="https://vccv.cc/article/fancybox-cactus.html" target="_blank" rel="noopener">这篇文章</a>介绍cactus主题如何引用fancybox插件，后面我又将博客的评论系统换成了<a href="https://twikoo.js.org/" target="_blank" rel="noopener">twikoo</a>。恰巧今天升级版本，读到文档里的一篇博文：<a href="https://www.imaegoo.com/2021/twikoo-lightgallery/" target="_blank" rel="noopener">集成 Twikoo 与 lightGallery 插件，实现评论图片的点击放大</a>。一想自己刚好安装有fancybox，何不集成twikoo与fancybox呢？</p>
<h2 id="经过">经过</h2>
<p>依据作者的思路，只需要找到 <code>twikoo.init</code> 代码所在位置，进行修改。原代码我就不贴上来了，主要说说自己修改了什么。</p>
<p>先放最终结果：</p>
<h3 id="最终成果">最终成果</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="nx">twikoo</span><span class="p">.</span><span class="nx">init</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// envId: &#39;abcdef&#39;,
</span></span></span><span class="line"><span class="cl">  <span class="c1">// ...
</span></span></span><span class="line"><span class="cl">  <span class="nx">onCommentLoaded</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">commentContents</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="s1">&#39;tk-content&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">commentContents</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kd">var</span> <span class="nx">commentItem</span> <span class="o">=</span> <span class="nx">commentContents</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="kd">var</span> <span class="nx">imgEls</span> <span class="o">=</span> <span class="nx">commentItem</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">&#39;img&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">imgEls</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o">&lt;</span> <span class="nx">imgEls</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="kd">var</span> <span class="nx">imgEl</span> <span class="o">=</span> <span class="nx">imgEls</span><span class="p">[</span><span class="nx">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">          <span class="c1">// 判断是表情还是正常图片
</span></span></span><span class="line"><span class="cl">          <span class="k">if</span> <span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">className</span> <span class="o">!=</span> <span class="s1">&#39;tk-owo-emotion&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kd">var</span> <span class="nx">aEl</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-fancybox&#39;</span><span class="p">,</span> <span class="s1">&#39;gallery&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-src&#39;</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;src&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-caption&#39;</span><span class="p">,</span> <span class="s1">&#39;评论区：&#39;</span><span class="o">+</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;alt&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">cloneNode</span><span class="p">(</span><span class="kc">false</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">imgEl</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">aEl</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">nextSibling</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">imgEl</span><span class="p">.</span><span class="nx">remove</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>下面来具体说说怎么修改成这样的。毕竟大家的主题基本上都不一样，但思路通用。</p>
<h3 id="读原代码">读原代码</h3>
<p>这里我还是贴上来了，方便看些。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="nx">twikoo</span><span class="p">.</span><span class="nx">init</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// envId: &#39;abcdef&#39;,
</span></span></span><span class="line"><span class="cl">  <span class="c1">// ...
</span></span></span><span class="line"><span class="cl">  <span class="nx">onCommentLoaded</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">commentContents</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="s1">&#39;tk-content&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">commentContents</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kd">var</span> <span class="nx">commentItem</span> <span class="o">=</span> <span class="nx">commentContents</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="kd">var</span> <span class="nx">imgEls</span> <span class="o">=</span> <span class="nx">commentItem</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">&#39;img&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">imgEls</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o">&lt;</span> <span class="nx">imgEls</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="kd">var</span> <span class="nx">imgEl</span> <span class="o">=</span> <span class="nx">imgEls</span><span class="p">[</span><span class="nx">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">          <span class="kd">var</span> <span class="nx">aEl</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;class&#39;</span><span class="p">,</span> <span class="s1">&#39;tk-lg-link&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;href&#39;</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;src&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">          <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-src&#39;</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;src&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">          <span class="nx">aEl</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">cloneNode</span><span class="p">(</span><span class="kc">false</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">          <span class="nx">imgEl</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">aEl</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">nextSibling</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="nx">imgEl</span><span class="p">.</span><span class="nx">remove</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="nx">lightGallery</span><span class="p">(</span><span class="nx">commentItem</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">selector</span><span class="o">:</span> <span class="s1">&#39;.tk-lg-link&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">share</span><span class="o">:</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>大体思路是找到评论区(tk-content)里面的图片资源(img)，然后遍历每个img标签，拼凑出一个符合插件格式的新的 <code>&lt;a&gt;</code> 标签，将原 <code>&lt;img&gt;</code> 放在新的 <code>&lt;a&gt;</code> 里面，再将原img删除即可。</p>
<blockquote>
<p>所以这里也可以拓展成其他的插件，只是格式不同而已：</p>
<p>lightgallery:</p>
<p><code>&lt;a class=&quot;tk-lg-link&quot; data-src=&quot;xxx.png&quot; href=&quot;xxx.png&quot;&gt;&lt;img src=&quot;xxx.png&quot; alt=&quot;xxx&quot;&gt;&lt;/a&gt;</code></p>
<p>fancybox:</p>
<p><code>&lt;a data-fancybox=&quot;gallery&quot; data-src=&quot;xxx.png&quot; data-caption=&quot;xxx&quot;&gt;&lt;img src=&quot;xxx.png&quot; alt=&quot;xxx&quot;&gt;&lt;/a&gt;</code></p>
</blockquote>
<h3 id="修改标签">修改标签</h3>
<p>我们依样画葫芦，将对应的标签修改成正确的格式即可。</p>
<p>例如：lightgallery需要的是 <code>class=&quot;tk-lg-link&quot;</code> ，但是fancybox需要的是 <code>data-fancybox=&quot;gallery&quot;</code> ，我们将原代码的 <code>aEl.setAttribute('class', 'tk-lg-link');</code> 修改为 <code>aEl.setAttribute('data-fancybox', 'gallery');</code> ，诸如此类。</p>
<h3 id="删除无用代码">删除无用代码</h3>
<p>紧跟着刚才的代码，下面还有一段：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="nx">lightGallery</span><span class="p">(</span><span class="nx">commentItem</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">selector</span><span class="o">:</span> <span class="s1">&#39;.tk-lg-link&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">share</span><span class="o">:</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这个也应该是lightgallery所需要的，fancybox并不需要，在这里我直接删除了。</p>
<p>以上两处修改好后，我们就可以运行一遍试试看结果如何了。不出意外的，又发现了新的问题。</p>
<h3 id="评论区图片与表情">评论区图片与表情</h3>
<p>如下图所示，我发现当评论区使用表情时，表情也是 <code>&lt;img&gt;</code> 包裹的png图片资源，表情理所当然的也会应用上fancybox插件，但是我觉得这是没有必要的，算是个bug？</p>
<p><a href="/article/fancybox-twikoo/image-20220713151533510_hu_58b21c6aa44abb16.webp" data-fancybox="gallery" data-src="/article/fancybox-twikoo/image-20220713151533510_hu_58b21c6aa44abb16.webp" data-caption="emoji也是png">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/fancybox-twikoo/image-20220713151533510_hu_df389db3b97e399c.webp 480w, /article/fancybox-twikoo/image-20220713151533510_hu_ed935a9a4e7cd48e.webp 720w, /article/fancybox-twikoo/image-20220713151533510_hu_58b21c6aa44abb16.webp 942w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="942"
                    height="514"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/fancybox-twikoo/image-20220713151533510_hu_ed935a9a4e7cd48e.webp"
                    srcset="/article/fancybox-twikoo/image-20220713151533510_hu_df389db3b97e399c.webp 480w, /article/fancybox-twikoo/image-20220713151533510_hu_ed935a9a4e7cd48e.webp 720w, /article/fancybox-twikoo/image-20220713151533510_hu_58b21c6aa44abb16.webp 942w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="emoji也是png"
                    
                />
            </picture>
        </a></p>
<p>于是我们便要找到emoji表情图片与普通图片的差别，把它们区分出来，分别做处理。</p>
<h3 id="处理emoji">处理emoji</h3>
<p>可以很容易的发现，emoji表情在twikoo下会打上 <code>class=&quot;tk-owo-emotion&quot;</code> 。我们只需要做一个简单的判断就可以很好的解决这个问题了：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">className</span> <span class="o">!=</span> <span class="s1">&#39;tk-owo-emotion&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// 普通图片
</span></span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// emoji
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>因为我们只需要处理普通图片，emoji不处理，所以代码中就没有else分支语句。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">className</span> <span class="o">!=</span> <span class="s1">&#39;tk-owo-emotion&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kd">var</span> <span class="nx">aEl</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-fancybox&#39;</span><span class="p">,</span> <span class="s1">&#39;gallery&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-src&#39;</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;src&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-caption&#39;</span><span class="p">,</span> <span class="s1">&#39;评论区：&#39;</span><span class="o">+</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;alt&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">cloneNode</span><span class="p">(</span><span class="kc">false</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">imgEl</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">aEl</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">nextSibling</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">imgEl</span><span class="p">.</span><span class="nx">remove</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>最后我们还需要找对判断位置，就是在<strong>第二个for循环</strong>的里面，看最上面的代码位置即可。</p>
<h2 id="成果">成果</h2>
<p><a href="/article/fancybox-twikoo/image-20220713153543806_hu_9b4f75bc6ca3b21.webp" data-fancybox="gallery" data-src="/article/fancybox-twikoo/image-20220713153543806_hu_9b4f75bc6ca3b21.webp" data-caption="最终成果">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/fancybox-twikoo/image-20220713153543806_hu_a768fe61115f769f.webp 480w, /article/fancybox-twikoo/image-20220713153543806_hu_368747c6341d6d9c.webp 720w, /article/fancybox-twikoo/image-20220713153543806_hu_bcd3e397ec76c272.webp 960w, /article/fancybox-twikoo/image-20220713153543806_hu_6e486905bf5d9e61.webp 1440w, /article/fancybox-twikoo/image-20220713153543806_hu_9b4f75bc6ca3b21.webp 2750w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2750"
                    height="1570"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/fancybox-twikoo/image-20220713153543806_hu_368747c6341d6d9c.webp"
                    srcset="/article/fancybox-twikoo/image-20220713153543806_hu_a768fe61115f769f.webp 480w, /article/fancybox-twikoo/image-20220713153543806_hu_368747c6341d6d9c.webp 720w, /article/fancybox-twikoo/image-20220713153543806_hu_bcd3e397ec76c272.webp 960w, /article/fancybox-twikoo/image-20220713153543806_hu_6e486905bf5d9e61.webp 1440w, /article/fancybox-twikoo/image-20220713153543806_hu_9b4f75bc6ca3b21.webp 2750w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="最终成果"
                    
                />
            </picture>
        </a></p>
<p>不得不说老师画的图确实好看（狗头）。</p>
<h2 id="感谢">感谢</h2>
<p><a href="https://www.imaegoo.com/2021/twikoo-lightgallery/" target="_blank" rel="noopener">iMaeGoo</a></p>
<p><a href="https://twikoo.js.org/" target="_blank" rel="noopener">twikoo</a></p>
<p><a href="https://fancyapps.com/fancybox/" target="_blank" rel="noopener">fancybox</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>解决EasyConnect的毒瘤行为</title>
      <link>https://vccv.cc/article/docker-easyconnect.html</link>
      <pubDate>Fri, 08 Jul 2022 15:29:12 +0000</pubDate>
      <guid>https://vccv.cc/article/docker-easyconnect.html</guid>
      <description>放假在家，连接学校内网需要使用深信服家的EasyConnect，我偶尔需要连接学校的服务器或者访问内网网页，便打算下载使用。但是！！！EasyConnect这个软件比较流氓，也就是常说的毒瘤软件，我便开始寻找起了应对方法。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>放假在家，连接学校内网需要使用深信服家的 <strong>EasyConnect</strong> ，我偶尔需要连接学校的服务器或者访问内网网页，便打算下载使用。</p>
<p>但是！！！EasyConnect 这个软件比较流氓，也就是常说的毒瘤软件。我便开始寻找起了应对方法。</p>
<blockquote>
<p>在 macOS下，EasyConnect 主要有以下行为：</p>
<ol>
<li>后台常驻进程 EasyMonitor 和 ECAgentProxy，且都以 root 权限运行；</li>
<li>自动安装根证书，包括系统根证书与 FireFox 的根证书，且在删除后会重新安装。</li>
</ol>
<p>ps：以 <em>root</em> 权限常驻进程，意味着这些进程可以读取和写入任何东西；安装根证书，意味着可以直接进行中间人攻击，随意篡改数据。</p>
</blockquote>
<h2 id="法1">法1</h2>
<p>该方法适合已安装 EasyConnect 的电脑，最少折腾。</p>
<ol>
<li>
<p>使用 <code>sudo su</code> 获取管理员权限；</p>
</li>
<li>
<p>删除（rm）</p>
<p>/Library/LaunchDaemons/com.sangfor.EasyMonitor.plist；</p>
</li>
<li>
<p>删除 /Library/LaunchAgents/com.sangfor.ECAgentProxy.plist；</p>
</li>
<li>
<p>重新启动 Mac；</p>
</li>
<li>
<p>打开钥匙串，删除系统钥匙串-系统-证书下面的证书（关键词 sangfor）。</p>
</li>
</ol>
<blockquote>
<p>注意一定要 <em>先重启Mac再删除证书</em> ，因为在后台的 EasyMonitor 进程会在证书被删除后自动导入。</p>
</blockquote>
<p>这样就消除了 EasyConnect 的问题。但是，目前为止会导致 EasyConnect 不能连接，因此我们需要用安全的方式启动 EasyConnect。可以编写两个脚本实现启动和退出。</p>
<p><strong>startEasyConnect.sh</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#! /bin/bash
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">/Applications/EasyConnect.app/Contents/Resources/bin/EasyMonitor &gt; /dev/null 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">&amp;</span>
</span></span><span class="line"><span class="cl">/Applications/EasyConnect.app/Contents/MacOS/EasyConnect &gt; /dev/null 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">&amp;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>killEasyMonitor.sh</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#! /bin/bash
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">pkill EasyMonitor
</span></span><span class="line"><span class="cl">pkill ECAgent
</span></span><span class="line"><span class="cl">pkill ECAgentProxy
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>2025.3.24更新：</p>
<p>如果普通用户不能直接pkill上述三个进程，可以尝试<code>sudo pkill -9 -f “EasyConnect”</code>等方式强制杀死进程。感谢@Jeblqr。</p>
<p>再次提醒，本人还是更加建议使用docker容器运行，详见<a href="#%E6%B3%952%E6%8E%A8%E8%8D%90">法2（推荐）</a>。毕竟动用sudo需要手动输入密码，可能会比较麻烦。</p>
</blockquote>
<p>将上述两个脚本放到 <code>PATH</code> 路径下，并给予可执行权限：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">chmod +x startEasyConnect.sh
</span></span><span class="line"><span class="cl">chmod +x killEasyMonitor.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>在需要使用 EasyConnect 时，使用 <strong>普通用户</strong> 身份执行 <code>startEasyConnect</code> 命令（EasyMonitor 进程就没有权限导入根证书了）。退出 EasyConnect 后，执行 <code>killEasyMonitor</code> 杀掉后台的 EasyMonitor 进程即可。</p>
<h2 id="法2推荐">法2（推荐）</h2>
<p>适合还未安装 EasyConnect 的情况下，并且具有一些Docker知识，不怕麻烦的。（正在使用）</p>
<h3 id="安装docker">安装Docker</h3>
<blockquote>
<p>2022.12.05 更新：</p>
<p>推荐macOS用户使用Colima安装docker运行环境，<a href="https://vccv.cc/article/docker-macos.html" target="_blank" rel="noopener">点击查看</a>。</p>
</blockquote>
<p><a href="https://docs.docker.com/desktop/windows/install/" target="_blank" rel="noopener">Windows</a></p>
<p><del><a href="https://docs.docker.com/desktop/mac/install/" target="_blank" rel="noopener">macOS</a></del></p>
<h3 id="安装clash">安装Clash</h3>
<p><a href="https://github.com/Fndroid/clash_for_windows_pkg/releases" target="_blank" rel="noopener">Windows</a></p>
<p>macOS也可以安装 <a href="https://github.com/yichengchen/clashX/releases" target="_blank" rel="noopener">ClashX</a> 或者 <a href="https://install.appcenter.ms/users/clashx/apps/clashx-pro/distribution_groups/public" target="_blank" rel="noopener">ClashX Pro</a> 版本</p>
<h3 id="安装vnc-viewer可选">安装VNC Viewer（可选）</h3>
<p>如果你用的 EasyConnect <strong>需要</strong> 图形界面登录的话，就需要安装 VNC Viewer，否则可以跳过这一步。</p>
<p>如果不知道可以先不装，到后面用 Docker 运行 EasyConnect 的时候提示你不能在命令行界面完成再返回这一步安装。</p>
<p>VNC Viewer 的安装非常简单，到官网的 <a href="https://www.realvnc.com/en/connect/download/viewer/" target="_blank" rel="noopener">下载</a> 页面，选择相应的版本下载，然后一路下一步就完成了。</p>
<h3 id="安装文本编辑器">安装文本编辑器</h3>
<p>因为涉及到 <strong>yaml</strong>文件 的编辑修改，你可能需要安装一个 <a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> ，不使用记事本的原因是它不带高亮，没有单词拼写提示也不会自动调整格式，可能会导致你有一些缩进、拼写和标点等方面的错误比较难发现。</p>
<p>VSCode是免费的，这里再推荐一个软件：<strong>Sublime Text</strong>（付费）。</p>
<h3 id="使用-docker-运行-easyconnect">使用 Docker 运行 EasyConnect</h3>
<p>首先确保你的 Docker 是运行状态（可以输入 <code>docker ps -a</code> 测试一下）。打开终端，根据是否需要图形化界面输入不同的命令。</p>
<blockquote>
<p>2022.12.29更新：</p>
<p>本人是Intel机型的MacBook，根据评论区老哥的提醒，下面的教程<strong>并不适用</strong>于苹果自研M系列芯片，即<strong>arm架构</strong>机器。</p>
<p>由于我没有M芯片的机器，如果需要请自行尝试编译 <strong>non-amd64</strong> 分支文件，详见<a href="https://github.com/Hagb/issues/167" target="_blank" rel="noopener">issue167</a>。如果在编译过程中遇到新的问题，可以多看看其他人提的issue。</p>
</blockquote>
<p><strong>纯命令行版（推荐）：</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch ~/.easyconn
</span></span><span class="line"><span class="cl">docker pull hagb/docker-easyconnect:cli
</span></span><span class="line"><span class="cl">docker run --device /dev/net/tun --cap-add NET_ADMIN -v <span class="nv">$HOME</span>/.easyconn:/root/.easyconn -it -p 127.0.0.1:1080:1080 -p 127.0.0.1:8888:8888 -e <span class="nv">EC_VER</span><span class="o">=</span>7.6.3 -e <span class="nv">CLI_OPTS</span><span class="o">=</span><span class="s2">&#34;-d vpn.xxx.edu.cn -u USERNAME -p PASSWORD&#34;</span> hagb/docker-easyconnect:cli
</span></span></code></pre></td></tr></table>
</div>
</div><p>下面对命令进行解释：</p>
<ul>
<li>
<p>第一行，我们在当前用户的 <code>$HOME</code> 目录下创建了一个配置文件，用来保存登录信息。</p>
</li>
<li>
<p>第二行，拉取我们需要的docker镜像到本地。</p>
</li>
<li>
<p>第三行，我们启动了一个 Easy­Con­nect 命令行版 Docker 容器：</p>
<ul>
<li>
<p><code>--device /dev/net/tun --cap-add NET_ADMIN</code> 创建了虚拟网络设备；</p>
</li>
<li>
<p><code>-it</code> 返回一个交互式终端，用来显示信息；</p>
</li>
<li>
<p><code>-v</code> 指定挂载卷，我们将当前用户 <code>$HOME$</code> 目录下的配置文件映射到容器内，实现登录信息的持久化；</p>
</li>
<li>
<p><code>-p</code> 指定容器的端口映射，可以根据实际情况更改端口号。其中 1080 是 Socks5 代理端口，8888 是 HTTP 代理端口；</p>
</li>
<li>
<p><code>-e EC_VER </code> 设置容器内环境变量 <code>EC_VER</code> 的值，指定 Sangfor 的版本，最好和服务端一致；</p>
</li>
<li>
<p><code>-e CLI_OPTS</code> 设置容器内环境变量 <code>CLI_OPTS</code> 的值，指定运行 Sangfor 时的参数。这里的 <code>-d</code> 指定 VPN 地址，<code>-u</code> 指定用户名，<code>-p</code> 指定用户的密码。这些信息请 <strong>自行修改正确</strong> ！</p>
</li>
<li>
<p><code>-e IPTABLES_LEGACY=1</code> 使用旧式的 iptables 命令，主要目的是和 WSL 保持兼容。在部分发行版的 WSL 版本上，缺少了这个环境变量会使得 VPN 不能正常运行。（非必要不选）</p>
<blockquote>
<p>2022.12.09 更新：</p>
<p>建议增加容器自动重启选项，方便开机自启：</p>
<ul>
<li>
<p>已安装：</p>
<p>在原容器的基础上使用<code>update</code>命令更新参数即可。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker ps -a
</span></span><span class="line"><span class="cl">docker update --restart<span class="o">=</span>always 容器ID
</span></span><span class="line"><span class="cl">docker restart 容器ID
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>未安装：</p>
<p>直接在上面命令的基础上加上<code>--restart</code>参数即可。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run --restart<span class="o">=</span>always --device /dev/net/tun --cap-add NET_ADMIN -v <span class="nv">$HOME</span>/.easyconn:/root/.easyconn -it -p 127.0.0.1:1080:1080 -p 127.0.0.1:8888:8888 -e <span class="nv">EC_VER</span><span class="o">=</span>7.6.3 -e <span class="nv">CLI_OPTS</span><span class="o">=</span><span class="s2">&#34;-d vpn.xxx.edu.cn -u USERNAME -p PASSWORD&#34;</span> hagb/docker-easyconnect:cli
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<p>2022.12.07 更新：</p>
<p>如果在运行完上述命令后 <em>docker容器保持在运行状态</em> ，我们需要Ctrl + C手动停止运行后，</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 找到容器ID</span>
</span></span><span class="line"><span class="cl">docker ps -a
</span></span><span class="line"><span class="cl"><span class="c1"># 重新运行容器</span>
</span></span><span class="line"><span class="cl">docker start 这里填写easyconnect容器ID
</span></span></code></pre></td></tr></table>
</div>
</div><p>2022.09.05 更新：</p>
<p>这个参数建议先删除，如果不能正常运行，再加上。</p>
<p>macOS Catalina系统下我测试添加此参数后账号将不能自动登录，建议删除。删除后一切正常。</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<p>具体的参数设置请参考：<a href="https://github.com/Hagb/blob/master/doc/usage.md" target="_blank" rel="noopener">usage.md</a></p>
<p><strong>图形界面版：</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker pull hagb/docker-easyconnect:7.6.3
</span></span><span class="line"><span class="cl">docker run --device /dev/net/tun --cap-add NET_ADMIN -ti -e <span class="nv">PASSWORD</span><span class="o">=</span>xxxx -v <span class="nv">$HOME</span>/.ecdata:/root -p 127.0.0.1:5901:5901 -p 127.0.0.1:1080:1080 hagb/docker-easyconnect:7.6.3
</span></span></code></pre></td></tr></table>
</div>
</div><p>其中 <code>hagb/docker-easyconnect:7.6.3</code> 表示使用 <code>7.6.3</code> 版本的 EasyConnect，请根据实际情况修改版本号。</p>
<blockquote>
<p>ps：当你的 5901 或者 1080 端口被其他服务占用时，可以通过如下命令更改我们上面用 docker 运行的 EasyConnect 的端口（以纯命令行版举例，图形界面版也是一样的）;</p>
<p>127.0.0.1:<em>15901</em>:5901 和 127.0.0.1:<em>10180</em>:1080中的 15901 和 10180 各位可以随意修改成自己没有被占用的端口。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run --device /dev/net/tun --cap-add NET_ADMIN -ti -e <span class="nv">PASSWORD</span><span class="o">=</span>xxxx -v <span class="nv">$HOME</span>/.ecdata:/root -p 127.0.0.1:15901:5901 -p 127.0.0.1:10180:1080 hagb/docker-easyconnect:7.6.3
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h3 id="图形化-vnc-viewer-连接">图形化 VNC Viewer 连接</h3>
<p>输入完之后打开 <strong>VNC Viewer</strong>，点击左上角的 <strong>File -&gt; New connection</strong>，或者在空白处 <strong>右键 -&gt; New connection</strong>，或者使用快捷键 <strong>Ctrl + N</strong>，新建一个链接，在弹出的对话框中的 VNC Server 中填入 <strong>127.0.0.1:5901</strong> ，Name 可以不填。</p>
<p><a href="/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp" data-fancybox="gallery" data-src="/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp" data-caption="VNC Viewer">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_9533240000a87157.webp 480w, /article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp 583w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="583"
                    height="791"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp"
                    srcset="/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_9533240000a87157.webp 480w, /article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp 583w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="VNC Viewer"
                    
                />
            </picture>
        </a></p>
<p>点击 OK 后，双击我们刚刚创建好的链接，输入密码 XXXX，就可以进行连接了，进去之后是熟悉的界面，输入地址，用户名和密码之后就可以关掉了。</p>
<blockquote>
<p>在 Docker 中运行的 EasyConnect 都不用输验证码，更加方便。</p>
<p>同时由于这个项目本身是会记住你输入的服务器地址的，所以以后使用的时候只需要点一下登录按钮就可以了。</p>
</blockquote>
<p>进行到这一步，就会有一个 socks5 代理跑在你电脑的 <strong>1080 端口</strong> 了，接下来就是配置 Clash，在我们需要的时候进行转发。</p>
<h3 id="配置-clash">配置 Clash</h3>
<blockquote>
<p>2022.12.07 更新：</p>
<p>可以直接创建一个新的配置文件，以免配置更新导致失效。ClashX同理，文件内容可以参考下面：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">7890</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">socks-port</span><span class="p">:</span><span class="w"> </span><span class="m">7891</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">allow-lan</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">mode</span><span class="p">:</span><span class="w"> </span><span class="l">Rule</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">log-level</span><span class="p">:</span><span class="w"> </span><span class="l">info</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">external-controller</span><span class="p">:</span><span class="w"> </span><span class="p">:</span><span class="m">9090</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- {<span class="nt">name: vpn, type: socks5, server: 127.0.0.1, port</span><span class="p">:</span><span class="w"> </span><span class="m">1080</span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">proxy-groups</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">校园网</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">select</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">vpn</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">IP-CIDR,172.20.2.0/24,vpn</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<p>这一小节讲述如何让你在需要的时候使用 EasyConnect 的 VPN 服务。</p>
<p>首先运行 Clash，点击左侧导航栏的 Profiles ，你会看到一个默认的 <strong>config.yaml</strong> ，如果你有其他配置文件也可以编辑其他配置文件。点击你想编辑的配置文件右边的形如 <code>&lt; &gt;</code> 的按钮，意思就是在文本编辑器中编辑配置文件，在最后增加：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># 增加一个名字是 vpn 的 sock5 代理</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span>- {<span class="nt">&#34;name&#34;: &#34;vpn&#34;, &#34;type&#34;: &#34;socks5&#34;, &#34;server&#34;: &#34;127.0.0.1&#34;, &#34;port&#34;: </span><span class="s2">&#34;1080&#34;</span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># 添加 ip-cidr 的规则</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span>- <span class="l">IP-CIDR,222.192.6.0/24,vpn</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>注意事项：</p>
<p>这里填写的 <code>222.192.6.0/24</code> 是指只有访问 <code>222.192.6.xxx</code> 的流量才会走上面配置的那个代理，需要根据你的实际情况进行更改。</p>
<p>当然，你如果是编辑你自己的机场配置文件，是需要在原来的 <code>proxies</code> 和 <code>rules</code> 下新增上面内容，而<em>不能再新增这两个属性</em>。</p>
</blockquote>
<p>到这一步，在 Clash 的 General 页面，将 <strong>System Proxy</strong> 打开，你就已经可以访问学校内网了，但是不可以使用远程桌面等功能，如果需要使用这些功能，还需要进一步配置。</p>
<h3 id="配置-clashx">配置 ClashX</h3>
<p>与上面类似：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span>- {<span class="w"> </span><span class="nt">name: &#39;vpn&#39;, type: socks5, server: 127.0.0.1, port</span><span class="p">:</span><span class="w"> </span><span class="m">1080</span><span class="w"> </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span>- <span class="s1">&#39;IP-CIDR,172.20.2.0/24,vpn&#39;</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="配置-tun-模式">配置 TUN 模式</h3>
<p>对于 TUN 模式，官方文档是这么描述的：</p>
<blockquote>
<p>对于不遵循系统代理的软件，TUN 模式可以接管其流量并交由 CFW 处理，在 Windows 中，TUN 模式性能比 TAP 模式好。</p>
</blockquote>
<p>浏览器之类的应用都是使用系统代理的，一些非系统代理应用，可以通过设置被 CFW 接管。总之，配置 TUN 模式之后，我们的需求就可以实现了，启动 TUN 模式需要进行如下操作（MacOS 用户跳过前两步）：</p>
<ol>
<li>打开 Clash 的 General 页面，找到 Home Directory，点击右边的 <code>Open Folder</code> 打开 <code>Home Directory</code> 文件夹；</li>
<li>进入网站 <a href="https://www.wintun.net/" target="_blank" rel="noopener">Wintun</a> ，点击界面中 <code>Download Wintun xxx</code> 下载压缩包。根据系统版本将 <code>wintun-x.xx/wintun/bin</code> 对应目录中 <code>wintun.dll</code> 复制至 <code>Home Directory</code> 目录中。基于 <code>x64</code> 的处理器的 <code>64</code> 位操作系统请使用 <code>amd64</code> 版本，M1 版本的 Mac 选择 <code>arm64</code> 版本；</li>
<li>点击 General 中 Service Mode 右边 Manage，在打开窗口中安装服务模式，安装完成应用会自动重启，Service Mode 右边地球图标变为绿色即安装成功；</li>
<li>点击 <strong>settings -&gt; Profile Mixin -&gt; YAML</strong>，点击 <strong>YAML</strong> 右侧的 <strong>Edit</strong>，输入下面的内容，点击右下角的按钮保存。</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">mixin</span><span class="p">:</span><span class="w"> 
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">hosts</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#39;mtalk.google.com&#39;</span><span class="p">:</span><span class="w"> </span><span class="m">108.177.125.188</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#39;services.googleapis.cn&#39;</span><span class="p">:</span><span class="w"> </span><span class="m">74.125.203.94</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#39;raw.githubusercontent.com&#39;</span><span class="p">:</span><span class="w"> </span><span class="m">151.101.76.133</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">dns</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">enable</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">default-nameserver</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">223.5.5.5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">1.0.0.1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">ipv6</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">enhanced-mode</span><span class="p">:</span><span class="w"> </span><span class="l">redir-host</span><span class="w"> </span><span class="c">#fake-ip</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">nameserver</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://dns.rubyfish.cn/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://223.5.5.5/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://dns.pub/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">fallback</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://1.0.0.1/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://public.dns.iij.jp/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://dns.twnic.tw/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">fallback-filter</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">geoip</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">ipcidr</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">240.0.0.0</span><span class="l">/4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">0.0.0.0</span><span class="l">/32</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">127.0.0.1</span><span class="l">/32</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">domain</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.google.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.facebook.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.twitter.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.youtube.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.xn--ngstr-lra8j.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.google.cn</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.googleapis.cn</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.gvt1.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">tun</span><span class="p">:</span><span class="w"> 
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">enable</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">stack</span><span class="p">:</span><span class="w"> </span><span class="l">gvisor</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">dns-hijack</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">198.18.0.2</span><span class="p">:</span><span class="m">53</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">macOS-auto-route</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">macOS-auto-detect-interface</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 自动检测出口网卡</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><ol start="5">
<li>返回 general 页面开启 Mixin 即可，之后点击 connections 会发现所有连接都是 TUN 模式，这时候我们就完成了所有配置。</li>
</ol>
<p>更详细的配置可以参考官方文档的 <a href="https://docs.cfw.lbyczf.com/contents/tun.html" target="_blank" rel="noopener">TUN 模式</a> 页面。</p>
<h3 id="过滤应用">过滤应用</h3>
<p>相关规则可以参考：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;officeVpnProxy&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;socks5&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">server</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;127.0.0.1&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;10180&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">proxy-groups</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;programs&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">select</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="s2">&#34;DIRECT&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="s2">&#34;PROXY&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,vpnkit.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,vpnkit-bridge.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.dev-envs.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.backend.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.extensions.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.proxy.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.service,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.wsl-distro-proxy.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,Docker Desktop.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,docker.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,wsl.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,wslhost.exe,programs</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>注意：其中的 port 要对应你前面配置 docker 配置的端口，需要对应起来。</p>
</blockquote>
<h3 id="再次启动">再次启动</h3>
<p>当你关掉终端窗口，或者重启电脑，想再次启动 Docker 时，我们只需要启动相应的容器，并且在 VNC Viewer 中点击登录就可以（如果你不使用图形界面的话只需要启动容器）。</p>
<p>启动容器的操作就不用再去打上面创建容器时的那一串命令了，因为那一串命令的意思是创建容器、下载镜像、启动并进入容器，我们已经创建好了容器，以后只需要启动就行了。所以，我们先要知道我们有哪些容器，然后启动相应的容器就可以。</p>
<p>首先，查看我们已有的容器：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker ps -a
</span></span></code></pre></td></tr></table>
</div>
</div><p>你应该会得到类似的输出，如果你是第一次使用 Docker，应该只有一个容器</p>
<p><a href="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp" data-fancybox="gallery" data-src="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp" data-caption="docker container">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_ef10729183ff2e30.webp 480w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp 720w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d708a6bdd75c67f5.webp 960w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_6f6a876e8f0cd3d8.webp 1440w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp 2010w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2010"
                    height="102"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp"
                    srcset="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_ef10729183ff2e30.webp 480w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp 720w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d708a6bdd75c67f5.webp 960w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_6f6a876e8f0cd3d8.webp 1440w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp 2010w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="docker container"
                    
                />
            </picture>
        </a></p>
<p>当电脑重启之后又想开启它的时候，只需要输入：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker start 81f
</span></span></code></pre></td></tr></table>
</div>
</div><p>就可以了，其中 <code>81f</code> 是我要启动的容器的 <code>ID</code> 也就是第一列的值，这个值很长，通常你只需要输入前几位就可以，或者也可以通过 <code>docker rename</code> 命令修改。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker rename OLDNAME NEWNAME
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="卸载-easyconnect">卸载 EasyConnect</h2>
<p>前面说道，EasyConnect 的流氓之处之一就是非常难卸载，但是我还是根据网上的资料和我自己操作的经验总结出一套方法，这一套方法可能略显复杂，可能有多余的操作，不过按照这样操作是可以将 EasyConnect 完全卸载干净的。</p>
<p>首先，找到 EasyConnect 的安装目录，双击运行他的卸载程序，等他运行完之后你会发现，这个目录并没有被完全删掉，还是有很多文件，这时候我们执行下列步骤：</p>
<ol>
<li>全选 Shift + Delete，如果遇到不给删的就跳过，这时候还是会剩下很多文件。</li>
<li>断网重启电脑，来到安装目录下，把所有文件夹都改名，随便改成什么，再次重启</li>
<li>全选刚刚改过名的文件夹 Shift + Delete，如果这时候还删不了就把文件夹剪切到别的地方再删除</li>
<li>重启电脑，管理员权限打开命令行（如果你没有常用的命令行工具可以 Win + X 选择 <strong>Windows PowerShell（管理员）</strong>）</li>
<li>输入命令 <code>netsh winsock reset</code> 回车</li>
</ol>
<p>最后两步重置 winsock 非常重要，如果不执行很可能会出现各种客户端无法连接网络的情况。</p>
<p>如果卸载之后发现还有 <strong>sanfor</strong> 这个服务可以参考 <a href="https://www.zhihu.com/question/333699380/answer/2358761655" target="_blank" rel="noopener">这篇文章</a> 尝试解决。</p>
<h2 id="效果">效果</h2>
<p>查看已经创建的docker容器，可以发现 <strong>docker-easyconnect:cli</strong> 字样。</p>
<p><a href="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp" data-fancybox="gallery" data-src="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp" data-caption="docker container">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_ef10729183ff2e30.webp 480w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp 720w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d708a6bdd75c67f5.webp 960w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_6f6a876e8f0cd3d8.webp 1440w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp 2010w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2010"
                    height="102"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp"
                    srcset="/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_ef10729183ff2e30.webp 480w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp 720w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d708a6bdd75c67f5.webp 960w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_6f6a876e8f0cd3d8.webp 1440w, /article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp 2010w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="docker container"
                    
                />
            </picture>
        </a></p>
<p>我是配合ClashX Pro使用，效果很不错，需要的时候直接切换到对应配置即可。</p>
<p><a href="/article/docker-easyconnect/image-20221207135810619_hu_79cb8361f74e1e42.webp" data-fancybox="gallery" data-src="/article/docker-easyconnect/image-20221207135810619_hu_79cb8361f74e1e42.webp" data-caption="配置样式">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/docker-easyconnect/image-20221207135810619_hu_4bd8db4cfe06f13b.webp 480w, /article/docker-easyconnect/image-20221207135810619_hu_ce42b75a4a6ad627.webp 720w, /article/docker-easyconnect/image-20221207135810619_hu_f3c7bae0b39d0df5.webp 960w, /article/docker-easyconnect/image-20221207135810619_hu_380d7cb21673a3c7.webp 1440w, /article/docker-easyconnect/image-20221207135810619_hu_79cb8361f74e1e42.webp 1516w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1516"
                    height="798"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/docker-easyconnect/image-20221207135810619_hu_ce42b75a4a6ad627.webp"
                    srcset="/article/docker-easyconnect/image-20221207135810619_hu_4bd8db4cfe06f13b.webp 480w, /article/docker-easyconnect/image-20221207135810619_hu_ce42b75a4a6ad627.webp 720w, /article/docker-easyconnect/image-20221207135810619_hu_f3c7bae0b39d0df5.webp 960w, /article/docker-easyconnect/image-20221207135810619_hu_380d7cb21673a3c7.webp 1440w, /article/docker-easyconnect/image-20221207135810619_hu_79cb8361f74e1e42.webp 1516w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="配置样式"
                    
                />
            </picture>
        </a></p>
<h2 id="感谢">感谢</h2>
<p><a href="https://github.com/Hagb/docker-easyconnect" target="_blank" rel="noopener">docker-easyconnect</a></p>
<p><a href="https://soulike.tech/article/64" target="_blank" rel="noopener">Soulike</a></p>
<p><a href="https://zhuanlan.zhihu.com/p/389894063" target="_blank" rel="noopener">Jortana</a></p>
<p><a href="https://naiv.fun/Ops/sangfor-in-docker.html" target="_blank" rel="noopener">Nativus</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Mac下的平铺桌面Yabai使用</title>
      <link>https://vccv.cc/article/mac-tiling-yabai.html</link>
      <pubDate>Thu, 19 May 2022 12:03:26 +0000</pubDate>
      <guid>https://vccv.cc/article/mac-tiling-yabai.html</guid>
      <description>长期使用Linux的用户应该对i3wm并不陌生，它与Mac、Windows这类操作系统悬浮（float）式桌面有着显著差别，这类被称之为平铺（tiling）式桌面。当我得知Mac下的开源项目yabai时，我便迫不及待的开始了使用之旅。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>长期使用Linux的用户应该对 <a href="https://i3wm.org/" target="_blank" rel="noopener">i3wm</a> 并不陌生，它与Mac、Windows这类操作系统悬浮（float）式桌面有着显著差别，这类被称之为平铺（tiling）式桌面。当我得知Mac下的开源项目 <a href="https://github.com/koekeishiya/yabai" target="_blank" rel="noopener">yabai</a> 时，我便迫不及待的开始了使用之旅。</p>
<h2 id="安装">安装</h2>
<blockquote>
<p>设备情况：</p>
<p><a href="https://zhuanlan.zhihu.com/p/90508170" target="_blank" rel="noopener">已安装Homebrew</a>（可以参照官网）</p>
<p><a href="https://github.com/koekeishiya/yabai/wiki/Disabling-System-Integrity-Protection" target="_blank" rel="noopener">已关闭SIP</a></p>
<p>Monterey12.4</p>
</blockquote>
<p>最好是参照 <a href="https://github.com/koekeishiya/yabai/wiki/Installing-yabai-%28latest-release%29" target="_blank" rel="noopener">官方文档</a>（英文）进行安装，毕竟官方的是最新最准确的。</p>
<p>下面是自己的过程，记录一下，可供大家参考。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 安装yabai</span>
</span></span><span class="line"><span class="cl">brew install koekeishiya/formulae/yabai
</span></span><span class="line"><span class="cl">sudo yabai --install-sa
</span></span><span class="line"><span class="cl"><span class="c1"># 启动yabai 这时候需要授权辅助功能</span>
</span></span><span class="line"><span class="cl">brew services start yabai
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 安装skhd</span>
</span></span><span class="line"><span class="cl">brew install koekeishiya/formulae/skhd
</span></span><span class="line"><span class="cl"><span class="c1"># 启动skhd 这时候需要授权辅助功能</span>
</span></span><span class="line"><span class="cl">brew services start skhd
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">########### macOS Big Sur or Monterey 需要多做以下步骤 ###########</span>
</span></span><span class="line"><span class="cl">sudo yabai --load-sa
</span></span><span class="line"><span class="cl">sudo visudo -f /private/etc/sudoers.d/yabai
</span></span><span class="line"><span class="cl"><span class="c1"># 然后输入以下内容 其中 &lt;user&gt; 修改为当前 mac 的用户名</span>
</span></span><span class="line"><span class="cl"><span class="c1"># yuesir ALL = (root) NOPASSWD: /usr/local/bin/yabai --load-sa</span>
</span></span><span class="line"><span class="cl">&lt;user&gt; <span class="nv">ALL</span> <span class="o">=</span> <span class="o">(</span>root<span class="o">)</span> NOPASSWD: /usr/local/bin/yabai --load-sa
</span></span><span class="line"><span class="cl"><span class="c1"># 之后在 yabairc 中添加以下命令即可 上面的配置文件中已经添加</span>
</span></span><span class="line"><span class="cl">sudo yabai --load-sa
</span></span><span class="line"><span class="cl">yabai -m signal --add <span class="nv">event</span><span class="o">=</span>dock_did_restart <span class="nv">action</span><span class="o">=</span><span class="s2">&#34;sudo yabai --load-sa&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>yabai 可配合 <a href="https://github.com/koekeishiya/skhd" target="_blank" rel="noopener">skhd</a> 使用，<strong>Secure Keyboard Entry</strong> 这个选项必须禁用（默认关闭）。</p>
<p>系统第一次启动 yabai 与 skhd 之后，macOS 会提示是否允许访问辅助功能。在<strong>系统偏好设置-&gt;安装性与隐私-&gt;隐私</strong>中添加权限后，再执行下面的命令即可。</p>
<p><a href="/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_48189a4b6857e765.webp" data-fancybox="gallery" data-src="/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_48189a4b6857e765.webp" data-caption="授权辅助功能">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_f95f04c5b6aa4bcb.webp 480w, /article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_7a56cdff6bd28bbe.webp 720w, /article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_fb3d69dd55d3b947.webp 960w, /article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_48189a4b6857e765.webp 1408w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1408"
                    height="1246"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_7a56cdff6bd28bbe.webp"
                    srcset="/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_f95f04c5b6aa4bcb.webp 480w, /article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_7a56cdff6bd28bbe.webp 720w, /article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_fb3d69dd55d3b947.webp 960w, /article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_48189a4b6857e765.webp 1408w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="授权辅助功能"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 重启服务</span>
</span></span><span class="line"><span class="cl">brew services restart yabai
</span></span><span class="line"><span class="cl">brew services restart skhd
</span></span></code></pre></td></tr></table>
</div>
</div><p>这时候还是不能正常使用的，还需要自行配置相关文件。</p>
<h2 id="配置">配置</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 创建yabai配置文件</span>
</span></span><span class="line"><span class="cl">touch ~/.yabairc
</span></span><span class="line"><span class="cl">chmod +x ~/.yabairc
</span></span><span class="line"><span class="cl"><span class="c1"># 创建skhd配置文件</span>
</span></span><span class="line"><span class="cl">touch ~/.skhdrc
</span></span><span class="line"><span class="cl">chmod +x ~/.skhdrc
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="yabairc配置文件示例">.yabairc配置文件<a href="https://www.cnblogs.com/tdg-yyx/p/15972309.html" target="_blank" rel="noopener">示例</a>：</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env sh
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 这里参考了 yabai 的 wiki 。具体步骤下面讲</span>
</span></span><span class="line"><span class="cl">sudo yabai --load-sa
</span></span><span class="line"><span class="cl">yabai -m signal --add <span class="nv">event</span><span class="o">=</span>dock_did_restart <span class="nv">action</span><span class="o">=</span><span class="s2">&#34;sudo yabai --load-sa&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 窗口布局 bsp: 平铺 float: 浮动</span>
</span></span><span class="line"><span class="cl">yabai -m config layout                       bsp
</span></span><span class="line"><span class="cl"><span class="c1"># 默认拆分规则 first_child second_child</span>
</span></span><span class="line"><span class="cl">yabai -m config window_placement             second_child
</span></span><span class="line"><span class="cl"><span class="c1"># 窗口间距设置</span>
</span></span><span class="line"><span class="cl">yabai -m config top_padding                  <span class="m">5</span>
</span></span><span class="line"><span class="cl">yabai -m config bottom_padding               <span class="m">5</span>
</span></span><span class="line"><span class="cl">yabai -m config left_padding                 <span class="m">5</span>
</span></span><span class="line"><span class="cl">yabai -m config right_padding                <span class="m">5</span>
</span></span><span class="line"><span class="cl">yabai -m config window_gap                   <span class="m">4</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 自动平衡所有窗口始终占据相同的空间</span>
</span></span><span class="line"><span class="cl">yabai -m config auto_balance                 off
</span></span><span class="line"><span class="cl"><span class="c1"># 如果禁用自动平衡，此项属性定义的是新窗口占用的空间量。0.5意为旧窗口占用50%</span>
</span></span><span class="line"><span class="cl">yabai -m config split_ratio                 0.50
</span></span><span class="line"><span class="cl"><span class="c1"># 鼠标修饰键 意思就是按着这个键就可以使用鼠标单独修改窗口大小了</span>
</span></span><span class="line"><span class="cl">yabai -m config mouse_modifier               fn
</span></span><span class="line"><span class="cl"><span class="c1"># fn + 左键 移动</span>
</span></span><span class="line"><span class="cl">yabai -m config mouse_action1                move
</span></span><span class="line"><span class="cl"><span class="c1"># fn + 右键 </span>
</span></span><span class="line"><span class="cl">yabai -m config mouse_action2                resize
</span></span><span class="line"><span class="cl"><span class="c1"># 焦点跟随鼠标 默认off: 关闭  autoraise:自动提升 autofocus: 自动对焦</span>
</span></span><span class="line"><span class="cl">yabai -m config focus_follows_mouse          autofocus
</span></span><span class="line"><span class="cl"><span class="c1"># 设置鼠标是否跟随当前活动窗口 默认 off: 关闭 on: 开启</span>
</span></span><span class="line"><span class="cl">yabai -m config mouse_follows_focus          on
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 浮动窗口问题在顶部</span>
</span></span><span class="line"><span class="cl">yabai -m config window_topmost               on
</span></span><span class="line"><span class="cl"><span class="c1"># 修改窗口阴影 on: 打开 off: 关闭 float: 只显示浮动窗口的阴影</span>
</span></span><span class="line"><span class="cl">yabai -m config window_shadow                float
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 窗口透明度设置</span>
</span></span><span class="line"><span class="cl">yabai -m config window_opacity               on
</span></span><span class="line"><span class="cl"><span class="c1"># 配置活动窗口不透明度</span>
</span></span><span class="line"><span class="cl">yabai -m config active_window_opacity        1.0             
</span></span><span class="line"><span class="cl">yabai -m config normal_window_opacity        0.9
</span></span><span class="line"><span class="cl">yabai -m config window_opacity_duration      0.0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 在主显示器上的每个空间顶部添加 20 填充 底部添加 0 填充</span>
</span></span><span class="line"><span class="cl"><span class="c1"># yabai -m config external_bar main:20:0</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 在所有显示器上的每个空间顶部添加 0 填充 底部添加 0 填充</span>
</span></span><span class="line"><span class="cl">yabai -m config external_bar all:0:5
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ================================ 规则 ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 打开系统偏好设置，不使用平铺模式</span>
</span></span><span class="line"><span class="cl">yabai -m rule --add <span class="nv">app</span><span class="o">=</span><span class="s2">&#34;^系统偏好设置</span>$<span class="s2">&#34;</span> <span class="nv">manage</span><span class="o">=</span>off
</span></span><span class="line"><span class="cl">yabai -m rule --add <span class="nv">app</span><span class="o">=</span><span class="s2">&#34;^提醒事项</span>$<span class="s2">&#34;</span> <span class="nv">manage</span><span class="o">=</span>off
</span></span><span class="line"><span class="cl">yabai -m rule --add <span class="nv">app</span><span class="o">=</span><span class="s2">&#34;^关于本机</span>$<span class="s2">&#34;</span> <span class="nv">manage</span><span class="o">=</span>off
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;yabai configuration loaded..&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="skhdrc-文件同理">.skhdrc 文件同理：</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># ================================ 窗口设置 ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># focus window : 激活窗口快捷键  h: 左  j: 下  k: 右 l: 上 </span>
</span></span><span class="line"><span class="cl">alt - h : yabai -m window --focus west
</span></span><span class="line"><span class="cl">alt - j : yabai -m window --focus south
</span></span><span class="line"><span class="cl">alt - k : yabai -m window --focus north
</span></span><span class="line"><span class="cl">alt - l : yabai -m window --focus east 
</span></span><span class="line"><span class="cl"><span class="c1"># 交换窗口位置</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + alt - h : yabai -m window --swap west
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + alt - j : yabai -m window --swap south
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + alt - k : yabai -m window --swap north
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + alt - l : yabai -m window --swap east
</span></span><span class="line"><span class="cl"><span class="c1"># 移动窗口位置</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - h : yabai -m window --warp west
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - j : yabai -m window --warp south
</span></span><span class="line"><span class="cl"><span class="c1"># 因与IDEA shift + cmd + K push code 冲突，故注释了此快捷键</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + cmd - k : yabai -m window --warp north</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - l : yabai -m window --warp east
</span></span><span class="line"><span class="cl"><span class="c1"># 浮动窗口设置 参考了Magent默认设置。因为之前用习惯了。。。。</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 恢复原始窗口大小</span>
</span></span><span class="line"><span class="cl">ctrl + alt - <span class="m">0</span> : yabai -m space --balance
</span></span><span class="line"><span class="cl"><span class="c1"># 把浮动窗口左右平分整个屏幕  rows:cols:start-x:star-y:width:height  m行:n列:x:y:w:h</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 最大化</span>
</span></span><span class="line"><span class="cl">ctrl + alt - <span class="k">return</span> : yabai -m window --grid 1:1:0:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 2分屏上</span>
</span></span><span class="line"><span class="cl">ctrl + alt - up     : yabai -m window --grid 2:1:0:0:2:1
</span></span><span class="line"><span class="cl"><span class="c1"># 2分屏左</span>
</span></span><span class="line"><span class="cl">ctrl + alt - left   : yabai -m window --grid 1:2:0:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 2分屏右</span>
</span></span><span class="line"><span class="cl">ctrl + alt - right  : yabai -m window --grid 1:2:1:1:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 2分屏下</span>
</span></span><span class="line"><span class="cl">ctrl + alt - down   : yabai -m window --grid 2:1:0:1:2:1
</span></span><span class="line"><span class="cl"><span class="c1"># 4分屏左上</span>
</span></span><span class="line"><span class="cl">ctrl + alt - u : yabai -m window --grid 2:2:0:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 4分屏右上</span>
</span></span><span class="line"><span class="cl">ctrl + alt - i : yabai -m window --grid 2:2:0:1:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 4分屏左下</span>
</span></span><span class="line"><span class="cl">ctrl + alt - j : yabai -m window --grid 2:2:1:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 4分屏右下</span>
</span></span><span class="line"><span class="cl">ctrl + alt - k : yabai -m window --grid 2:2:1:1:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏左1</span>
</span></span><span class="line"><span class="cl">ctrl + alt - d : yabai -m window --grid 1:3:0:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏左2</span>
</span></span><span class="line"><span class="cl">ctrl + alt - e : yabai -m window --grid 1:3:0:0:2:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏中1</span>
</span></span><span class="line"><span class="cl">ctrl + alt - f : yabai -m window --grid 1:3:1:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏右2</span>
</span></span><span class="line"><span class="cl">ctrl + alt - t : yabai -m window --grid 1:3:1:0:2:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏右1</span>
</span></span><span class="line"><span class="cl">ctrl + alt - g : yabai -m window --grid 1:3:3:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 9分屏居中</span>
</span></span><span class="line"><span class="cl">ctrl + alt - c : yabai -m window --grid 3:3:1:1:1:1
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 浮动/不浮动窗口 float / unfloat window and center on screen</span>
</span></span><span class="line"><span class="cl">alt - t : yabai -m window --toggle float<span class="p">;</span>yabai -m window --grid 4:4:1:1:2:2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">alt - r         : yabai -m space --rotate <span class="m">90</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 调整窗口大小</span>
</span></span><span class="line"><span class="cl">ctrl + alt + cmd - left : yabai -m window --resize left:-50:0<span class="p">;</span> yabai -m window --resize right:-50:0
</span></span><span class="line"><span class="cl">ctrl + alt + cmd - down : yabai -m window --resize bottom:0:50<span class="p">;</span> yabai -m window --resize top:0:50
</span></span><span class="line"><span class="cl">ctrl + alt + cmd - up : yabai -m window --resize top:0:-50<span class="p">;</span> yabai -m window --resize bottom:0:-50
</span></span><span class="line"><span class="cl">ctrl + alt + cmd - right : yabai -m window --resize right:50:0<span class="p">;</span> yabai -m window --resize left:50:0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 重启 Yabai</span>
</span></span><span class="line"><span class="cl">cmd + alt - r : /usr/bin/env osascript <span class="o">&lt;&lt;&lt;</span> <span class="s2">&#34;display notification \&#34;正在重启 Yabai\&#34; with title \&#34;Yabai\&#34;&#34;</span><span class="p">;</span> launchctl kickstart -k <span class="s2">&#34;gui/</span><span class="si">${</span><span class="nv">UID</span><span class="si">}</span><span class="s2">/homebrew.mxcl.yabai&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ================================ 多桌面配置  ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 创建一个新桌面，并把当前活动的窗口发送到新桌面，并且自动跳转到新桌面 需要jq支持 brew install jq</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - n : yabai -m space --create <span class="o">&amp;&amp;</span> <span class="nv">index</span><span class="o">=</span><span class="s2">&#34;</span><span class="k">$(</span>yabai -m query --spaces --display <span class="p">|</span> jq <span class="s1">&#39;.| length&#39;</span><span class="k">)</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> yabai -m window --space <span class="s2">&#34;</span><span class="si">${</span><span class="nv">index</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> yabai -m space --focus <span class="s2">&#34;</span><span class="si">${</span><span class="nv">index</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 切换回最近的一个桌面</span>
</span></span><span class="line"><span class="cl">alt - x : yabai -m space --focus recent
</span></span><span class="line"><span class="cl"><span class="c1"># 切换回第一个桌面</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">1</span> : yabai -m space --focus <span class="m">1</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">2</span> : yabai -m space --focus <span class="m">2</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">3</span> : yabai -m space --focus <span class="m">3</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">4</span> : yabai -m space --focus <span class="m">4</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">5</span> : yabai -m space --focus <span class="m">5</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">6</span> : yabai -m space --focus <span class="m">6</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">7</span> : yabai -m space --focus <span class="m">7</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">8</span> : yabai -m space --focus <span class="m">8</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">9</span> : yabai -m space --focus <span class="m">9</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 关闭当前桌面</span>
</span></span><span class="line"><span class="cl">cmd + alt - w : yabai -m space --destroy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 把窗口发送到桌面，并跟随过去 send window to desktop and follow focus</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - z : yabai -m window --space next<span class="p">;</span> yabai -m space --focus next
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">1</span> : yabai -m window --space  1<span class="p">;</span> yabai -m space --focus <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">2</span> : yabai -m window --space  2<span class="p">;</span> yabai -m space --focus <span class="m">2</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">3</span> : yabai -m window --space  3<span class="p">;</span> yabai -m space --focus <span class="m">3</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">4</span> : yabai -m window --space  4<span class="p">;</span> yabai -m space --focus <span class="m">4</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">5</span> : yabai -m window --space  5<span class="p">;</span> yabai -m space --focus <span class="m">5</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">6</span> : yabai -m window --space  6<span class="p">;</span> yabai -m space --focus <span class="m">6</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">7</span> : yabai -m window --space  7<span class="p">;</span> yabai -m space --focus <span class="m">7</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">8</span> : yabai -m window --space  8<span class="p">;</span> yabai -m space --focus <span class="m">8</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">9</span> : yabai -m window --space  9<span class="p">;</span> yabai -m space --focus <span class="m">9</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ================================ APPS ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># iTerm2</span>
</span></span><span class="line"><span class="cl">cmd - <span class="k">return</span> : open -a iTerm
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ================================ 多显示器配置 ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># focus monitora : </span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + alt - z  : yabai -m display --focus prev</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + alt - 3  : yabai -m display --focus 3</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># send window to monitor and follow focus</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + cmd - c  : yabai -m window --display next; yabai -m display --focus next</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + cmd - 1  : yabai -m window --display 1; yabai -m display --focus 1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># move floating window</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + ctrl - a : yabai -m window --move rel:-20:0</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + ctrl - s : yabai -m window --move rel:0:20</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># increase window size</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + alt - a : yabai -m window --resize left:-20:0</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + alt - w : yabai -m window --resize top:0:-20</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># decrease window size</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + cmd - s : yabai -m window --resize bottom:0:-20</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + cmd - w : yabai -m window --resize top:0:20</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># set insertion point in focused container</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + alt - h : yabai -m window --insert west</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># toggle window zoom</span>
</span></span><span class="line"><span class="cl"><span class="c1"># alt - d : yabai -m window --toggle zoom-parent</span>
</span></span><span class="line"><span class="cl"><span class="c1"># alt - f : yabai -m window --toggle zoom-fullscreen</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># toggle window split type</span>
</span></span><span class="line"><span class="cl"><span class="c1"># alt - e : yabai -m window --toggle split</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 浮动/不浮动窗口 float / unfloat window and center on screen</span>
</span></span><span class="line"><span class="cl"><span class="c1">#alt - t : yabai -m window --toggle float;yabai -m window --grid 4:4:1:1:2:2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># toggle sticky(+float), topmost, picture-in-picture</span>
</span></span><span class="line"><span class="cl"><span class="c1"># alt - p : yabai -m window --toggle sticky;\</span>
</span></span><span class="line"><span class="cl"><span class="c1">#           yabai -m window --toggle topmost;\</span>
</span></span><span class="line"><span class="cl"><span class="c1">#           yabai -m window --toggle pip</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="使用">使用</h2>
<p>使用几天后发现，skhd的快捷键经常与应用或者系统快捷键冲突，有点麻烦。</p>
<p>再者就是快捷键比较多，要多加使用才能记熟，我再使用一段时间看看情况先。</p>
<p>效果的话差不多就下面这样：</p>
<p><a href="/article/mac-tiling-yabai/image-20220520121029280_hu_13fbfc0ddb2c2fd6.webp" data-fancybox="gallery" data-src="/article/mac-tiling-yabai/image-20220520121029280_hu_13fbfc0ddb2c2fd6.webp" data-caption="效果图">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/mac-tiling-yabai/image-20220520121029280_hu_45487547f7a8f045.webp 480w, /article/mac-tiling-yabai/image-20220520121029280_hu_566e0ac6fa30cf75.webp 720w, /article/mac-tiling-yabai/image-20220520121029280_hu_1d12674daaeaaf6c.webp 960w, /article/mac-tiling-yabai/image-20220520121029280_hu_d049b745022b47ff.webp 1440w, /article/mac-tiling-yabai/image-20220520121029280_hu_13fbfc0ddb2c2fd6.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2760"
                    height="1840"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/mac-tiling-yabai/image-20220520121029280_hu_566e0ac6fa30cf75.webp"
                    srcset="/article/mac-tiling-yabai/image-20220520121029280_hu_45487547f7a8f045.webp 480w, /article/mac-tiling-yabai/image-20220520121029280_hu_566e0ac6fa30cf75.webp 720w, /article/mac-tiling-yabai/image-20220520121029280_hu_1d12674daaeaaf6c.webp 960w, /article/mac-tiling-yabai/image-20220520121029280_hu_d049b745022b47ff.webp 1440w, /article/mac-tiling-yabai/image-20220520121029280_hu_13fbfc0ddb2c2fd6.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="效果图"
                    
                />
            </picture>
        </a></p>
<p>看着还行，就是还没玩转，效率没怎么提升，遗憾。</p>
<h2 id="感谢">感谢</h2>
<p><a href="https://github.com/koekeishiya/yabai" target="_blank" rel="noopener">yabai 开源项目</a></p>
<p><a href="https://github.com/koekeishiya/skhd" target="_blank" rel="noopener">skhd 开源项目</a></p>
<p><a href="https://www.cnblogs.com/tdg-yyx/p/15972309.html" target="_blank" rel="noopener">Toretto</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>擅长捉弄的高木同学</title>
      <link>https://vccv.cc/article/takagi-san.html</link>
      <pubDate>Sat, 26 Mar 2022 14:06:28 +0000</pubDate>
      <guid>https://vccv.cc/article/takagi-san.html</guid>
      <description>高木同学TV版已然完结,特意在凌晨一点去追了，感慨良多。之前得知剧场版将于6月在日本上映，国内B站或许会引进，期待一下。另外，转载一个up主的剪辑视频，回顾了三季的剧情，做得很棒。</description>
      <content:encoded><![CDATA[<h2 id="からかい上手の高木さん">からかい上手の高木さん</h2>
<style>
    .bilibili_shortcodes {
        position: relative;
        width: 100%;
        height: 0;
        padding-bottom: 58%;
    }
    .bilibili_shortcodes iframe {
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        border-radius: var(--radius);
    }
</style>

<div class="bilibili_shortcodes">
    <iframe
            src="https://player.bilibili.com/player.html?bvid=BV1eS4y127Eg&page=1&high_quality=1&danmaku=0&as_wide=0"
            scrolling="no"
            border="0"
            frameborder="no"
            framespacing="0"
            allowfullscreen="true"
            sandbox="allow-top-navigation allow-same-origin allow-forms allow-scripts"
    >
    </iframe>
</div>

<h2 id="感想">感想</h2>
<p>《<strong>擅长捉弄的高木同学</strong>》（日语：からかい上手の高木さん）动画TV第三季在今日（3.26）完结了，或许也没有第四季了。</p>
<p>特意在凌晨一点去追了，感慨良多。</p>
<p>之前得知剧场版将于6月在日本上映，国内B站或许会引进，期待一下。</p>
<p>另外，转载一个up主的剪辑视频，回顾了三季的剧情，做得很棒。</p>
<p>感谢<a href="https://www.bilibili.com/video/BV1eS4y127Eg" target="_blank" rel="noopener">吕吕吕谷修</a>。</p>
<h2 id="更新">更新</h2>
<p><a href="/article/takagi-san/B1834133-4AB1-45BC-A0DB-3DCC418ED357_1_105_c_hu_dedf2ef8b3fc2663.webp" data-fancybox="gallery" data-src="/article/takagi-san/B1834133-4AB1-45BC-A0DB-3DCC418ED357_1_105_c_hu_dedf2ef8b3fc2663.webp" data-caption="b站评论">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/takagi-san/B1834133-4AB1-45BC-A0DB-3DCC418ED357_1_105_c_hu_dedf2ef8b3fc2663.webp 411w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="411"
                    height="1911"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/takagi-san/B1834133-4AB1-45BC-A0DB-3DCC418ED357_1_105_c_hu_dedf2ef8b3fc2663.webp"
                    srcset="/article/takagi-san/B1834133-4AB1-45BC-A0DB-3DCC418ED357_1_105_c_hu_dedf2ef8b3fc2663.webp 411w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="b站评论"
                    
                />
            </picture>
        </a></p>
]]></content:encoded>
    </item>
    <item>
      <title>macOS系统配置Aria2</title>
      <link>https://vccv.cc/article/aria2-mac.html</link>
      <pubDate>Sat, 19 Mar 2022 16:49:15 +0000</pubDate>
      <guid>https://vccv.cc/article/aria2-mac.html</guid>
      <description>备份一下macOS系统下配置aria2以及配合Chrome浏览器众多插件实现下载多线程等功能的过程。部分内容来自GitHub作者分享，已在文末注明。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<h3 id="aria2是什么">Aria2是什么</h3>
<blockquote>
<p>Aria2是一款自由、跨平台命令行界面的下载管理器，支持的下载协议有：HTTP、HTTPS、FTP、Bittorrent以及Metalink。</p>
<p>Aria2的另一个特性便是可以使用JSON-RPC和XML-RPC进行HTTP远程下载控制，JSON-RPC接口可通过WebSocket获得。</p>
</blockquote>
<p>本人主要拿来下载种子Bittorrent文件以及多线程下载。</p>
<h3 id="配置前的准备工作">配置前的准备工作</h3>
<ul>
<li>
<p>安装 <a href="https://brew.sh/index_zh-cn" target="_blank" rel="noopener">Homebrew</a> 。</p>
</li>
<li>
<p>会使用 <strong>vim</strong> 或者其他编辑器。</p>
<blockquote>
<p>常用命令：</p>
<p>在打开的vim 界面中按 <em>i</em> 键进入编辑模式；按 <em>Esc</em> 键退出编辑模式，进入命令行模式；使用 <strong>:wq</strong> 命令保存并退出。</p>
</blockquote>
</li>
</ul>
<h3 id="docker安装方式可选">Docker安装方式（可选）</h3>
<blockquote>
<p>2024/03/14 更新：</p>
<p>如果会使用docker，可以通过安装docker镜像而不影响本地环境。点击查看docker的<a href="https://vccv.cc/article/docker-macos.html" target="_blank" rel="noopener">轻量化安装</a>教程，镜像的话可以选择<a href="https://github.com/P3TERX/Aria2-Pro-Docker" target="_blank" rel="noopener">Aria2-Pro</a>。具体安装教程请参照仓库README文件（包含中文教程），本文不做展开。</p>
<p>本次更新只是多提供了一个选择，无需docker安装的忽略本小节即可。</p>
</blockquote>
<h2 id="安装并配置aria2">安装并配置Aria2</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 使用 Homebrew 安装 aria2</span>
</span></span><span class="line"><span class="cl">brew install aria2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 创建配置文件aria2.conf和空对话文件aria2.session</span>
</span></span><span class="line"><span class="cl">mkdir ~/.aria2 <span class="o">&amp;&amp;</span> <span class="nb">cd</span> ~/.aria2
</span></span><span class="line"><span class="cl">touch aria2.conf
</span></span><span class="line"><span class="cl">touch aria2.session
</span></span></code></pre></td></tr></table>
</div>
</div><p>编辑配置文件 <strong>aria2.conf</strong> ：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span><span class="lnt">150
</span><span class="lnt">151
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">##</span> <span class="err">文件保存相关</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">文件的保存路径(可使用绝对路径或相对路径),</span> <span class="err">默认:</span> <span class="err">Mac下Downloads下载文件夹</span>
</span></span><span class="line"><span class="cl"><span class="err">dir=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/Downloads</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">启用磁盘缓存,</span> <span class="mi">0</span><span class="err">为禁用缓存,</span> <span class="err">需</span><span class="mf">1.16</span><span class="err">以上版本,</span> <span class="err">默认:</span><span class="mi">16</span><span class="err">M</span>
</span></span><span class="line"><span class="cl"><span class="err">disk-cache=</span><span class="mi">32</span><span class="err">M</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">文件预分配方式,</span> <span class="err">能有效降低磁盘碎片,</span> <span class="err">默认:prealloc</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">预分配所需时间:</span> <span class="err">none</span> <span class="err">&lt;</span> <span class="err">falloc</span> <span class="err">?</span> <span class="err">trunc</span> <span class="err">&lt;</span> <span class="err">prealloc</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">falloc和trunc则需要文件系统和内核支持</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">NTFS建议使用falloc,</span> <span class="err">EXT</span><span class="mi">3</span><span class="err">/</span><span class="mi">4</span><span class="err">建议trunc,</span> <span class="err">MAC</span> <span class="err">下需要注释此项</span>
</span></span><span class="line"><span class="cl"><span class="err">#file-allocation=none</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">断点续传</span>
</span></span><span class="line"><span class="cl"><span class="err">continue=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">下载连接相关</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">最大同时下载任务数,</span> <span class="err">运行时可修改,</span> <span class="err">默认:</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-concurrent-downloads=</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">同一服务器连接数,</span> <span class="err">添加时可指定,</span> <span class="err">默认:</span><span class="mi">1</span><span class="err">,</span> <span class="err">最大值</span><span class="mi">16</span>
</span></span><span class="line"><span class="cl"><span class="err">max-connection-per-server=</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">最小文件分片大小,</span> <span class="err">添加时可指定,</span> <span class="err">取值范围</span><span class="mi">1</span><span class="err">M</span> <span class="mi">-1024</span><span class="err">M,</span> <span class="err">默认:</span><span class="mi">20</span><span class="err">M</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">假定size=</span><span class="mi">10</span><span class="err">M,</span> <span class="err">文件为</span><span class="mi">20</span><span class="err">MiB</span> <span class="err">则使用两个来源下载;</span> <span class="err">文件为</span><span class="mi">15</span><span class="err">MiB</span> <span class="err">则使用一个来源下载</span>
</span></span><span class="line"><span class="cl"><span class="err">min-split-size=</span><span class="mi">10</span><span class="err">M</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">单个任务最大线程数,</span> <span class="err">添加时可指定,</span> <span class="err">默认:</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#split=</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">分片选择算法,有助于视频的边下边播同时兼顾减少建立连接的次数</span>
</span></span><span class="line"><span class="cl"><span class="err">stream-piece-selector=geom</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">整体下载速度限制,</span> <span class="err">运行时可修改,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-overall-download-limit=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">单个任务下载速度限制,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-download-limit=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">整体上传速度限制,</span> <span class="err">运行时可修改,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-overall-upload-limit=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">单个任务上传速度限制,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-upload-limit=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">禁用IPv</span><span class="mi">6</span><span class="err">,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">#disable-ipv</span><span class="mi">6</span><span class="err">=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">连接超时时间,</span> <span class="err">默认:</span><span class="mi">60</span>
</span></span><span class="line"><span class="cl"><span class="err">#timeout=</span><span class="mi">60</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">最大重试次数,</span> <span class="err">设置为</span><span class="mi">0</span><span class="err">表示不限制重试次数,</span> <span class="err">默认:</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-tries=</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">设置重试等待的秒数,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#retry-wait=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">进度保存相关</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">日志文件</span>
</span></span><span class="line"><span class="cl"><span class="err">log-level=notice</span>
</span></span><span class="line"><span class="cl"><span class="err">log=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/aria</span><span class="mi">2</span><span class="err">.log</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">从会话文件中读取下载任务</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">需提前创建一个空文件否则会报错</span>
</span></span><span class="line"><span class="cl"><span class="err">input-file=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/aria</span><span class="mi">2</span><span class="err">.session</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">在Aria</span><span class="mi">2</span><span class="err">退出时保存`错误/未完成`的下载任务到会话文件</span>
</span></span><span class="line"><span class="cl"><span class="err">save-session=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/aria</span><span class="mi">2</span><span class="err">.session</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">定时保存会话,</span> <span class="mi">0</span><span class="err">为退出时才保存,</span> <span class="err">需</span><span class="mf">1.16</span><span class="err">.</span><span class="mi">1</span><span class="err">以上版本,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">save-session-interval=</span><span class="mi">60</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">强制保存会话,</span> <span class="err">即使任务已经完成,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">较新的版本开启后会在任务完成后依然保留.aria</span><span class="mi">2</span><span class="err">文件</span>
</span></span><span class="line"><span class="cl"><span class="err">#force-save=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">RPC相关设置</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">启用RPC,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">enable-rpc=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">允许所有来源,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">rpc-allow-origin-all=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">允许非外部访问,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">rpc-listen-all=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">RPC监听端口,</span> <span class="err">端口被占用时可以修改,</span> <span class="err">默认:</span><span class="mi">6800</span>
</span></span><span class="line"><span class="cl"><span class="err">rpc-listen-port=</span><span class="mi">6800</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">设置的RPC授权令牌</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">此处使用`openssl</span> <span class="err">rand</span> <span class="err">-base</span><span class="mi">64</span> <span class="mi">32</span><span class="err">`命令生成&lt;TOKEN&gt;</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">此次需要自行配置，将&lt;TOKEN&gt;整体替换为你的RPC“密码”</span>
</span></span><span class="line"><span class="cl"><span class="err">rpc-secret=&lt;TOKEN&gt;</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">是否启用</span> <span class="err">RPC</span> <span class="err">服务的</span> <span class="err">SSL/TLS</span> <span class="err">加密,</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">启用加密后</span> <span class="err">RPC</span> <span class="err">服务需要使用</span> <span class="err">https</span> <span class="err">或者</span> <span class="err">wss</span> <span class="err">协议连接</span>
</span></span><span class="line"><span class="cl"><span class="err">#rpc-secure=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">在</span> <span class="err">RPC</span> <span class="err">服务中启用</span> <span class="err">SSL/TLS</span> <span class="err">加密时的证书文件,</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">使用</span> <span class="err">PEM</span> <span class="err">格式时，您必须通过</span> <span class="err">--rpc-private-key</span> <span class="err">指定私钥</span>
</span></span><span class="line"><span class="cl"><span class="err">#rpc-certificate=/path/to/certificate.pem</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">在</span> <span class="err">RPC</span> <span class="err">服务中启用</span> <span class="err">SSL/TLS</span> <span class="err">加密时的私钥文件</span>
</span></span><span class="line"><span class="cl"><span class="err">#rpc-private-key=/path/to/certificate.key</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">HTTP</span> <span class="err">设置</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">自定义</span> <span class="err">User</span> <span class="err">Agent</span>
</span></span><span class="line"><span class="cl"><span class="err">user-agent=Mozilla/</span><span class="mf">5.0</span> <span class="err">(Macintosh;</span> <span class="err">Intel</span> <span class="err">Mac</span> <span class="err">OS</span> <span class="err">X</span> <span class="mi">10</span><span class="err">_</span><span class="mi">15</span><span class="err">_</span><span class="mi">1</span><span class="err">)</span> <span class="err">AppleWebKit/</span><span class="mf">537.36</span> <span class="err">(KHTML,</span> <span class="err">like</span> <span class="err">Gecko)</span> <span class="err">Chrome/</span><span class="mf">80.0</span><span class="err">.</span><span class="mf">3987.85</span> <span class="err">Safari/</span><span class="mf">537.36</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">BT/PT下载相关</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">当下载的是一个种子(以.torrent结尾)时,</span> <span class="err">自动开始BT任务,</span> <span class="err">默认:</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">follow-torrent=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT监听端口,</span> <span class="err">当端口被屏蔽时使用,</span> <span class="err">默认:</span><span class="mi">6881-6999</span>
</span></span><span class="line"><span class="cl"><span class="err">listen-port=</span><span class="mi">6881-6999</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">单个种子最大连接数,</span> <span class="err">默认:</span><span class="mi">55</span>
</span></span><span class="line"><span class="cl"><span class="err">#bt-max-peers=</span><span class="mi">55</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">###</span> <span class="err">DHT</span> <span class="err">功能,</span> <span class="err">仅对</span> <span class="err">BT</span> <span class="err">生效,</span> <span class="err">PT</span> <span class="err">无效###</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">打开</span> <span class="err">DHT</span> <span class="err">(IPv</span><span class="mi">4</span><span class="err">)</span> <span class="err">功能</span>
</span></span><span class="line"><span class="cl"><span class="err">enable-dht=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">打开</span> <span class="err">DHT</span> <span class="err">(IPv</span><span class="mi">6</span><span class="err">)</span> <span class="err">功能</span>
</span></span><span class="line"><span class="cl"><span class="err">enable-dht</span><span class="mi">6</span><span class="err">=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">DHT网络监听端口,</span> <span class="err">默认:</span><span class="mi">6881-6999</span>
</span></span><span class="line"><span class="cl"><span class="err">dht-listen-port=</span><span class="mi">6881-6999</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">本地节点查找</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-enable-lpd=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">种子交换</span>
</span></span><span class="line"><span class="cl"><span class="err">enable-peer-exchange=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">DHT</span> <span class="err">(IPv</span><span class="mi">4</span><span class="err">)</span> <span class="err">路由表文件路径</span>
</span></span><span class="line"><span class="cl"><span class="err">dht-file-path=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/dht.dat</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">DHT</span> <span class="err">(IPv</span><span class="mi">6</span><span class="err">)</span> <span class="err">路由表文件路径</span>
</span></span><span class="line"><span class="cl"><span class="err">dht-file-path</span><span class="mi">6</span><span class="err">=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/dht</span><span class="mi">6</span><span class="err">.dat</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">客户端伪装,</span> <span class="err">PT需要</span>
</span></span><span class="line"><span class="cl"><span class="err">peer-id-prefix=-UT</span><span class="mi">341</span><span class="err">-</span>
</span></span><span class="line"><span class="cl"><span class="err">peer-agent=uTorrent/</span><span class="mi">341</span><span class="err">(</span><span class="mi">109279400</span><span class="err">)(</span><span class="mi">30888</span><span class="err">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">同一服务器连接数</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">每个种子限速,</span> <span class="err">对少种的PT很有用,</span> <span class="err">默认:</span><span class="mi">50</span><span class="err">K</span>
</span></span><span class="line"><span class="cl"><span class="err">#bt-request-peer-speed-limit=</span><span class="mi">50</span><span class="err">K</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">当种子的分享率达到这个数时,</span> <span class="err">自动停止做种,</span> <span class="mi">0</span><span class="err">为一直做种,</span> <span class="err">默认:</span><span class="mf">1.0</span>
</span></span><span class="line"><span class="cl"><span class="err">seed-ratio=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT校验相关,</span> <span class="err">默认:</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#bt-hash-check-seed=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">继续之前的BT任务时,</span> <span class="err">无需再次校验,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-seed-unverified=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">保存磁力链接元数据为种子文件(.torrent文件),</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-save-metadata=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT</span> <span class="err">服务器地址</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">逗号分隔的</span> <span class="err">BT</span> <span class="err">服务器地址.</span> <span class="err">如果服务器地址在</span> <span class="err">--bt-exclude-tracker</span> <span class="err">选项中,</span> <span class="err">其将不会生效.</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-tracker=udp:</span><span class="c1">//tracker.coppersurfer.tk:6969/announce,udp://tracker.leechers-paradise.org:6969/announce,udp://tracker.opentrackr.org:1337/announce,udp://p4p.arenabg.com:1337/announce,udp://9.rarbg.to:2710/announce,udp://9.rarbg.me:2710/announce,udp://tracker.internetwarriors.net:1337/announce,udp://exodus.desync.com:6969/announce,udp://tracker.tiny-vps.com:6969/announce,udp://tracker.moeking.me:6969/announce,udp://retracker.lanta-net.ru:2710/announce,udp://open.stealth.si:80/announce,udp://open.demonii.si:1337/announce,udp://tracker.torrent.eu.org:451/announce,udp://tracker.cyberia.is:6969/announce,udp://denis.stalker.upeer.me:6969/announce,udp://tracker3.itzmx.com:6961/announce,udp://ipv4.tracker.harry.lu:80/announce,udp://valakas.rollo.dnsabr.com:2710/announce,udp://tracker.nyaa.uk:6969/announce,udp://retracker.netbynet.ru:2710/announce,udp://opentor.org:2710/announce,udp://explodie.org:6969/announce,http://explodie.org:6969/announce,udp://zephir.monocul.us:6969/announce,udp://xxxtor.com:2710/announce,udp://tracker.zum.bi:6969/announce,udp://tracker.yoshi210.com:6969/announce,udp://tracker.uw0.xyz:6969/announce,udp://tracker.sbsub.com:2710/announce,udp://tracker.lelux.fi:6969/announce,udp://tracker.iamhansen.xyz:2000/announce,udp://tracker.filemail.com:6969/announce,udp://tracker.dler.org:6969/announce,udp://retracker.sevstar.net:2710/announce,udp://retracker.akado-ural.ru:80/announce,udp://open.nyap2p.com:6969/announce,udp://chihaya.toss.li:9696/announce,udp://bt2.archive.org:6969/announce,udp://bt1.archive.org:6969/announce,udp://bt.okmp3.ru:2710/announce,https://tracker.nanoha.org:443/announce,http://tracker.torrentyorg.pl:80/announce,http://tracker.opentrackr.org:1337/announce,http://tracker.internetwarriors.net:1337/announce,http://tracker.bt4g.com:2095/announce,http://t.nyaatracker.com:80/announce,http://retracker.sevstar.net:2710/announce,http://pow7.com:80/announce,http://mail2.zelenaya.net:80/announce,http://h4.trakx.nibba.trade:80/announce,udp://tracker4.itzmx.com:2710/announce,udp://tracker2.itzmx.com:6961/announce,udp://tracker.zerobytes.xyz:1337/announce,udp://tracker.swateam.org.uk:2710/announce,udp://tr.bangumi.moe:6969/announce,udp://qg.lorzl.gq:2710/announce,udp://opentracker.i2p.rocks:6969/announce,udp://bt2.54new.com:8080/announce,https://tracker.opentracker.se:443/announce,https://tracker.lelux.fi:443/announce,http://www.loushao.net:8080/announce,http://vps02.net.orel.ru:80/announce,http://tracker4.itzmx.com:2710/announce,http://tracker3.itzmx.com:6961/announce,http://tracker2.itzmx.com:6961/announce,http://tracker1.itzmx.com:8080/announce,http://tracker01.loveapp.com:6789/announce,http://tracker.zerobytes.xyz:1337/announce,http://tracker.yoshi210.com:6969/announce,http://tracker.nyap2p.com:8080/announce,http://tracker.lelux.fi:80/announce,http://tracker.bz:80/announce,http://opentracker.i2p.rocks:6969/announce,http://open.acgnxtracker.com:80/announce
</span></span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT</span> <span class="err">排除服务器地址</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-exclude-tracker=</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">启用后台进程</span>
</span></span><span class="line"><span class="cl"><span class="err">daemon=</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">部分事件hook</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">如果使用Aria</span><span class="mi">2</span> <span class="err">Explorer插件请注释或者删除该部分内容</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">即</span> <span class="err">on-bt-download-complete</span> <span class="err">和</span> <span class="err">on-download-complete</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT下载完成(如有做种将包含做种，如需调用请务必确定设定完成做种条件)</span>
</span></span><span class="line"><span class="cl"><span class="err">on-bt-download-complete=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/download-complete-hook.sh</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">下载完成</span>
</span></span><span class="line"><span class="cl"><span class="err">on-download-complete=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/download-complete-hook.sh</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">下载错误</span>
</span></span><span class="line"><span class="cl"><span class="err">on-download-error=</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">代理</span> <span class="err">仅支持</span> <span class="err">HTTP</span> <span class="err">协议</span>
</span></span><span class="line"><span class="cl"><span class="err">#all-proxy=http:</span><span class="c1">//127.0.0.1:1087
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>本配置文件注意事项如下:</p>
<ul>
<li>默认开启 RPC 模式。</li>
<li>已设置RPC授权令牌，请自行修改为自己的。</li>
<li>已经添加 BT tracker 。</li>
<li>如果使用后文提到的Aria2 Explorer插件，请注释或者删除配置文件末尾的<em><strong>部分事件hook</strong></em>内容。</li>
</ul>
<h2 id="设置为开机自启动">设置为开机自启动</h2>
<h3 id="创建用户启动文件">创建用户启动文件</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch ~/Library/LaunchAgents/aria2.plist
</span></span><span class="line"><span class="cl">vim ~/Library/LaunchAgents/aria2.plist
</span></span></code></pre></td></tr></table>
</div>
</div><p>写入如下：</p>
<blockquote>
<p>2023/11/16 更新：</p>
<p>经评论区老哥提醒，由于brew安装位置的不同(M系列芯片默认安装位置可能在<code>/opt/homebrew/bin/</code>目录下)，下面文件中的<code>ProgramArguments</code>参数需要自行修改为本机aria2c的位置，可以使用<code>which</code>命令查看具体位置：</p>
<p><a href="/article/aria2-mac/image-20231116222506139_hu_98f573f3da97a255.webp" data-fancybox="gallery" data-src="/article/aria2-mac/image-20231116222506139_hu_98f573f3da97a255.webp" data-caption="查看aria2c目录">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/aria2-mac/image-20231116222506139_hu_f830a9ab7f68a83a.webp 480w, /article/aria2-mac/image-20231116222506139_hu_797b8ae605682813.webp 720w, /article/aria2-mac/image-20231116222506139_hu_c242272efb4c7a49.webp 960w, /article/aria2-mac/image-20231116222506139_hu_98f573f3da97a255.webp 1072w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1072"
                    height="266"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/aria2-mac/image-20231116222506139_hu_797b8ae605682813.webp"
                    srcset="/article/aria2-mac/image-20231116222506139_hu_f830a9ab7f68a83a.webp 480w, /article/aria2-mac/image-20231116222506139_hu_797b8ae605682813.webp 720w, /article/aria2-mac/image-20231116222506139_hu_c242272efb4c7a49.webp 960w, /article/aria2-mac/image-20231116222506139_hu_98f573f3da97a255.webp 1072w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="查看aria2c目录"
                    
                />
            </picture>
        </a></p>
<p>示例文件中的相关参数目录还是以上图我的aria2c目录<code>/usr/local/bin/aria2c</code>为例，你可能需要修改为<code>/opt/homebrew/bin/aria2c</code>或者其他自定义目录。</p>
</blockquote>
<blockquote>
<p>2023.10.13 更新：</p>
<p>感谢评论区小伙伴的提醒，aria2在macOS Sonoma版本使用下述plist“不能”自启动。</p>
<p>根据<a href="https://github.com/aria2/aria2/issues/2083" target="_blank" rel="noopener">官方issue#2083</a>讨论，该bug是由于aria2的依赖 <em>gettext</em> 导致的，截止文章更新时该bug应该已经修复，使用<code>brew upgrade</code>更新全部依赖即可。</p>
<p><a href="/article/aria2-mac/image-20231013145445532_hu_fb813488b1090d8f.webp" data-fancybox="gallery" data-src="/article/aria2-mac/image-20231013145445532_hu_fb813488b1090d8f.webp" data-caption="gettext依赖更新">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/aria2-mac/image-20231013145445532_hu_af2887f377135f8.webp 480w, /article/aria2-mac/image-20231013145445532_hu_a8b4391417fd40d9.webp 720w, /article/aria2-mac/image-20231013145445532_hu_974073b94baa1ec4.webp 960w, /article/aria2-mac/image-20231013145445532_hu_5c6ab51e3fee82be.webp 1440w, /article/aria2-mac/image-20231013145445532_hu_fb813488b1090d8f.webp 1572w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1572"
                    height="260"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/aria2-mac/image-20231013145445532_hu_a8b4391417fd40d9.webp"
                    srcset="/article/aria2-mac/image-20231013145445532_hu_af2887f377135f8.webp 480w, /article/aria2-mac/image-20231013145445532_hu_a8b4391417fd40d9.webp 720w, /article/aria2-mac/image-20231013145445532_hu_974073b94baa1ec4.webp 960w, /article/aria2-mac/image-20231013145445532_hu_5c6ab51e3fee82be.webp 1440w, /article/aria2-mac/image-20231013145445532_hu_fb813488b1090d8f.webp 1572w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="gettext依赖更新"
                    
                />
            </picture>
        </a></p>
<p>如果仍然无法使用，可以使用以下plist文件内容：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="cp">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
</span></span><span class="line"><span class="cl"><span class="cp">&lt;!DOCTYPE plist PUBLIC &#34;-//Apple//DTD PLIST 1.0//EN&#34; &#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#34;&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;plist</span> <span class="na">version=</span><span class="s">&#34;1.0&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;dict&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>EnvironmentVariables<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;dict&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;key&gt;</span>LC_MESSAGES<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>C<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/dict&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>KeepAlive<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>Label<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;string&gt;</span>aria2<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>ProgramArguments<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;array&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>/usr/local/bin/aria2c<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/array&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>RunAtLoad<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>WorkingDirectory<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;string&gt;</span>/Users/用户名/Downloads<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/dict&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/plist&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>主要是添加了一个<code>LC_MESSAGES='C'</code>键值对。请注意，万不得已才使用上述修改内容，因为该bug按理说已经得到官方修复。</p>
<p><a href="/article/aria2-mac/image-20231013150326965_hu_6b23f62b94f44f51.webp" data-fancybox="gallery" data-src="/article/aria2-mac/image-20231013150326965_hu_6b23f62b94f44f51.webp" data-caption="LC_MESSAGES">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/aria2-mac/image-20231013150326965_hu_80e32825ee39106e.webp 480w, /article/aria2-mac/image-20231013150326965_hu_56ca9f86169b9318.webp 720w, /article/aria2-mac/image-20231013150326965_hu_93012d79aff2f900.webp 960w, /article/aria2-mac/image-20231013150326965_hu_f24f24ff82065332.webp 1440w, /article/aria2-mac/image-20231013150326965_hu_6b23f62b94f44f51.webp 1542w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1542"
                    height="630"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/aria2-mac/image-20231013150326965_hu_56ca9f86169b9318.webp"
                    srcset="/article/aria2-mac/image-20231013150326965_hu_80e32825ee39106e.webp 480w, /article/aria2-mac/image-20231013150326965_hu_56ca9f86169b9318.webp 720w, /article/aria2-mac/image-20231013150326965_hu_93012d79aff2f900.webp 960w, /article/aria2-mac/image-20231013150326965_hu_f24f24ff82065332.webp 1440w, /article/aria2-mac/image-20231013150326965_hu_6b23f62b94f44f51.webp 1542w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="LC_MESSAGES"
                    
                />
            </picture>
        </a></p>
</blockquote>
<p>以下为原文件内容（默认使用该文件即可，出现问题无法解决再尝试上述修改文件）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="cp">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
</span></span><span class="line"><span class="cl"><span class="cp">&lt;!DOCTYPE plist PUBLIC &#34;-//Apple//DTD PLIST 1.0//EN&#34; &#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#34;&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;plist</span> <span class="na">version=</span><span class="s">&#34;1.0&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;dict&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>KeepAlive<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>Label<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;string&gt;</span>aria2<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>ProgramArguments<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;array&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>/usr/local/bin/aria2c<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/array&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>RunAtLoad<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>WorkingDirectory<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;string&gt;</span>/Users/用户名/Downloads<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/dict&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/plist&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>注意事项：</p>
<p>一定要记得替换<code>WorkingDirectory</code>参数下的用户名，以及检查<code>ProgramArguments</code>参数下的目录是否正确。</p>
</blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 检查plist语法是否正确</span>
</span></span><span class="line"><span class="cl">plutil ~/Library/LaunchAgents/aria2.plist
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 修改文件权限</span>
</span></span><span class="line"><span class="cl">chmod <span class="m">644</span> ~/Library/LaunchAgents/aria2.plist
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="添加并启用自启动项">添加并启用自启动项</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 添加自启动项: aria2</span>
</span></span><span class="line"><span class="cl">launchctl load ~/Library/LaunchAgents/aria2.plist
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 删除自启动项: aria2</span>
</span></span><span class="line"><span class="cl">launchctl unload ~/Library/LaunchAgents/aria2.plist
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 启动服务: aria2</span>
</span></span><span class="line"><span class="cl">launchctl start aria2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 停止服务: aria2</span>
</span></span><span class="line"><span class="cl">launchctl stop aria2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 强制添加 加上-w参数</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 这个命令是最后无奈之举才尝试运行，不推荐</span>
</span></span><span class="line"><span class="cl">launchctl load -w ~/Library/LaunchAgents/aria2.plist
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>注意事项：</p>
<p>如果以前添加过aria2启动项，再次操作时记得先删除启动项再重新添加！</p>
<p>2024/03/14 更新：</p>
<p>如果提示诸如<code>Load failed: 5: Input/output error Try running launchctl bootstrap as root for richer errors.</code>此类的错误，请先按照上述指引检查aria2c路径或者尝试更新全部brew依赖。若没有解决请尝试先删除启动项再进行load。如果还是不行，可以加上-w参数强制添加。实在不行请评论区反馈或者查看以往评论进行尝试。</p>
</blockquote>
<h2 id="添加自动更新-bt-tracker-功能">添加自动更新 BT tracker 功能</h2>
<h3 id="创建-trackers-list-aria2sh-脚本">创建 trackers-list-aria2.sh 脚本</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch ~/.aria2/trackers-list-aria2.sh
</span></span><span class="line"><span class="cl">vim ~/.aria2/trackers-list-aria2.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>脚本内容如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="c1"># 文件名 trackers-list-aria2.sh</span>
</span></span><span class="line"><span class="cl"><span class="c1"># aria2 设置文件路径</span>
</span></span><span class="line"><span class="cl"><span class="nv">CONF</span><span class="o">=</span><span class="si">${</span><span class="nv">HOME</span><span class="si">}</span>/.aria2/aria2.conf
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 设置选择的 trackerlist （可选 all_aria2.txt, best_aria2.txt, http_aria2.txt）</span>
</span></span><span class="line"><span class="cl"><span class="nv">trackerfile</span><span class="o">=</span>all_aria2.txt
</span></span><span class="line"><span class="cl"><span class="c1"># downloadfile=https://raw.githubusercontent.com/ngosang/trackerslist/master/${trackerfile}</span>
</span></span><span class="line"><span class="cl"><span class="nv">downloadfile</span><span class="o">=</span>https://trackerslist.com/<span class="si">${</span><span class="nv">trackerfile</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">list</span><span class="o">=</span><span class="k">$(</span>curl -fsSL <span class="si">${</span><span class="nv">downloadfile</span><span class="si">}</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> ! grep -q <span class="s2">&#34;bt-tracker&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CONF</span><span class="si">}</span><span class="s2">&#34;</span> <span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> -e <span class="s2">&#34;\033[34m==&gt; 添加 bt-tracker 服务器信息......\033[0m&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> -e <span class="s2">&#34;\nbt-tracker=</span><span class="si">${</span><span class="nv">list</span><span class="si">}</span><span class="s2">&#34;</span> &gt;&gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CONF</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> -e <span class="s2">&#34;\033[34m==&gt; 更新 bt-tracker 服务器信息.....\033[0m&#34;</span>
</span></span><span class="line"><span class="cl">    sed -i <span class="s1">&#39;&#39;</span> <span class="s2">&#34;s@bt-tracker.*@bt-tracker=</span><span class="si">${</span><span class="nv">list</span><span class="si">}</span><span class="s2">@g&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CONF</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 重启 aria2 服务</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> -e <span class="s2">&#34;\033[34m==&gt; 停止 aria2 服务......\033[0m&#34;</span>
</span></span><span class="line"><span class="cl">launchctl stop aria2
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> -e <span class="s2">&#34;\033[34m==&gt; 启动 aria2 服务......\033[0m&#34;</span>
</span></span><span class="line"><span class="cl">launchctl start aria2
</span></span></code></pre></td></tr></table>
</div>
</div><p>设置运行权限：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">chmod +x ~/.aria2/trackers-list-aria2.sh
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="设置任务计划程序-实现自动更新">设置任务计划程序 实现自动更新</h3>
<p>编译当前用户任务计划：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">crontab -e
</span></span></code></pre></td></tr></table>
</div>
</div><p>可用 <strong>crontab -l</strong> 查看当前用户任务计划。文件内容如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">MAILTO</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span> <span class="m">18</span> * * * ~/.aria2/trackers-list-aria2.sh
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>2022/05/27 更新：</p>
<p>添加 <em>MAILTO = &ldquo;&rdquo;</em> 配置避免终端出现 <em>You have new mail</em> 提示。</p>
<p>如果已经出现此类通知，输入 <code>mail</code> 即可查看并消除。</p>
</blockquote>
<p>或者直接输入：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">(</span>crontab -l 2<span class="p">&amp;</span>&gt; /dev/null<span class="p">;</span> <span class="nb">echo</span> <span class="s2">&#34;0 18 * * * ~/.aria2/trackers-list-aria2.sh&#34;</span><span class="o">)</span> <span class="p">|</span> crontab
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>以上表示：</p>
<p>每天下午 6 点自动更新 BT tracker 并重启 aria2 服务。</p>
<p>取消计划任务：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">crontab -e
</span></span></code></pre></td></tr></table>
</div>
</div><p>然后手动删除内容，或者直接运行：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">crontab -l 2<span class="p">&amp;</span>&gt; /dev/null<span class="p">|</span> sed <span class="s2">&#34;/trackers-list-aria2.sh/d&#34;</span> <span class="p">|</span> crontab
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h3 id="添加下载通知">添加下载通知</h3>
<blockquote>
<p>2024.08.19 更新：</p>
<p>如果使用后文提到的Aria2 Explorer插件，请忽略本小节内容。</p>
</blockquote>
<p>最终效果：当下载完成会在屏幕右上角弹出一个提示框显示具体下载完成的文件名，同时语音播报：“有个文件下载完成，请查收！”</p>
<p><a href="/article/aria2-mac/image-20220319180124115_hu_20eb603bc0fd28b8.webp" data-fancybox="gallery" data-src="/article/aria2-mac/image-20220319180124115_hu_20eb603bc0fd28b8.webp" data-caption="macOS 下aria2 提示框实例">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/aria2-mac/image-20220319180124115_hu_143c9d9257067920.webp 480w, /article/aria2-mac/image-20220319180124115_hu_299aa375bd663ec0.webp 720w, /article/aria2-mac/image-20220319180124115_hu_20eb603bc0fd28b8.webp 744w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="744"
                    height="180"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/aria2-mac/image-20220319180124115_hu_299aa375bd663ec0.webp"
                    srcset="/article/aria2-mac/image-20220319180124115_hu_143c9d9257067920.webp 480w, /article/aria2-mac/image-20220319180124115_hu_299aa375bd663ec0.webp 720w, /article/aria2-mac/image-20220319180124115_hu_20eb603bc0fd28b8.webp 744w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="macOS 下aria2 提示框实例"
                    
                />
            </picture>
        </a></p>
<h3 id="创建-download-complete-hooksh-脚本">创建 download-complete-hook.sh 脚本</h3>
<blockquote>
<p>2024.08.19 更新：</p>
<p>如果使用后文提到的Aria2 Explorer插件，请忽略本小节内容。</p>
</blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch ~/.aria2/download-complete-hook.sh
</span></span><span class="line"><span class="cl">vim ~/.aria2/download-complete-hook.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>脚本内容如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/sh
</span></span></span><span class="line"><span class="cl"><span class="c1"># 文件名 download-complete-hook.sh</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 给aria2 RPC添加一个下载完成通知 for macOS</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 变量 3 表示下载完成文件的路径</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 具体提示框设置可参考`https://code-maven.com/display-notification-from-the-mac-command-line`。</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 不支持设置自定义图标</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">fname</span><span class="o">=</span><span class="sb">`</span>basename <span class="nv">$3</span><span class="sb">`</span>
</span></span><span class="line"><span class="cl">osascript <span class="s">&lt;&lt;EOF
</span></span></span><span class="line"><span class="cl"><span class="s">display notification &#34;$fname 已经下载完成！&#34; with title &#34;【下载完成】&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">say &#34;有个文件下载完成，请查收！&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>设置运行权限：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">chmod +x ~/.aria2/download-complete-hook.sh
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="添加-hook-设置">添加 Hook 设置</h3>
<blockquote>
<p>上面的 <em>aria2.conf</em> 配置文件已经包含了如下内容，使用上面文件的可以直接跳过此部分。</p>
<p>除此之外，如果使用后文提到的Aria2 Explorer插件，也可以删除配置文件中关于这部分的内容。</p>
</blockquote>
<p>在 aria2 设置文件 <strong>aria2.conf</strong> 加入如下内容：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT下载完成(如有做种将包含做种，如需调用请务必确定设定完成做种条件)</span>
</span></span><span class="line"><span class="cl"><span class="err">on-bt-download-complete=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/download-complete-hook.sh</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">下载完成</span>
</span></span><span class="line"><span class="cl"><span class="err">on-download-complete=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/download-complete-hook.sh</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="aria2-web-ui">Aria2 web UI</h2>
<p>无需安装，直接使用浏览器打开： <a href="http://ariang.mayswind.net/latest/" target="_blank" rel="noopener">AriaNg版 UI</a> 。</p>
<h3 id="prc-设置">PRC 设置</h3>
<blockquote>
<p>根据 <em>aria2.conf</em> 配置文件中的 PRC 相关设置项进行设置。</p>
</blockquote>
<p><a href="/article/aria2-mac/image-20220319180542315_hu_ad100b1b20b776b0.webp" data-fancybox="gallery" data-src="/article/aria2-mac/image-20220319180542315_hu_ad100b1b20b776b0.webp" data-caption="AriaNg PRC设置">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/aria2-mac/image-20220319180542315_hu_55e35000499379b5.webp 480w, /article/aria2-mac/image-20220319180542315_hu_a38fe1c7d7b2007e.webp 720w, /article/aria2-mac/image-20220319180542315_hu_547e522f5efb545a.webp 960w, /article/aria2-mac/image-20220319180542315_hu_ad100b1b20b776b0.webp 1196w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1196"
                    height="856"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/aria2-mac/image-20220319180542315_hu_a38fe1c7d7b2007e.webp"
                    srcset="/article/aria2-mac/image-20220319180542315_hu_55e35000499379b5.webp 480w, /article/aria2-mac/image-20220319180542315_hu_a38fe1c7d7b2007e.webp 720w, /article/aria2-mac/image-20220319180542315_hu_547e522f5efb545a.webp 960w, /article/aria2-mac/image-20220319180542315_hu_ad100b1b20b776b0.webp 1196w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="AriaNg PRC设置"
                    
                />
            </picture>
        </a></p>
<h2 id="安装浏览器下载插件">安装浏览器下载插件</h2>
<h3 id="aria2-explorer">Aria2 Explorer</h3>
<blockquote>
<p>2024.08.19 更新：</p>
<p>首先感谢评论区老哥Chlorine的提醒，让我能够有机会继续完善本章节。</p>
</blockquote>
<p>推荐配合<em><strong>Aria2 Explorer</strong></em>浏览器插件使用，Aria2-Explorer 能够自动拦截浏览器下载任务并通过JSON-RPC接口导出到Aria2进行高速下载并内置AriaNG作为管理前端。点击<a href="https://chromewebstore.google.com/detail/aria2-explorer/mpkodccbngfoacfalldjimigbofkhgjn" target="_blank" rel="noopener">Chrome插件地址</a>进行安装以及查看具体使用教程，其实主要是修改<strong>Server地址</strong>和<strong>RPC密钥</strong>。</p>
<p><a href="/article/aria2-mac/example-setting_hu_7574b7f761e8042f.webp" data-fancybox="gallery" data-src="/article/aria2-mac/example-setting_hu_7574b7f761e8042f.webp" data-caption="官方配置示意图">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/aria2-mac/example-setting_hu_2658ce0808963af0.webp 480w, /article/aria2-mac/example-setting_hu_af632ee3193a45e.webp 720w, /article/aria2-mac/example-setting_hu_7574b7f761e8042f.webp 800w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="800"
                    height="500"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/aria2-mac/example-setting_hu_af632ee3193a45e.webp"
                    srcset="/article/aria2-mac/example-setting_hu_2658ce0808963af0.webp 480w, /article/aria2-mac/example-setting_hu_af632ee3193a45e.webp 720w, /article/aria2-mac/example-setting_hu_7574b7f761e8042f.webp 800w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="官方配置示意图"
                    
                />
            </picture>
        </a></p>
<p><a href="/article/aria2-mac/image-20240819104302578_hu_6639e78e4ac39a77.webp" data-fancybox="gallery" data-src="/article/aria2-mac/image-20240819104302578_hu_6639e78e4ac39a77.webp" data-caption="中文配置示意图">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/aria2-mac/image-20240819104302578_hu_821f5ed8759801d2.webp 480w, /article/aria2-mac/image-20240819104302578_hu_3f10c90f8cc9171d.webp 720w, /article/aria2-mac/image-20240819104302578_hu_97248a62f4d14f0.webp 960w, /article/aria2-mac/image-20240819104302578_hu_20b631f5fac9b885.webp 1440w, /article/aria2-mac/image-20240819104302578_hu_6639e78e4ac39a77.webp 2360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2360"
                    height="1124"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/aria2-mac/image-20240819104302578_hu_3f10c90f8cc9171d.webp"
                    srcset="/article/aria2-mac/image-20240819104302578_hu_821f5ed8759801d2.webp 480w, /article/aria2-mac/image-20240819104302578_hu_3f10c90f8cc9171d.webp 720w, /article/aria2-mac/image-20240819104302578_hu_97248a62f4d14f0.webp 960w, /article/aria2-mac/image-20240819104302578_hu_20b631f5fac9b885.webp 1440w, /article/aria2-mac/image-20240819104302578_hu_6639e78e4ac39a77.webp 2360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="中文配置示意图"
                    
                />
            </picture>
        </a></p>
<p>除此之外，如果使用了这个插件，可以配合插件本身具备的通知功能，适当删减<code>aria2.conf</code>配置文件以及跳过<em><strong>添加下载通知</strong></em>等相关章节内容，所有关于通知功能的内容都可以直接删除和跳过，进一步缩减配置文件和过程的复杂性。</p>
<h3 id="aria2-for-chrome">Aria2 for Chrome</h3>
<blockquote>
<p>2024.08.19 更新：</p>
<p>更加推荐前面提到的Aria2 Explorer插件。</p>
</blockquote>
<p><a href="https://chrome.google.com/webstore/detail/aria2-for-chrome/mpkodccbngfoacfalldjimigbofkhgjn" target="_blank" rel="noopener">Aria2 for Chrome插件</a></p>
<ul>
<li>内置一个离线 AriaNg版 UI</li>
<li>整合右键下载菜单</li>
</ul>
<blockquote>
<p>内置的离线AriaNg版也需要 <em>设置PRC</em> ，否则无法成功连接。</p>
</blockquote>
<h2 id="仅供参考">仅供参考</h2>
<h3 id="网盘文件下载">网盘文件下载</h3>
<p><a href="https://greasyfork.org/zh-CN/scripts/436446" target="_blank" rel="noopener">网盘直链下载助手</a>：需要通过安装拓展插件 <a href="https://violentmonkey.github.io/get-it/" target="_blank" rel="noopener">Violentmonkey</a> 或者 <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener">Tampermonkey</a> 等脚本管理器来启用。</p>
<h4 id="使用方法">使用方法</h4>
<blockquote>
<p>配合<a href="https://chrome.google.com/webstore/detail/aria2-for-chrome/mpkodccbngfoacfalldjimigbofkhgjn" target="_blank" rel="noopener">Aria2 for Chrome插件</a>使用。</p>
</blockquote>
<ol>
<li>选择要下载的文件，点击下载助手页面里的“Aria下载”或者“RPC下载”推送到Aria2 UI界面。</li>
<li>使用鼠标点击相应选项后，选择“发送链接”，然后确定下载。</li>
</ol>
<p><a href="/article/aria2-mac/QQ20220319-175017.gif" data-fancybox="gallery" data-src="/article/aria2-mac/QQ20220319-175017.gif" data-caption="插件使用示例">
            <img
                width="480"
                height="176"
                style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                loading="lazy"
                decoding="async"
                src="/article/aria2-mac/QQ20220319-175017.gif"
                alt="插件使用示例"
                
            />
        </a></p>
<h2 id="感谢">感谢</h2>
<p><a href="https://github.com/maboloshi/" target="_blank" rel="noopener">GitHub作者沙漠之子</a></p>
<p><a href="https://www.yoghurtlee.com/hello-aria2/" target="_blank" rel="noopener">Hello，Aria2</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>服务器利用之青龙面板</title>
      <link>https://vccv.cc/article/qinglong-jd.html</link>
      <pubDate>Thu, 10 Mar 2022 13:04:37 +0000</pubDate>
      <guid>https://vccv.cc/article/qinglong-jd.html</guid>
      <description>在接触到了青龙面板部署签到后查阅了很多资料，发现都是东一个西一篇的简单介绍，所以萌生了写下这篇文章的想法。教程详细，将自己踩的坑悉数罗列，如有遗漏，欢迎补充！</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>由于我的本意是压榨闲置服务器的价值，所以本篇文章都是以云服务器为本体进行部署，其他设备比如N1或者玩客云，请自行查找资料部署。</p>
<h2 id="服务器选择">服务器选择</h2>
<p>地区选择：</p>
<p>最好选择国内服务器，这样对京东挂机来说比较安全，但是有网络问题（连接GitHub不稳定，比较麻烦），国外服务器则没有这方面的问题。</p>
<p>系统选择Centos 7 x64。</p>
<blockquote>
<p>Centos 7相对于青龙面板来说是较好的，亲测Ubuntu系统有些环境依赖安装不上，比较麻烦。</p>
</blockquote>
<h2 id="安装">安装</h2>
<h3 id="方法一">方法一</h3>
<p>使用 <strong>docker-compose</strong> 进行安装。</p>
<blockquote>
<p>macOS安装：</p>
<p>使用Homebrew安装，<a href="https://vccv.cc/article/docker-macos.html" target="_blank" rel="noopener">点击查看</a>。</p>
</blockquote>
<ul>
<li>docker-compose 安装</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-<span class="sb">`</span>uname -s<span class="sb">`</span>-<span class="sb">`</span>uname -m<span class="sb">`</span> -o /usr/local/bin/docker-compose
</span></span><span class="line"><span class="cl">sudo chmod +x /usr/local/bin/docker-compose
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>启动容器</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir qinglong
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> qinglong
</span></span><span class="line"><span class="cl">wget https://raw.githubusercontent.com/whyour/qinglong/master/docker/docker-compose.yml
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 启动</span>
</span></span><span class="line"><span class="cl">docker-compose up -d
</span></span><span class="line"><span class="cl"><span class="c1"># 停止</span>
</span></span><span class="line"><span class="cl">docker-compose down
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="方法二">方法二</h3>
<p>直接使用docker安装</p>
<ul>
<li>
<p>安装<strong>Docker</strong>：</p>
<blockquote>
<p>2022.12.05 更新：</p>
<p>推荐macOS用户使用Colima安装docker运行环境，<a href="https://vccv.cc/article/docker-macos.html" target="_blank" rel="noopener">点击查看</a>。</p>
</blockquote>
<p>国内：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">curl -fsSL https://get.docker.com <span class="p">|</span> bash -s docker --mirror Aliyun
</span></span></code></pre></td></tr></table>
</div>
</div><p>国外：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">curl -fsSL https://get.docker.com <span class="p">|</span> bash -s docker
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>启动Docker并设置自启：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo systemctl start docker
</span></span><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> docker
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>拉取镜像</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">docker pull whyour/qinglong:latest
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>部署面板</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run -dit <span class="se">\
</span></span></span><span class="line"><span class="cl">-v <span class="nv">$PWD</span>/ql/config:/ql/config <span class="se">\
</span></span></span><span class="line"><span class="cl">-v <span class="nv">$PWD</span>/ql/log:/ql/log <span class="se">\
</span></span></span><span class="line"><span class="cl">-v <span class="nv">$PWD</span>/ql/db:/ql/db <span class="se">\
</span></span></span><span class="line"><span class="cl">-p 5600:5600 <span class="se">\
</span></span></span><span class="line"><span class="cl">--name qinglong <span class="se">\
</span></span></span><span class="line"><span class="cl">--hostname qinglong <span class="se">\
</span></span></span><span class="line"><span class="cl">--restart always <span class="se">\
</span></span></span><span class="line"><span class="cl">whyour/qinglong:latest
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>第五行端口号（5600）建议修改一下，安全一些。</p>
</blockquote>
</li>
</ul>
<h2 id="初始化">初始化</h2>
<p>访问 <strong>IP:端口号</strong> ，例如本地地址127.0.0.1:5600进入青龙面板安装界面。</p>
<p><a href="/article/qinglong-jd/image-20220310160646421_hu_f01ef1d287d5dfa1.webp" data-fancybox="gallery" data-src="/article/qinglong-jd/image-20220310160646421_hu_f01ef1d287d5dfa1.webp" data-caption="初始化">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/qinglong-jd/image-20220310160646421_hu_d20b495683bdbf46.webp 480w, /article/qinglong-jd/image-20220310160646421_hu_41b0bf1d4c2bc5e.webp 720w, /article/qinglong-jd/image-20220310160646421_hu_d44d6a3645478e1f.webp 960w, /article/qinglong-jd/image-20220310160646421_hu_eb18c1254dee5843.webp 1440w, /article/qinglong-jd/image-20220310160646421_hu_f01ef1d287d5dfa1.webp 1582w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1582"
                    height="1078"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/qinglong-jd/image-20220310160646421_hu_41b0bf1d4c2bc5e.webp"
                    srcset="/article/qinglong-jd/image-20220310160646421_hu_d20b495683bdbf46.webp 480w, /article/qinglong-jd/image-20220310160646421_hu_41b0bf1d4c2bc5e.webp 720w, /article/qinglong-jd/image-20220310160646421_hu_d44d6a3645478e1f.webp 960w, /article/qinglong-jd/image-20220310160646421_hu_eb18c1254dee5843.webp 1440w, /article/qinglong-jd/image-20220310160646421_hu_f01ef1d287d5dfa1.webp 1582w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="初始化"
                    
                />
            </picture>
        </a></p>
<p>按照流程走一遍即可。</p>
<blockquote>
<p>通知设置那里可以配置多种通知方式，选择一个你最常用的。如果没有，也可以跳过或者百度一下Sever酱（简单，不推荐）、企业微信机器人（有使用企业微信的推荐）。</p>
<p><a href="/article/qinglong-jd/image-20220310161019853_hu_d7cafd0f482253a4.webp" data-fancybox="gallery" data-src="/article/qinglong-jd/image-20220310161019853_hu_d7cafd0f482253a4.webp" data-caption="通知设置">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/qinglong-jd/image-20220310161019853_hu_2e75e6e8224ee0da.webp 480w, /article/qinglong-jd/image-20220310161019853_hu_90353ec5f8129422.webp 720w, /article/qinglong-jd/image-20220310161019853_hu_e7de64836634f7f8.webp 960w, /article/qinglong-jd/image-20220310161019853_hu_42eaa0e6979b6edc.webp 1440w, /article/qinglong-jd/image-20220310161019853_hu_d7cafd0f482253a4.webp 1548w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1548"
                    height="1068"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/qinglong-jd/image-20220310161019853_hu_90353ec5f8129422.webp"
                    srcset="/article/qinglong-jd/image-20220310161019853_hu_2e75e6e8224ee0da.webp 480w, /article/qinglong-jd/image-20220310161019853_hu_90353ec5f8129422.webp 720w, /article/qinglong-jd/image-20220310161019853_hu_e7de64836634f7f8.webp 960w, /article/qinglong-jd/image-20220310161019853_hu_42eaa0e6979b6edc.webp 1440w, /article/qinglong-jd/image-20220310161019853_hu_d7cafd0f482253a4.webp 1548w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="通知设置"
                    
                />
            </picture>
        </a></p>
</blockquote>
<h2 id="添加任务">添加任务</h2>
<p>进入主菜单，右上角选择新建任务：</p>
<p><a href="/article/qinglong-jd/image-20220310161222686_hu_8921b535e66a05cf.webp" data-fancybox="gallery" data-src="/article/qinglong-jd/image-20220310161222686_hu_8921b535e66a05cf.webp" data-caption="添加任务">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/qinglong-jd/image-20220310161222686_hu_9ae779ac997b3c3c.webp 480w, /article/qinglong-jd/image-20220310161222686_hu_d01561829de613b7.webp 720w, /article/qinglong-jd/image-20220310161222686_hu_e7017497bccbb5dc.webp 960w, /article/qinglong-jd/image-20220310161222686_hu_c1cf720d400f404a.webp 1440w, /article/qinglong-jd/image-20220310161222686_hu_8921b535e66a05cf.webp 1678w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1678"
                    height="1008"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/qinglong-jd/image-20220310161222686_hu_d01561829de613b7.webp"
                    srcset="/article/qinglong-jd/image-20220310161222686_hu_9ae779ac997b3c3c.webp 480w, /article/qinglong-jd/image-20220310161222686_hu_d01561829de613b7.webp 720w, /article/qinglong-jd/image-20220310161222686_hu_e7017497bccbb5dc.webp 960w, /article/qinglong-jd/image-20220310161222686_hu_c1cf720d400f404a.webp 1440w, /article/qinglong-jd/image-20220310161222686_hu_8921b535e66a05cf.webp 1678w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="添加任务"
                    
                />
            </picture>
        </a></p>
<p>名称随意，可不填；命令如下，一行一个，共九个；定时规则可自己填写，我这里默认 0 0 0 * * * ，表示每一天的0时0分0秒。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">ql repo https://github.com/KingRan/KR.git <span class="s2">&#34;jd_|jx_|jdCookie&#34;</span> <span class="s2">&#34;activity|backUp&#34;</span> <span class="s2">&#34;^jd[^_]|USER|utils|function|sign|sendNotify|ql|JDJR&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/curtinlv/JD-Script.git
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/Zy143L/wskey.git <span class="s2">&#34;wskey&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo ql repo https://github.com/smiek2121/scripts.git <span class="s2">&#34;jd_|gua_&#34;</span> <span class="s2">&#34;&#34;</span> <span class="s2">&#34;ZooFaker_Necklace.js|JDJRValidator_Pure.js|sign_graphics_validate.js|cleancart_activity.js|jdCookie.js|sendNotify.js&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/Yun-City/City.git <span class="s2">&#34;jd_|jx_|gua_|jddj_|getJDCookie&#34;</span> <span class="s2">&#34;activity|backUp&#34;</span> <span class="s2">&#34;^jd[^_]|USER|function|utils|sendnotify|ZooFaker_Necklace|jd_Cookie|JDJRValidator_|sign_graphics_validate|ql|magic|cleancart_activity&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/6dylan6/jdpro.git <span class="s2">&#34;jd_|jx_|jddj_&#34;</span> <span class="s2">&#34;backUp&#34;</span> <span class="s2">&#34;^jd[^_]|USER|JD|function|sendNotify&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/gys619/Absinthe.git <span class="s2">&#34;jd_|jx_|jddj_|gua_|getJDCookie|wskey&#34;</span> <span class="s2">&#34;activity|backUp&#34;</span> <span class="s2">&#34;^jd[^_]|USER|utils|ZooFaker_Necklace|JDJRValidator_|sign_graphics_validate|jddj_cookie|function|ql|magic|JDJR|JD&#34;</span> <span class="s2">&#34;main&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/zero205/JD_tencent_scf.git <span class="s2">&#34;jd_|jx_|jdCookie&#34;</span> <span class="s2">&#34;backUp|icon&#34;</span> <span class="s2">&#34;^jd[^_]|USER|sendNotify|sign_graphics_validate|JDJR|JDSign|ql&#34;</span> <span class="s2">&#34;main&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/whyour/hundun.git <span class="s2">&#34;quanx&#34;</span> <span class="s2">&#34;tokens|caiyun|didi|donate|fold|Env&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/article/qinglong-jd/image-20220310162558349_hu_28b34a0b61a194d6.webp" data-fancybox="gallery" data-src="/article/qinglong-jd/image-20220310162558349_hu_28b34a0b61a194d6.webp" data-caption="新建任务">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/qinglong-jd/image-20220310162558349_hu_a32c3e64348d8f22.webp 480w, /article/qinglong-jd/image-20220310162558349_hu_5973386631a9e0e9.webp 720w, /article/qinglong-jd/image-20220310162558349_hu_8e868643682d63f7.webp 960w, /article/qinglong-jd/image-20220310162558349_hu_28b34a0b61a194d6.webp 1030w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1030"
                    height="1034"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/qinglong-jd/image-20220310162558349_hu_5973386631a9e0e9.webp"
                    srcset="/article/qinglong-jd/image-20220310162558349_hu_a32c3e64348d8f22.webp 480w, /article/qinglong-jd/image-20220310162558349_hu_5973386631a9e0e9.webp 720w, /article/qinglong-jd/image-20220310162558349_hu_8e868643682d63f7.webp 960w, /article/qinglong-jd/image-20220310162558349_hu_28b34a0b61a194d6.webp 1030w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="新建任务"
                    
                />
            </picture>
        </a></p>
<p>全部填写好后，我们主动运行一遍，全选后点击 <strong>批量运行</strong> 。等一会儿会发现多出了几百个任务。</p>
<h2 id="配置京东cookie">配置京东cookie</h2>
<p>这里我使用的是 <strong>Google浏览器</strong> ，访问京东 <em><a href="https://bean.m.jd.com/bean/signIndex.action" target="_blank" rel="noopener">移动网页端签到地址</a></em> ，打开开发者模式（<strong>快捷键：F12</strong>），打开<strong>网络</strong>（Network）标签，按照网页提示登录你的京东账号，复制账号 Cookie，如下图所示：</p>
<p><a href="/article/qinglong-jd/image-20220310163451895_hu_15c04ab904506340.webp" data-fancybox="gallery" data-src="/article/qinglong-jd/image-20220310163451895_hu_15c04ab904506340.webp" data-caption="京东cookie">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/qinglong-jd/image-20220310163451895_hu_3453950250d867c4.webp 480w, /article/qinglong-jd/image-20220310163451895_hu_60f714e85df6877d.webp 720w, /article/qinglong-jd/image-20220310163451895_hu_f044d4622c6eb926.webp 960w, /article/qinglong-jd/image-20220310163451895_hu_c5378ef5ff019761.webp 1440w, /article/qinglong-jd/image-20220310163451895_hu_15c04ab904506340.webp 1662w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1662"
                    height="958"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/qinglong-jd/image-20220310163451895_hu_60f714e85df6877d.webp"
                    srcset="/article/qinglong-jd/image-20220310163451895_hu_3453950250d867c4.webp 480w, /article/qinglong-jd/image-20220310163451895_hu_60f714e85df6877d.webp 720w, /article/qinglong-jd/image-20220310163451895_hu_f044d4622c6eb926.webp 960w, /article/qinglong-jd/image-20220310163451895_hu_c5378ef5ff019761.webp 1440w, /article/qinglong-jd/image-20220310163451895_hu_15c04ab904506340.webp 1662w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="京东cookie"
                    
                />
            </picture>
        </a>然后回到青龙面板，选择 <strong>环境变量</strong>&mdash;&gt;<strong>新建变量</strong> ，名称为 <strong>JD_COOKIE</strong> ，值为刚复制的Cookie，自动拆分保持为<strong>否</strong>。点击确定，添加完毕。</p>
<p><a href="/article/qinglong-jd/image-20220310163958888_hu_97b6c36607162268.webp" data-fancybox="gallery" data-src="/article/qinglong-jd/image-20220310163958888_hu_97b6c36607162268.webp" data-caption="新建变量">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/qinglong-jd/image-20220310163958888_hu_348f883a8b9f5549.webp 480w, /article/qinglong-jd/image-20220310163958888_hu_ddf1cd58dd81abdf.webp 720w, /article/qinglong-jd/image-20220310163958888_hu_1aaa3ef4f1c6f341.webp 960w, /article/qinglong-jd/image-20220310163958888_hu_d53543069bb792b5.webp 1440w, /article/qinglong-jd/image-20220310163958888_hu_97b6c36607162268.webp 1670w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1670"
                    height="1124"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/qinglong-jd/image-20220310163958888_hu_ddf1cd58dd81abdf.webp"
                    srcset="/article/qinglong-jd/image-20220310163958888_hu_348f883a8b9f5549.webp 480w, /article/qinglong-jd/image-20220310163958888_hu_ddf1cd58dd81abdf.webp 720w, /article/qinglong-jd/image-20220310163958888_hu_1aaa3ef4f1c6f341.webp 960w, /article/qinglong-jd/image-20220310163958888_hu_d53543069bb792b5.webp 1440w, /article/qinglong-jd/image-20220310163958888_hu_97b6c36607162268.webp 1670w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="新建变量"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>一些小提示：</p>
<ul>
<li><del>多账号只需要在值里面<em>换行输入下一个Cookie</em>，不能再创建一个变量。</del></li>
<li>多账号配置在最新版本中需要先 <em>全部换行输入</em> 再勾选 <em>自动拆分</em> 即可。<a href="/article/qinglong-jd/image-20220602190147235_hu_ca51d9104accfef9.webp" data-fancybox="gallery" data-src="/article/qinglong-jd/image-20220602190147235_hu_ca51d9104accfef9.webp" data-caption="多账号配置">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/qinglong-jd/image-20220602190147235_hu_75ed5145a134bec.webp 480w, /article/qinglong-jd/image-20220602190147235_hu_afbcf6f98e642a22.webp 720w, /article/qinglong-jd/image-20220602190147235_hu_a2e3f05b1fa5d377.webp 960w, /article/qinglong-jd/image-20220602190147235_hu_ca51d9104accfef9.webp 1050w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1050"
                    height="1014"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/qinglong-jd/image-20220602190147235_hu_afbcf6f98e642a22.webp"
                    srcset="/article/qinglong-jd/image-20220602190147235_hu_75ed5145a134bec.webp 480w, /article/qinglong-jd/image-20220602190147235_hu_afbcf6f98e642a22.webp 720w, /article/qinglong-jd/image-20220602190147235_hu_a2e3f05b1fa5d377.webp 960w, /article/qinglong-jd/image-20220602190147235_hu_ca51d9104accfef9.webp 1050w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="多账号配置"
                    
                />
            </picture>
        </a></li>
<li>Cookie值只需要其中的 <em>pt_key</em> 与 <em>pt_pin</em> 就可以了，不懂的话全部复制粘贴上去也没问题。</li>
<li>不要频繁的去执行，避免黑号。</li>
<li>京东账号建议绑定微信，活动抽奖抽到微信红包会自动提现到微信钱包。</li>
</ul>
</blockquote>
<h2 id="修改配置文件可选">修改配置文件（可选）</h2>
<p>点击 <strong>配置文件</strong> ，可以修改其中的通知推送服务。这里的通知推送是每日任务的推送，开头设置的推送是青龙面板的登录推送等。这里建议设置一下，但是需注意，消息通常特别多。</p>
<h2 id="安装依赖">安装依赖</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="c1"># 进入容器</span>
</span></span><span class="line"><span class="cl">docker <span class="nb">exec</span> -it qinglong bash
</span></span><span class="line"><span class="cl"><span class="c1"># 安装依赖</span>
</span></span><span class="line"><span class="cl">curl -fsSL https://ghproxy.com/https://raw.githubusercontent.com/shufflewzc/QLDependency/main/Shell/QLOneKeyDependency.sh <span class="p">|</span> sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>漫长的等待，完成即可。</p>
<blockquote>
<p>如果你的青龙容器不叫 <em>qinglong</em> ，请自行替换。</p>
</blockquote>
<h2 id="运行">运行</h2>
<p>此时终于大功告成了，我们将页数选择为 <strong>1000条/页</strong> 后再全选任务批量运行即可。</p>
<p><a href="/article/qinglong-jd/image-20220310165735358_hu_6dd850d67b4f09dd.webp" data-fancybox="gallery" data-src="/article/qinglong-jd/image-20220310165735358_hu_6dd850d67b4f09dd.webp" data-caption="页数">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/qinglong-jd/image-20220310165735358_hu_d4b3fbc50850cebd.webp 480w, /article/qinglong-jd/image-20220310165735358_hu_43d8b4d25b6414.webp 720w, /article/qinglong-jd/image-20220310165735358_hu_a8d3569b506aea4f.webp 960w, /article/qinglong-jd/image-20220310165735358_hu_1b6f66b11020a38e.webp 1440w, /article/qinglong-jd/image-20220310165735358_hu_6dd850d67b4f09dd.webp 1470w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1470"
                    height="688"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/qinglong-jd/image-20220310165735358_hu_43d8b4d25b6414.webp"
                    srcset="/article/qinglong-jd/image-20220310165735358_hu_d4b3fbc50850cebd.webp 480w, /article/qinglong-jd/image-20220310165735358_hu_43d8b4d25b6414.webp 720w, /article/qinglong-jd/image-20220310165735358_hu_a8d3569b506aea4f.webp 960w, /article/qinglong-jd/image-20220310165735358_hu_1b6f66b11020a38e.webp 1440w, /article/qinglong-jd/image-20220310165735358_hu_6dd850d67b4f09dd.webp 1470w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="页数"
                    
                />
            </picture>
        </a></p>
<p>以后任务会自动定时运行，就不用再管它了。</p>
<h2 id="感谢">感谢</h2>
<p><a href="https://github.com/whyour/qinglong" target="_blank" rel="noopener">青龙面板开源项目</a></p>
<p><a href="">各位仓库作者</a></p>
<h2 id="更新">更新</h2>
<p>更新一个傻瓜式一键脚本，适合小白或者不想折腾的用户：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">wget -q https://raw.githubusercontents.com/shufflewzc/VIP/main/Scripts/sh/ql.sh -O ql.sh <span class="o">&amp;&amp;</span> bash ql.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>需要预先安装<strong>wget</strong>，centos用户直接 <strong>yum install wget</strong> 即可，其他系统自行百度。</p>
<h2 id="更新1">更新1</h2>
<p>务必先下载好 <strong>京东</strong>、<strong>京喜</strong>、<strong>京东极速版</strong> 三个app并开启以下活动（有些需要选择种植或者生产的物品自行选择即可，千万不要空着，否则相当于活动未开），以防脚本无法运行未开启的活动，导致收益降低。</p>
<blockquote>
<p>京东必开活动：东东农场、东东萌宠、宠汪汪、种豆得豆；</p>
<p>京喜必开活动：京喜财富岛、京喜牧场、京喜工厂；</p>
<p>京东极速版必开活动：汪汪乐园、注意需要绑定微信号（部分脚本会自动提现至微信）。</p>
</blockquote>
<h2 id="更新2">更新2</h2>
<p>2022/06/02 更新最新版本多账号配置方式。</p>
<h2 id="更新3">更新3</h2>
<p>2022/06/12 更新获取京东cookie的网址。</p>
]]></content:encoded>
    </item>
    <item>
      <title>自用iOS越狱插件以及源备份</title>
      <link>https://vccv.cc/article/jailbreak-plugin-backup.html</link>
      <pubDate>Mon, 28 Feb 2022 11:16:02 +0000</pubDate>
      <guid>https://vccv.cc/article/jailbreak-plugin-backup.html</guid>
      <description>个人越狱自用插件以及越狱源备份目录，以备不时之需。顺便推荐一些良心的作者。</description>
      <content:encoded><![CDATA[<blockquote>
<p>机型：12mini</p>
<p>系统：iOS 14.2.1</p>
<p>软件：unc0ver</p>
<p>商店：cydia + zebra</p>
</blockquote>
<h2 id="源">源</h2>
<ul>
<li>
<p><a href="https://repo.cydiabc.top/" target="_blank" rel="noopener">小苹果</a></p>
</li>
<li>
<p><a href="https://havoc.app/" target="_blank" rel="noopener">Havoc</a></p>
</li>
<li>
<p><a href="https://opa334.github.io/" target="_blank" rel="noopener">opa334</a></p>
</li>
<li>
<p><a href="https://creaturecoding.com/repo/" target="_blank" rel="noopener">Shuffle 官方</a></p>
</li>
<li>
<p><a href="http://tigisoftware.com/cydia/" target="_blank" rel="noopener">Filza 官方</a></p>
</li>
<li>
<p><a href="http://cokepokes.github.io/" target="_blank" rel="noopener">AppStore++ 官方</a></p>
</li>
<li>
<p><a href="http://ib-soft.net/cydia/" target="_blank" rel="noopener">iCleaner Pro 官方</a></p>
</li>
<li>
<p><a href="https://lenglengyu.com/" target="_blank" rel="noopener">冷冷雨</a></p>
</li>
<li>
<p><a href="http://repo.niceios.com/" target="_blank" rel="noopener">NiceiOS</a></p>
</li>
<li>
<p><a href="http://repo.qqtlr.com/" target="_blank" rel="noopener">Hi客 汉化</a></p>
</li>
<li>
<p><a href="https://miro92.com/repo/" target="_blank" rel="noopener">MiRO92</a></p>
</li>
<li>
<p><a href="http://apt.thebigboss.org/repofiles/cydia/" target="_blank" rel="noopener">大老板</a></p>
</li>
<li>
<p><a href="https://repo.co.kr/" target="_blank" rel="noopener">A-Bypass 官方</a></p>
</li>
<li>
<p><a href="https://lzsxcl.github.io/repo/" target="_blank" rel="noopener">h2 官方</a></p>
</li>
<li>
<p><a href="https://repo.chariz.com/" target="_blank" rel="noopener">Chariz</a></p>
</li>
<li>
<p><a href="http://limneos.net/repo/" target="_blank" rel="noopener">BioProtect XS 官方</a></p>
</li>
<li>
<p><a href="https://udevsharold.github.io/repo/" target="_blank" rel="noopener">Bakgrunnur 官方</a></p>
</li>
<li>
<p><a href="https://sharman79.github.io/Netskao/" target="_blank" rel="noopener">Netskao 备份</a></p>
<blockquote>
<p>2022.04 更新：</p>
<p><a href="https://repo.initnil.com/" target="_blank" rel="noopener">Netskao官方源</a>已经重新开放。</p>
</blockquote>
</li>
</ul>
<blockquote>
<p>一些自带的源以及一些开发方面的源就没有罗列。</p>
</blockquote>
<h2 id="插件">插件</h2>
<h3 id="付费插件">付费插件</h3>
<blockquote>
<p>付费插件在自己力所能及的情况下还是建议付费支持一下作者，感谢他们的付出。由于是外区付费插件居多，可以注册PayPal绑定国内卡使用。</p>
</blockquote>
<ul>
<li>App Hider：隐藏应用</li>
<li>iCleaner Pro：清理垃圾，排除插件故障</li>
<li>Filza：强大的文件管理器，直接安装deb以及ipa</li>
<li>Fake GPS Pro：虚拟定位，模拟Wi-Fi</li>
<li>h2：一个综合性插件</li>
<li>Snapper2 + Snapper2 CC Toggle：截图插件，功能强大</li>
<li>NiceCaller：系统通话增强，常用窗口电话</li>
<li>Crane：另类多开插件</li>
<li>CopyLog：剪切板管理增强</li>
<li>Flex 3：系统增强神器</li>
<li>InstaLauncher 2：侧滑打开软件</li>
<li>Aemulo：nfc增强，模拟非加密卡添加至钱包</li>
<li>冷冷雨源的一些付费插件</li>
</ul>
<h3 id="免费插件">免费插件</h3>
<ul>
<li>AppSync Unified：关闭系统签名验证，安装ipa</li>
<li>QQ净化：QQ增强</li>
<li>微信净化：微信开启Callkit等</li>
<li>PerfectGrabber：游戏模式下拉显示电量时间</li>
<li>PullClearNC：下拉清除全部通知</li>
<li>哥哥源（Netskao）里其他很多的软件优化插件</li>
<li>Shuffle：设置插件归类</li>
<li>StoreSwitcher 2：App Store快捷切换账号</li>
<li>AppStore++：App Store增强，主要下载旧版本</li>
<li>VideoAdsSpeed：适用于不能屏蔽广告而变相加速跳过</li>
<li>Choicy，A-Bypass，Shadow：屏蔽越狱</li>
<li>Eyeplugs：通知屏蔽，类似于安卓系统游戏模式中的消息免打扰</li>
<li>Safari Plus：自带浏览器增强</li>
<li>Tranzlo：翻译插件，免费且功能强大</li>
<li>CrackTool4：破解一部分付费插件</li>
<li>CyDown：cydia增强以及付费插件破解</li>
<li>Shortmoji 2：原生输入法增强</li>
</ul>
<h2 id="2023101-更新">2023.10.1 更新</h2>
<p><del>插件列表还会一直更新，我使用到的优质插件都会不时更新上传。</del></p>
<p>目前主力机在Android，iOS系统没有使用了，以后可能也不会更新了。</p>
<p>（越狱也是越来越难了，iOS14.3以后的版本越狱都不太稳定，macOS黑苹果也快要绝迹，这个时代可能就快要终结了吧）</p>
]]></content:encoded>
    </item>
    <item>
      <title>Cactus使用上Fancybox图片放大</title>
      <link>https://vccv.cc/article/fancybox-cactus.html</link>
      <pubDate>Sun, 20 Feb 2022 15:24:12 +0000</pubDate>
      <guid>https://vccv.cc/article/fancybox-cactus.html</guid>
      <description>将fancybox安装到hexo主题cactus上的一些经验，供大家参考。fancybox可以解决cactus主题图片不能放大的问题，感谢fancyapps做出的贡献。</description>
      <content:encoded><![CDATA[<h2 id="起因">起因</h2>
<p>本博客主题cactus没有图片放大功能，在看教程图片时往往会出现文字太小而看不清楚的状况。经搜索，发现 <strong>fancybox</strong> 这一插件，效果良好。</p>
<h2 id="安装">安装</h2>
<p>下图为fancyapps的官网，可以看到除了fancybox还有其他的Javascript UI库。</p>
<p><a href="/article/fancybox-cactus/image-20220220160055554_hu_5d25dfb7b973f5ae.webp" data-fancybox="gallery" data-src="/article/fancybox-cactus/image-20220220160055554_hu_5d25dfb7b973f5ae.webp" data-caption="fancyapps官网">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/fancybox-cactus/image-20220220160055554_hu_6c6ecba71d7111b.webp 480w, /article/fancybox-cactus/image-20220220160055554_hu_70fe02693bddef39.webp 720w, /article/fancybox-cactus/image-20220220160055554_hu_c1c80007e98c2141.webp 960w, /article/fancybox-cactus/image-20220220160055554_hu_3e9192a60ae72d62.webp 1440w, /article/fancybox-cactus/image-20220220160055554_hu_5d25dfb7b973f5ae.webp 1920w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1920"
                    height="864"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/fancybox-cactus/image-20220220160055554_hu_70fe02693bddef39.webp"
                    srcset="/article/fancybox-cactus/image-20220220160055554_hu_6c6ecba71d7111b.webp 480w, /article/fancybox-cactus/image-20220220160055554_hu_70fe02693bddef39.webp 720w, /article/fancybox-cactus/image-20220220160055554_hu_c1c80007e98c2141.webp 960w, /article/fancybox-cactus/image-20220220160055554_hu_3e9192a60ae72d62.webp 1440w, /article/fancybox-cactus/image-20220220160055554_hu_5d25dfb7b973f5ae.webp 1920w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="fancyapps官网"
                    
                />
            </picture>
        </a></p>
<h3 id="引入文件">引入文件</h3>
<p>点击进入<a href="https://fancyapps.com/docs/ui/installation" target="_blank" rel="noopener">fancybox的文档</a>，在 <strong>Installation</strong> 部分看到我们可以通过npm安装以及直接CDN引入等方式。由于是博客网站，我直接选择CDN引入。</p>
<blockquote>
<p>You can also use standalone UMD build by downloading the files or using directly from the CDN on your page:</p>
<ul>
<li><a href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js" target="_blank" rel="noopener">https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js</a></li>
<li><a href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.css" target="_blank" rel="noopener">https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.css</a></li>
</ul>
</blockquote>
<p>在 <strong>hexo文件夹/themes/cactus/layout/_partial/head.ejs</strong> 文件中，我们在head标签的最后添加代码引入css文件：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="o">&lt;%</span> <span class="k">if</span> <span class="p">(</span><span class="nx">theme</span><span class="p">.</span><span class="nx">fancybox</span><span class="p">.</span><span class="nx">enabled</span><span class="p">)</span> <span class="p">{</span><span class="o">%&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="o">&lt;</span><span class="nx">link</span> <span class="nx">rel</span><span class="o">=</span><span class="s2">&#34;stylesheet&#34;</span> <span class="nx">href</span><span class="o">=</span><span class="s2">&#34;https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.css&#34;</span> <span class="o">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;%</span> <span class="p">}</span> <span class="o">%&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在同级目录下的 <strong>scripts.ejs</strong> 文件中，我们直接在最后一行添加代码引入js文件：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="c">&lt;!--</span> <span class="nx">FancyBox</span> <span class="o">--&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;%</span> <span class="k">if</span> <span class="p">(</span><span class="nx">theme</span><span class="p">.</span><span class="nx">fancybox</span><span class="p">.</span><span class="nx">enabled</span><span class="p">)</span> <span class="p">{</span><span class="o">%&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="nx">script</span> <span class="nx">src</span><span class="o">=</span><span class="s2">&#34;https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js&#34;</span><span class="o">&gt;&lt;</span><span class="err">/script&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;%</span> <span class="p">}</span> <span class="o">%&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>可以发现我添加了条件判断，所以要在 <strong>主题的_config.yml</strong> 文件中添加：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Enable FancyBox</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">fancybox</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>至于是否直接引入，全凭大家喜欢。</p>
<h3 id="修改配置">修改配置</h3>
<p>继续看官方文档可以发现，我们只需要简单的在img标签 <strong>&lt;img</strong> 外套上一层a标签 <strong>&lt;a</strong> ，加上标签属性 <strong>data-fancybox</strong> <strong>data-src</strong> <strong>data-caption</strong> ，即可实现功能。</p>
<p>刚开始我打算直接引入js脚本修改，但是发现毫无作用。后来想想，或许hexo将markdown渲染成html的时刻在外部js脚本生效之后？我也没去深究缘由，如果有大佬懂这些，欢迎评论指点！</p>
<p>所以我决定试试能不能直接从渲染器下手。搜索得知，hexo默认渲染器是 <strong>hexo-renderer-marked</strong> ，在 <strong>hexo文件夹/node_modules/hexo-renderer-marked/lib/renderer.js</strong> 文件中，搜索关键词 <strong>img</strong> 找到相关代码修改如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="c1">// 原代码
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">out</span> <span class="o">=</span> <span class="sb">`&lt;img src=&#34;</span><span class="si">${</span><span class="nx">encodeURL</span><span class="p">(</span><span class="nx">href</span><span class="p">)</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="sb">` alt=&#34;</span><span class="si">${</span><span class="nx">text</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">title</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="sb">` title=&#34;</span><span class="si">${</span><span class="nx">title</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">lazyload</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s1">&#39; loading=&#34;lazy&#34;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">out</span> <span class="o">+=</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// 修改后
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">out</span> <span class="o">=</span> <span class="sb">`&lt;a data-fancybox=&#34;gallery&#34; data-src=&#34;</span><span class="si">${</span><span class="nx">href</span><span class="si">}</span><span class="sb">&#34; data-caption=&#34;</span><span class="si">${</span><span class="nx">text</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;img src=&#34;</span><span class="si">${</span><span class="nx">encodeURL</span><span class="p">(</span><span class="nx">href</span><span class="p">)</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="sb">` alt=&#34;</span><span class="si">${</span><span class="nx">text</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">title</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="sb">` title=&#34;</span><span class="si">${</span><span class="nx">title</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">lazyload</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s1">&#39; loading=&#34;lazy&#34;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">out</span> <span class="o">+=</span> <span class="s1">&#39;&gt;&lt;/a&gt;&#39;</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="验证收尾">验证收尾</h3>
<p>执行 <strong>hexo clean &amp;&amp; hexo s</strong> 预览后发现显示正常，功能也有，问题解决了。</p>
<h2 id="效果">效果</h2>
<p>来张图片看看效果。</p>
<p><a href="/article/fancybox-cactus/image-20220220172801964_hu_332dc068081152a2.webp" data-fancybox="gallery" data-src="/article/fancybox-cactus/image-20220220172801964_hu_332dc068081152a2.webp" data-caption="最终成果">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/fancybox-cactus/image-20220220172801964_hu_befd40fb05313a7b.webp 480w, /article/fancybox-cactus/image-20220220172801964_hu_96736498f411a2cf.webp 720w, /article/fancybox-cactus/image-20220220172801964_hu_ea781079473b1623.webp 960w, /article/fancybox-cactus/image-20220220172801964_hu_5f733f016d1dc7e4.webp 1440w, /article/fancybox-cactus/image-20220220172801964_hu_332dc068081152a2.webp 1909w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1909"
                    height="865"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/fancybox-cactus/image-20220220172801964_hu_96736498f411a2cf.webp"
                    srcset="/article/fancybox-cactus/image-20220220172801964_hu_befd40fb05313a7b.webp 480w, /article/fancybox-cactus/image-20220220172801964_hu_96736498f411a2cf.webp 720w, /article/fancybox-cactus/image-20220220172801964_hu_ea781079473b1623.webp 960w, /article/fancybox-cactus/image-20220220172801964_hu_5f733f016d1dc7e4.webp 1440w, /article/fancybox-cactus/image-20220220172801964_hu_332dc068081152a2.webp 1909w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="最终成果"
                    
                />
            </picture>
        </a></p>
<p>真不错，满足了哈哈哈。</p>
<h2 id="感谢">感谢</h2>
<p><a href="https://fancyapps.com/docs/ui/fancybox/" target="_blank" rel="noopener">Fancybox</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>JetBrains全家桶激活教程2022</title>
      <link>https://vccv.cc/article/jetbrains-activate.html</link>
      <pubDate>Thu, 06 Jan 2022 14:12:54 +0000</pubDate>
      <guid>https://vccv.cc/article/jetbrains-activate.html</guid>
      <description>该激活方法对JetBrains全家桶都有效，其中包括IDEA、PyCharm、GoLand、WebStorm等，仅供个人学习使用参考！如果以前安装过旧版本，建议卸载重装，全新开始。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<blockquote>
<p>对 JetBrains 全家桶有效，包括 IDEA、PyCharm、GoLand、WebStorm 等。</p>
<p><strong>仅供个人学习使用参考</strong>！</p>
</blockquote>
<p>在教程之前，如果安装过旧版本，建议<strong>卸载重装</strong>，全新开始。</p>
<table>
  <thead>
      <tr>
          <th>IDE</th>
          <th>官网地址</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>IDEA</td>
          <td><a href="https://www.jetbrains.com/idea/download/other.html" target="_blank" rel="noopener">https://www.jetbrains.com/idea/download/other.html</a></td>
      </tr>
      <tr>
          <td>PyCharm</td>
          <td><a href="https://www.jetbrains.com/pycharm/download/other.html" target="_blank" rel="noopener">https://www.jetbrains.com/pycharm/download/other.html</a></td>
      </tr>
      <tr>
          <td>GoLand</td>
          <td><a href="https://www.jetbrains.com/go/download/other.html" target="_blank" rel="noopener">https://www.jetbrains.com/go/download/other.html</a></td>
      </tr>
      <tr>
          <td>WebStorm</td>
          <td><a href="https://www.jetbrains.com/webstorm/download/other.html" target="_blank" rel="noopener">https://www.jetbrains.com/webstorm/download/other.html</a></td>
      </tr>
  </tbody>
</table>
<h2 id="更新3">更新3</h2>
<p>无论是哪个软件，都建议使用2021.3版本的最新版本。经过实测，该版本操作最简单，最稳定。</p>
<p>激活好后请在设置里面关闭自动检查更新（关键词：update）。</p>
<h2 id="202123版本及以后">2021.2.3版本及以后</h2>
<blockquote>
<p>截止2022年1月6日，Mac最新版本为2021.3.1。</p>
</blockquote>
<p>从 2021.2.3 版本开始，Jetbrains试用策略更新：强制登录账号，试用期与账号绑定。这时候我们通过网络拦截的方式来实现激活。</p>
<h3 id="mac版">Mac版</h3>
<p>因为本人使用的是Mac版本，所以教程会相对详细许多。</p>
<ol>
<li>
<p>全新下载你需要的IDE，如果安装过无限试用、修改过hosts，请先<strong>卸载干净旧版本再安装</strong>，否需无法激活。</p>
<p>下面以PyCharm为例。</p>
</li>
<li>
<p>安装好后先打开，到激活页面，<strong>不要关闭</strong>，再进行下列步骤。</p>
</li>
<li>
<p>下载 <a href="https://yuesir.lanzouo.com/ig1O9yg1uxe" target="_blank" rel="noopener">ja-netfilter.zip</a> ，解压到你能找到的位置。</p>
<blockquote>
<p>2022.04.17 更新：</p>
<p>适用于最新2022.1版本的 <a href="https://yuesir.lanzoum.com/iNlyJ03cykid" target="_blank" rel="noopener">ja-netfilter.zip</a> 。</p>
</blockquote>
</li>
<li>
<p>打开访达，点击左侧的 <strong>应用程序</strong> 找到 <strong>PyCharm</strong> ，在 <strong>PyCharm</strong> 图标上右键，点击 <strong>显示包内容</strong> 。</p>
</li>
<li>
<p>进入 <strong>Contents/bin</strong> 目录，使用文本编辑器打开 <strong>pycharm.vmoptions</strong> 文件。</p>
<blockquote>
<p>推荐下载使用 <strong>Sublime Text</strong> 进行编辑。</p>
</blockquote>
</li>
<li>
<p>在最后面添加 <code>-javaagent:/绝对路径/ja-netfilter.jar</code> ，记得修改成自己的 <strong>绝对路径</strong> ，保存文件。</p>
</li>
<li>
<p>退出PyCharm，快捷键 <strong>Command + Q</strong> 。</p>
</li>
<li>
<p>重新打开，选择 <strong>Activate PyCharm</strong> ，再点击 <strong>Activation Code</strong> 。</p>
<blockquote>
<p>2022.04.17 更新：</p>
<p>这里可以选择另一种激活方式，更加简单：</p>
<p><a href="/article/jetbrains-activate/image-20220417181002264_hu_4813fca1bca94c43.webp" data-fancybox="gallery" data-src="/article/jetbrains-activate/image-20220417181002264_hu_4813fca1bca94c43.webp" data-caption="许可证服务器激活方式">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/jetbrains-activate/image-20220417181002264_hu_8c0dfc348fc4301a.webp 480w, /article/jetbrains-activate/image-20220417181002264_hu_82c115f112b70435.webp 720w, /article/jetbrains-activate/image-20220417181002264_hu_c5491ebaf2cf597b.webp 960w, /article/jetbrains-activate/image-20220417181002264_hu_4813fca1bca94c43.webp 1098w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1098"
                    height="398"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/jetbrains-activate/image-20220417181002264_hu_82c115f112b70435.webp"
                    srcset="/article/jetbrains-activate/image-20220417181002264_hu_8c0dfc348fc4301a.webp 480w, /article/jetbrains-activate/image-20220417181002264_hu_82c115f112b70435.webp 720w, /article/jetbrains-activate/image-20220417181002264_hu_c5491ebaf2cf597b.webp 960w, /article/jetbrains-activate/image-20220417181002264_hu_4813fca1bca94c43.webp 1098w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="许可证服务器激活方式"
                    
                />
            </picture>
        </a></p>
<p>选择 <em><strong>License Server</strong></em> 方式（许可证服务器），输入服务器地址：<em><strong><a href="https://jetbra.in" target="_blank" rel="noopener">https://jetbra.in</a></strong></em> ，然后激活即可。</p>
</blockquote>
</li>
<li>
<p>复制下面的激活码粘贴到激活窗口的输入框中，点击 <strong>Activate</strong> 。Over！</p>
</li>
<li>
<p>其他：如果你没有试用过JetBrains的产品，则无需使用下列激活码，只需要在 <strong>步骤2</strong> 打开IDE时选择注册账号试用即可，后续步骤不变。</p>
</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">IFB45W18MX-eyJsaWNlbnNlSWQiOiJJRkI0NVcxOE1YIiwibGljZW5zZWVOYW1lIjoi5rC45LmF5r+A5rS7IHd3d8K3YWppaHVvwrdjb20iLCJhc3NpZ25lZU5hbWUiOiIiLCJhc3NpZ25lZUVtYWlsIjoiIiwibGljZW5zZVJlc3RyaWN0aW9uIjoiIiwiY2hlY2tDb25jdXJyZW50VXNlIjpmYWxzZSwicHJvZHVjdHMiOlt7ImNvZGUiOiJEUE4iLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRCIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQUyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiSUkiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJTQyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJHTyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiRE0iLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJTRiIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJEUyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiV1MiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJEIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSUzAiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJNIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJBQyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNWIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IkRDIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSU1UiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRQIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBEQiIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQV1MiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFNJIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBQUyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQQ1dNUCIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQR08iLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFBDIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBSQiIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQU1ciLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUlMiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6dHJ1ZX1dLCJtZXRhZGF0YSI6IjAxMjAyMjAxMDVQUEFNMDAwMDA1IiwiaGFzaCI6IjI5NjkzNjI3LzA6LTIwNjkyMjgzNDciLCJncmFjZVBlcmlvZERheXMiOjcsImF1dG9Qcm9sb25nYXRlZCI6ZmFsc2UsImlzQXV0b1Byb2xvbmdhdGVkIjpmYWxzZX0=-MEkjEOAC1dEQpMqlge5gs64YYPdP1gNn0miz12/3xTQQ+bk8qMymnwKk/rCNNH8xe3DLneF+YMm0Orvz6QTTW12KeQ1uOPoOnBjDFvsjoT4NtzhXgVDYJ0lQlTapJFPTCyqfuir1RHw08SLPjAxFrQROVkR315E3oHCdmz8ZEB/sahLK081cgxrqFznXtLrSi17ZaCDvbO/0dhChY1dur6SnjOMTShytrRKc4w6/wn1lbfncBVL7pPMwzSOAgA5NPToC3uxDzEJh3Hhpip8okaa28dohFherPzHR9/jT2yh3Gyh2NraqoNtQTFoPwxkOYahKEw06jWrISRA1mH57tw==-MIIETDCCAjSgAwIBAgIBDTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTIwMTAxOTA5MDU1M1oXDTIyMTAyMTA5MDU1M1owHzEdMBsGA1UEAwwUcHJvZDJ5LWZyb20tMjAyMDEwMTkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCP4uk4SlVdA5nuA3DQC+NsEnZS9npFnO0zrmMWcz1++q2UWJNuGTh0rwi+3fUJIArfvVh7gNtIp93rxjtrQAuf4/Fa6sySp4c32MeFACfC0q+oUoWebhOIaYTYUxm4LAZ355vzt8YeDPmvWKxA81udqEk4gU9NNAOz1Um5/8LyR8SGsSc4EDBRSjcMWMwMkYSauGqGcEUK8WhfplsyF61lKSOFA6VmfUmeDK15rUWWLbOMKgn2cxFA98A+s74T9Oo96CU7rp/umDXvhnyhAXSukw/qCGOVhwKR8B6aeDtoBWQgjnvMtPgOUPRTPkPGbwPwwDkvAHYiuKJ7Bd2wH7rAgMBAAGjgZkwgZYwCQYDVR0TBAIwADAdBgNVHQ4EFgQUJNoRIpb1hUHAk0foMSNM9MCEAv8wSAYDVR0jBEEwP4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0GCCQDSbLGDsoN54TATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBAB2J1ysRudbkqmkUFK8xqhiZaYPd30TlmCmSAaGJ0eBpvkVeqA2jGYhAQRqFiAlFC63JKvWvRZO1iRuWCEfUMkdqQ9VQPXziE/BlsOIgrL6RlJfuFcEZ8TK3syIfIGQZNCxYhLLUuet2HE6LJYPQ5c0jH4kDooRpcVZ4rBxNwddpctUO2te9UU5/FjhioZQsPvd92qOTsV+8Cyl2fvNhNKD1Uu9ff5AkVIQn4JU23ozdB/R5oUlebwaTE6WZNBs+TA/qPj+5/wi9NH71WRB0hqUoLI2AKKyiPw++FtN4Su1vsdDlrAzDj9ILjpjJKA1ImuVcG329/WTYIKysZ1CWK3zATg9BeCUPAV1pQy8ToXOq+RSYen6winZ2OO93eyHv2Iw5kbn1dqfBw1BuTE29V2FJKicJSu8iEOpfoafwJISXmz1wnnWL3V/0NxTulfWsXugOoLfv0ZIBP1xH9kmf22jjQ2JiHhQZP7ZDsreRrOeIQ/c4yR8IQvMLfC0WKQqrHu5ZzXTH4NO3CwGWSlTY74kE91zXB5mwWAx1jig+UXYc2w4RkVhy0//lOmVya/PEepuuTTI4+UJwC7qbVlh5zfhj8oTNUXgN0AOc+Q0/WFPl1aw5VV/VrO8FCoB15lFVlpKaQ1Yh+DVU8ke+rt9Th0BCHXe0uZOEmH0nOnH/0onD
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="windows版">Windows版</h3>
<p><del><strong>第四步</strong>与Mac版不同，其他类似：</del></p>
<ul>
<li><del>接下来找到 IDE 安装目录下的 <strong>vmoptions</strong> 文件。不管你用的是 **IDEA **、<strong>WebStorm</strong> 、<strong>PyCharm</strong> 还是其它的，文件名都叫 <strong>xxxxx.vmoptions</strong> 。</del></li>
</ul>
<ol>
<li>
<p>执行Mac下教程1-2步。</p>
</li>
<li>
<p>清空以前使用过的任何激活方式。</p>
</li>
<li>
<p>下载 <a href="https://yuesir.lanzouo.com/iGxtCzqu98d" target="_blank" rel="noopener">激活脚本</a> 并解压。</p>
<ul>
<li>
<p><strong>scripts</strong>：放置了相关脚本，包含自动安装、卸载破解补丁脚本（包含有Windows、Mac、Linux 对应系统的脚本）。</p>
<blockquote>
<p>针对找不到 <strong>idea.vmoptions</strong> 文件的问题，这次通过运行脚本可以直接引入补丁，方便了很多。</p>
</blockquote>
</li>
<li>
<p><strong>vmoptions</strong>：放置了 JetBrains 产品的 <strong>xxx.vmoptions</strong> 配置文件。2021.3.2新版本我们可以直接引用这个文件夹下的 <strong>xxx.vmoptions</strong> 配置文件。</p>
</li>
</ul>
</li>
<li>
<p>点击运行 <strong>install-current-user.vbs</strong> 脚本，为当前用户安装破解补丁。</p>
<blockquote>
<p><strong>install-all-users.vbs</strong> 为所有用户安装，不推荐；</p>
<p><strong>unistall-</strong>* 前缀的是卸载补丁脚本。</p>
</blockquote>
</li>
<li>
<p>如果弹出提示，请点击确定，等待几秒钟即可。</p>
</li>
<li>
<p>执行Mac版教程7-10步。</p>
<blockquote>
<p>激活成功后，补丁文件夹不能移动或者删除掉，因为这样脚本就找不到对应文件了，激活也就失效了。所以放着吃灰就行，千万别动它。</p>
</blockquote>
</li>
</ol>
<h3 id="linux版">Linux版</h3>
<p>参考Windows版激活教程。</p>
<p>第4步点击运行 <strong>install.sh</strong> 脚本安装。</p>
<h2 id="202122版本及以前">2021.2.2版本及以前</h2>
<p>JetBrains 2021.2.2 及之前，我们可以通过无限重置试用期补丁来实现永久使用。</p>
<ol>
<li>
<p>安装插件</p>
<p>离线安装方式：</p>
<p>1.1、下载插件
<a href="https://plugins.zhile.io/files/ide-eval-resetter-2.1.6.zip" target="_blank" rel="noopener">下载地址</a>。</p>
<p>1.2、安装插件</p>
<p>直接下载插件 zip 包，直接把 zip 包拖进 IDE 的窗口来进行插件的安装。如果无法拖动安装，你可以在 <strong>Settings/Preferences&hellip; -&gt; Plugins</strong> 里手动安装插件**（Install Plugin From Disk&hellip;）** ，插件会提示安装成功。</p>
<hr>
<p>在线安装方式：</p>
<p>搜索 <strong>IDE Eval Reset</strong> 安装即可。</p>
</li>
<li>
<p>使用插件</p>
<ul>
<li>
<p>成功安装插件后，在 <strong>帮助</strong> 下会多一个 <strong>Eval Reset</strong> 按钮。一般来说，在IDE窗口切出去或切回来时（窗口失去/得到焦点）会触发事件，检测是否长时间（25 天）没有重置，给通知让你选择。（初次安装则会直接给予提示）</p>
</li>
<li>
<p>也可以手动唤出插件的主界面：</p>
<p>如果 IDE 没有打开项目，在Welcome界面点击菜单：<strong>Get Help -&gt; Eval Reset</strong> 。如果 IDE 打开了项目，点击菜单：<strong>Help -&gt; Eval Reset</strong> 。唤出的插件主界面中包含了2 个按钮，1 个勾选项：</p>
<ul>
<li>按钮：<strong>Reload</strong> 用来刷新界面上的显示信息；</li>
<li>按钮：<strong>Reset</strong> 点击会询问是否重置试用信息并重启 IDE。选择 Yes 则执行重置操作并重启 IDE 生效，选择 No 则什么也不做；</li>
<li>勾选项：<strong>Auto reset before per restart</strong> 。勾选后则每次重启/退出 IDE 时会自动重置试用信息。</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="成功截图">成功截图</h2>
<p><a href="/article/jetbrains-activate/image-20220106145338969_hu_edd18a07a6b28679.webp" data-fancybox="gallery" data-src="/article/jetbrains-activate/image-20220106145338969_hu_edd18a07a6b28679.webp" data-caption="成功截图">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/jetbrains-activate/image-20220106145338969_hu_993e5a3a53f3ebf1.webp 480w, /article/jetbrains-activate/image-20220106145338969_hu_eccf4e1ef82f8c89.webp 720w, /article/jetbrains-activate/image-20220106145338969_hu_9f46997733b7929c.webp 960w, /article/jetbrains-activate/image-20220106145338969_hu_c1505e101444bc8d.webp 1440w, /article/jetbrains-activate/image-20220106145338969_hu_edd18a07a6b28679.webp 1600w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1600"
                    height="952"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/jetbrains-activate/image-20220106145338969_hu_eccf4e1ef82f8c89.webp"
                    srcset="/article/jetbrains-activate/image-20220106145338969_hu_993e5a3a53f3ebf1.webp 480w, /article/jetbrains-activate/image-20220106145338969_hu_eccf4e1ef82f8c89.webp 720w, /article/jetbrains-activate/image-20220106145338969_hu_9f46997733b7929c.webp 960w, /article/jetbrains-activate/image-20220106145338969_hu_c1505e101444bc8d.webp 1440w, /article/jetbrains-activate/image-20220106145338969_hu_edd18a07a6b28679.webp 1600w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="成功截图"
                    
                />
            </picture>
        </a></p>
<h2 id="感谢">感谢</h2>
<p><a href="https://github.com/ja-netfilter/ja-netfilter" target="_blank" rel="noopener">GitHub作者pengzhile</a></p>
<p><a href="https://www.macwk.com/article/jetbrains-crack" target="_blank" rel="noopener">MacWk作者Pertim</a></p>
<h2 id="更新">更新</h2>
<p>经本人测试（Mac环境下），升级至最新版本 <strong>2021.3.2</strong> 后，第一个方法依旧有效，只需要<strong>重复步骤4-7</strong>，可以放心地升级。</p>
<p>Windows下官方似乎加入了反制手段，在用户目录下已经找不到这个文件了，所以这次我也更新了相应部分的教程。</p>
<p>另外。激活成功后建议不要升级新版本了，能用就行，你说呢。</p>
<h2 id="更新1">更新1</h2>
<p>2021.3.3版本更新成功。</p>
<p><a href="/article/jetbrains-activate/image-20220321174826134_hu_efa92de8610b570a.webp" data-fancybox="gallery" data-src="/article/jetbrains-activate/image-20220321174826134_hu_efa92de8610b570a.webp" data-caption="2021.3.3版本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/jetbrains-activate/image-20220321174826134_hu_7274ef00ec0eeb37.webp 480w, /article/jetbrains-activate/image-20220321174826134_hu_88a4e646906e43d2.webp 720w, /article/jetbrains-activate/image-20220321174826134_hu_2ab388fe21a934.webp 960w, /article/jetbrains-activate/image-20220321174826134_hu_efa92de8610b570a.webp 1142w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1142"
                    height="824"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/jetbrains-activate/image-20220321174826134_hu_88a4e646906e43d2.webp"
                    srcset="/article/jetbrains-activate/image-20220321174826134_hu_7274ef00ec0eeb37.webp 480w, /article/jetbrains-activate/image-20220321174826134_hu_88a4e646906e43d2.webp 720w, /article/jetbrains-activate/image-20220321174826134_hu_2ab388fe21a934.webp 960w, /article/jetbrains-activate/image-20220321174826134_hu_efa92de8610b570a.webp 1142w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="2021.3.3版本"
                    
                />
            </picture>
        </a></p>
<h2 id="更新2">更新2</h2>
<p>Mac下2022.1版本，以前的失效了，更新了文章。</p>
<p><a href="/article/jetbrains-activate/image-20220417180532192_hu_21b70f2b31f23c5a.webp" data-fancybox="gallery" data-src="/article/jetbrains-activate/image-20220417180532192_hu_21b70f2b31f23c5a.webp" data-caption="2022.1版本">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/jetbrains-activate/image-20220417180532192_hu_800fa942902bc438.webp 480w, /article/jetbrains-activate/image-20220417180532192_hu_e98ee31821d98912.webp 720w, /article/jetbrains-activate/image-20220417180532192_hu_e61e1dc769ba8c61.webp 960w, /article/jetbrains-activate/image-20220417180532192_hu_21b70f2b31f23c5a.webp 1096w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1096"
                    height="786"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/jetbrains-activate/image-20220417180532192_hu_e98ee31821d98912.webp"
                    srcset="/article/jetbrains-activate/image-20220417180532192_hu_800fa942902bc438.webp 480w, /article/jetbrains-activate/image-20220417180532192_hu_e98ee31821d98912.webp 720w, /article/jetbrains-activate/image-20220417180532192_hu_e61e1dc769ba8c61.webp 960w, /article/jetbrains-activate/image-20220417180532192_hu_21b70f2b31f23c5a.webp 1096w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="2022.1版本"
                    
                />
            </picture>
        </a></p>
]]></content:encoded>
    </item>
    <item>
      <title>iOS越狱插件PassBy定制</title>
      <link>https://vccv.cc/article/passby-fix.html</link>
      <pubDate>Sat, 01 Jan 2022 23:19:51 +0000</pubDate>
      <guid>https://vccv.cc/article/passby-fix.html</guid>
      <description>此前听闻过一些智能解锁插件，像IntelligentPass 4，以及PassBy。我发现了这类插件的“痛点”：蓝牙解锁功能是残废的。通过修改PassBy源代码，我们可以侧面解决此类问题。</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>此前听闻过一款<strong>智能解锁</strong>插件，叫做IntelligentPass 4。我找到它的官方源以2.99美元购买后发现了这类插件的“痛点”，这也是此类可以靠识别安全蓝牙设备解锁的插件的痛点：</p>
<blockquote>
<p>自从iOS7以后就无法从API直接获取蓝牙设备的MAC地址，只能用UUID来标识设备，要注意的是同一个设备在不同手机上显示的UUID并不相同，所以不能拿来做唯一标识。</p>
</blockquote>
<p>但我最需要的就是使用其中的蓝牙自动解锁功能，经过我不断尝试，该类插件是无法发现我的Amazfit手表设备的。</p>
<blockquote>
<p>顺便说个事，在发现这款插件对我并无作用后，我立马邮件联系了插件源的作者，希望得到帮助或者退款。但是！！！并没有人鸟我。我这才到Reddit上发现这个插件商店毫无信誉，毫无售后可言。各位记得避坑，我的2.99美元啊我去😭。</p>
</blockquote>
<p>此时，我又发现了开源项目 <strong><a href="https://github.com/giorgioiavicoli/PassBy.git" target="_blank" rel="noopener">PassBy</a></strong> ，我的目光便转向了它。</p>
<h2 id="解决经过">解决经过</h2>
<p>在该项目的issue上我发现也有人有此类问题：</p>
<p><a href="/article/passby-fix/image-20220114222356631_hu_3ca9883ad27c45f5.webp" data-fancybox="gallery" data-src="/article/passby-fix/image-20220114222356631_hu_3ca9883ad27c45f5.webp" data-caption="问题">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/passby-fix/image-20220114222356631_hu_f6918e820686c46a.webp 480w, /article/passby-fix/image-20220114222356631_hu_991d11ffee9bdac0.webp 720w, /article/passby-fix/image-20220114222356631_hu_f65ffe0d7d6a8ed6.webp 960w, /article/passby-fix/image-20220114222356631_hu_3ca9883ad27c45f5.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="624"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/passby-fix/image-20220114222356631_hu_991d11ffee9bdac0.webp"
                    srcset="/article/passby-fix/image-20220114222356631_hu_f6918e820686c46a.webp 480w, /article/passby-fix/image-20220114222356631_hu_991d11ffee9bdac0.webp 720w, /article/passby-fix/image-20220114222356631_hu_f65ffe0d7d6a8ed6.webp 960w, /article/passby-fix/image-20220114222356631_hu_3ca9883ad27c45f5.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="问题"
                    
                />
            </picture>
        </a></p>
<p>所幸PassBy为开源插件，同时我在刚才那个issue下看到有人评论提到了一些见解：</p>
<p><a href="/article/passby-fix/image-20220114222622805_hu_562fe41fa07d40d2.webp" data-fancybox="gallery" data-src="/article/passby-fix/image-20220114222622805_hu_562fe41fa07d40d2.webp" data-caption="评论">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/passby-fix/image-20220114222622805_hu_62ce23611d1ea808.webp 480w, /article/passby-fix/image-20220114222622805_hu_a609b63d68d8eb7d.webp 720w, /article/passby-fix/image-20220114222622805_hu_65d24a05875338.webp 960w, /article/passby-fix/image-20220114222622805_hu_562fe41fa07d40d2.webp 1030w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1030"
                    height="546"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/passby-fix/image-20220114222622805_hu_a609b63d68d8eb7d.webp"
                    srcset="/article/passby-fix/image-20220114222622805_hu_62ce23611d1ea808.webp 480w, /article/passby-fix/image-20220114222622805_hu_a609b63d68d8eb7d.webp 720w, /article/passby-fix/image-20220114222622805_hu_65d24a05875338.webp 960w, /article/passby-fix/image-20220114222622805_hu_562fe41fa07d40d2.webp 1030w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="评论"
                    
                />
            </picture>
        </a></p>
<p>他说使用的 <strong>BluetoothManager</strong> 头来获取蓝牙设备，我们是否可以通过创建一个没有 <strong>if(name)</strong> 的版本。</p>
<p>自此，我觉得可以自己修改源代码，将自己需要的设备名称加在判断里面。它不能获取到我的设备，我就自己加上，想想应该还可以😂。</p>
<h3 id="搭建环境">搭建环境</h3>
<p>将源代码克隆到本地后，我发现它是通过 <strong>theos</strong> 构建的，所以第一步我必须将其环境搭建好，能够正常编译出插件本体。theos的 <a href="https://theos.dev/docs/" target="_blank" rel="noopener">官方文档</a> 很详细，我是Mac系统，所以便按照其关于Mac系统的介绍方法来安装：</p>
<p><a href="https://theos.dev/docs/installation-macos" target="_blank" rel="noopener">Installation instructions for macOS</a>。</p>
<h3 id="克隆">克隆</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/giorgioiavicoli/PassBy.git
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="编译">编译</h3>
<p>搭建好后我便第一时间进行了编译尝试，结果发现PassBy需要的 <strong>iOS SDK</strong> 版本是13.3，但我在theos官方提供的SDK中并无发现。还好Google搜到<a href="https://github.com/SniperGER/iOS13-Private-SDK" target="_blank" rel="noopener">SniperGER提供的iOS13.3版本SDK</a>。</p>
<blockquote>
<p>Copy the SDK folder(s) in sdks to $THEOS/sdks and the folder(s) in include to $THEOS/include.</p>
</blockquote>
<p>代码参考如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">git clone https://github.com/SniperGER/iOS13-Private-SDK.git
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> iOS13-Private-SDK
</span></span><span class="line"><span class="cl">unzip sdks/iPhoneOS13.3.sdk.zip
</span></span><span class="line"><span class="cl"><span class="c1"># 如果提示找不到$THEOS</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 请重启终端或者source一下</span>
</span></span><span class="line"><span class="cl">mv iPhoneOS13.3.sdk <span class="nv">$THEOS</span>/sdks
</span></span><span class="line"><span class="cl">mv include/* <span class="nv">$THEOS</span>/include
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="修改源代码">修改源代码</h3>
<p>打开 <strong>Tweak.xm</strong> 文件（我用的Sublime Text），通过搜索关键词 <strong>bluetooth</strong> 发现控制蓝牙这块功能的主函数 <strong>isUsingBT</strong> ，原代码如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">BOOL</span> <span class="nf">isUsingBT</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">useGracePeriodOnBT</span> <span class="o">&amp;&amp;</span> <span class="n">allowedBTs</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">NSArray</span> <span class="o">*</span> <span class="n">connectedDevices</span> <span class="o">=</span> <span class="p">[[</span><span class="n">BluetoothManager</span> <span class="n">sharedInstance</span><span class="p">]</span> <span class="n">connectedDevices</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="n">BluetoothDevice</span> <span class="o">*</span> <span class="n">bluetoothDevice</span> <span class="k">in</span> <span class="n">connectedDevices</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">NSString</span> <span class="o">*</span> <span class="n">deviceName</span> <span class="o">=</span> <span class="p">[</span><span class="n">bluetoothDevice</span> <span class="n">name</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">deviceName</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">deviceName</span> <span class="n">length</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="n">deviceName</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">NO</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>因为我对 <strong>objective-c</strong> 语言不熟悉，并没有去系统学习过，所以只有靠学过的C语言的一点点底子看了一下，发现确实如上面所说，用的 <strong>BluetoothManager</strong> 头文件，其中最主要的逻辑如下：</p>
<p><a href="/article/passby-fix/image-20240821133721171_hu_9a0fb14596004858.webp" data-fancybox="gallery" data-src="/article/passby-fix/image-20240821133721171_hu_9a0fb14596004858.webp" data-caption="代码位置在第500行">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/passby-fix/image-20240821133721171_hu_12828dc8274ce3e2.webp 480w, /article/passby-fix/image-20240821133721171_hu_481cea8b82e85886.webp 720w, /article/passby-fix/image-20240821133721171_hu_8531fbad07ba170.webp 960w, /article/passby-fix/image-20240821133721171_hu_b7d93d9783929997.webp 1440w, /article/passby-fix/image-20240821133721171_hu_9a0fb14596004858.webp 1616w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1616"
                    height="456"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/passby-fix/image-20240821133721171_hu_481cea8b82e85886.webp"
                    srcset="/article/passby-fix/image-20240821133721171_hu_12828dc8274ce3e2.webp 480w, /article/passby-fix/image-20240821133721171_hu_481cea8b82e85886.webp 720w, /article/passby-fix/image-20240821133721171_hu_8531fbad07ba170.webp 960w, /article/passby-fix/image-20240821133721171_hu_b7d93d9783929997.webp 1440w, /article/passby-fix/image-20240821133721171_hu_9a0fb14596004858.webp 1616w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="代码位置在第500行"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">deviceName</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">deviceName</span> <span class="n">length</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="n">deviceName</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>它将你允许的安全蓝牙设备名字 <strong>deviceName</strong> 存到 <strong>allowedBTs</strong> 中，我还发现它将 <strong>devicename</strong> 的 <strong>sha1</strong> 值这个数据最终存到了 <strong>passbybt.plist</strong> 文件中：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="cp">#define BT_PLIST_PATH   &#34;/var/mobile/Library/Preferences/com.giorgioiavicoli.passbybt.plist&#34;
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>于是我修改 <strong>isUsingBT()</strong> 函数如下，也就是多添加了一个条件判断if在上面判断语句的后面：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">([</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="s">@&#34;Amazfit GTS 2&#34;</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>修改后的该函数整体代码如下所示，请参照正确的位置进行修改：</p>
<p><a href="/article/passby-fix/image-20240821134322077_hu_e603c646826e57e6.webp" data-fancybox="gallery" data-src="/article/passby-fix/image-20240821134322077_hu_e603c646826e57e6.webp" data-caption="修改位置">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/passby-fix/image-20240821134322077_hu_7f9fe0dc9a8cf386.webp 480w, /article/passby-fix/image-20240821134322077_hu_4f9fbd21e45d6f22.webp 720w, /article/passby-fix/image-20240821134322077_hu_f77e5e4e111c411b.webp 960w, /article/passby-fix/image-20240821134322077_hu_283e56d05b0af49a.webp 1440w, /article/passby-fix/image-20240821134322077_hu_e603c646826e57e6.webp 1926w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1926"
                    height="488"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/passby-fix/image-20240821134322077_hu_4f9fbd21e45d6f22.webp"
                    srcset="/article/passby-fix/image-20240821134322077_hu_7f9fe0dc9a8cf386.webp 480w, /article/passby-fix/image-20240821134322077_hu_4f9fbd21e45d6f22.webp 720w, /article/passby-fix/image-20240821134322077_hu_f77e5e4e111c411b.webp 960w, /article/passby-fix/image-20240821134322077_hu_283e56d05b0af49a.webp 1440w, /article/passby-fix/image-20240821134322077_hu_e603c646826e57e6.webp 1926w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="修改位置"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">BOOL</span> <span class="nf">isUsingBT</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">useGracePeriodOnBT</span> <span class="o">&amp;&amp;</span> <span class="n">allowedBTs</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">NSArray</span> <span class="o">*</span> <span class="n">connectedDevices</span> <span class="o">=</span> <span class="p">[[</span><span class="n">BluetoothManager</span> <span class="n">sharedInstance</span><span class="p">]</span> <span class="n">connectedDevices</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="n">BluetoothDevice</span> <span class="o">*</span> <span class="n">bluetoothDevice</span> <span class="k">in</span> <span class="n">connectedDevices</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">NSString</span> <span class="o">*</span> <span class="n">deviceName</span> <span class="o">=</span> <span class="p">[</span><span class="n">bluetoothDevice</span> <span class="n">name</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">deviceName</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">deviceName</span> <span class="n">length</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="n">deviceName</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// 这里开始
</span></span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">([</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="s">@&#34;Amazfit GTS 2&#34;</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="c1">// 这里结束
</span></span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">NO</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>注：我需要添加的设备名为 <strong>Amazfit GTS 2</strong> ，请根据个人情况自行修改！</p>
<h3 id="修改文件">修改文件</h3>
<p>上面看到它是将设备名的 <strong>sha1</strong> 值这个数据存到 <strong>passbybt.plist</strong> 文件中，我们在iPhone中用 <strong>Filza</strong> 找到这个文件，发现确实如此，它是一个字典格式。</p>
<table>
  <thead>
      <tr>
          <th>sha1</th>
          <th>bool</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>063dc8e6c26233fc20a129a31403a642ea1095c4</td>
          <td>true</td>
      </tr>
      <tr>
          <td>811e9e206b053a4e02c74155bfa27b6c84e7dcad</td>
          <td>true</td>
      </tr>
  </tbody>
</table>
<p>我们利用下面的网页工具将设备名生成对应的sha1值后新添加一个键值对即可：<a href="https://passwords-generator.org/sha1-hash-generator" target="_blank" rel="noopener">SHA-1 Hash Generator</a>。</p>
<blockquote>
<p>2022.12.15 更新：</p>
<p>感谢网友Vivian Chen发邮件提醒我生成sha1的网站已经失效，并且还提供了一个新的网站，再次感谢！</p>
<p><a href="/article/passby-fix/image-20221215103327735_hu_7002d9d18c48ebb.webp" data-fancybox="gallery" data-src="/article/passby-fix/image-20221215103327735_hu_7002d9d18c48ebb.webp" data-caption="生成sha1值">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/passby-fix/image-20221215103327735_hu_61af002d61c7c37.webp 480w, /article/passby-fix/image-20221215103327735_hu_81372b4c66feba38.webp 720w, /article/passby-fix/image-20221215103327735_hu_3ad1143f051be7dd.webp 960w, /article/passby-fix/image-20221215103327735_hu_78a02c8c08fcbe90.webp 1440w, /article/passby-fix/image-20221215103327735_hu_7002d9d18c48ebb.webp 2122w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2122"
                    height="846"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/passby-fix/image-20221215103327735_hu_81372b4c66feba38.webp"
                    srcset="/article/passby-fix/image-20221215103327735_hu_61af002d61c7c37.webp 480w, /article/passby-fix/image-20221215103327735_hu_81372b4c66feba38.webp 720w, /article/passby-fix/image-20221215103327735_hu_3ad1143f051be7dd.webp 960w, /article/passby-fix/image-20221215103327735_hu_78a02c8c08fcbe90.webp 1440w, /article/passby-fix/image-20221215103327735_hu_7002d9d18c48ebb.webp 2122w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="生成sha1值"
                    
                />
            </picture>
        </a></p>
<p><del>特别更新：</del></p>
<p><del>必须勾选上网页的 Lowercase hash 选项，将hash值全部转化为小写，一定要记得！！！</del></p>
</blockquote>
<p><a href="/article/passby-fix/image-20220113161956969_hu_69313b056d793ea5.webp" data-fancybox="gallery" data-src="/article/passby-fix/image-20220113161956969_hu_69313b056d793ea5.webp" data-caption="生成sha1值">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/passby-fix/image-20220113161956969_hu_d611d5133f5c3092.webp 480w, /article/passby-fix/image-20220113161956969_hu_7a1225ddc2061578.webp 720w, /article/passby-fix/image-20220113161956969_hu_4395c656f00f8add.webp 960w, /article/passby-fix/image-20220113161956969_hu_d912e897c2b8a9aa.webp 1440w, /article/passby-fix/image-20220113161956969_hu_69313b056d793ea5.webp 1706w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1706"
                    height="716"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/passby-fix/image-20220113161956969_hu_7a1225ddc2061578.webp"
                    srcset="/article/passby-fix/image-20220113161956969_hu_d611d5133f5c3092.webp 480w, /article/passby-fix/image-20220113161956969_hu_7a1225ddc2061578.webp 720w, /article/passby-fix/image-20220113161956969_hu_4395c656f00f8add.webp 960w, /article/passby-fix/image-20220113161956969_hu_d912e897c2b8a9aa.webp 1440w, /article/passby-fix/image-20220113161956969_hu_69313b056d793ea5.webp 1706w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="生成sha1值"
                    
                />
            </picture>
        </a></p>
<h3 id="打包安装">打包安装</h3>
<p>在PassBy项目文件夹新建终端，输入命令 <strong>make package</strong> 即可打包成deb文件，用Filza打开安装即可。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">yuesir at iMac in ~/Documents/iOS
</span></span><span class="line"><span class="cl">$ <span class="nb">cd</span> PassBy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">yuesir at iMac in ~/Documents/iOS/PassBy <span class="o">(</span>master●<span class="o">)</span>
</span></span><span class="line"><span class="cl">$ make <span class="nv">package</span>
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Warning: Building <span class="k">for</span> iOS 9.0, but the current toolchain can’t produce arm64e binaries <span class="k">for</span> iOS earlier than 14.0. More information: https://theos.dev/docs/arm64e-deployment
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> tweak PassBy…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Preprocessing Tweak.xm…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Preprocessing Tweak.xm…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Preprocessing Tweak.xm…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling Tweak.xm <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling Tweak.xm <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling Tweak.xm <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking tweak PassBy <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassBy…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassBy <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking tweak PassBy <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassBy…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassBy <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking tweak PassBy <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassBy…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassBy <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Merging tweak PassBy…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Signing PassBy…
</span></span><span class="line"><span class="cl">&gt; Making all in passbyprefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Warning: Building <span class="k">for</span> iOS 9.0, but the current toolchain can’t produce arm64e binaries <span class="k">for</span> iOS earlier than 14.0. More information: https://theos.dev/docs/arm64e-deployment
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> bundle PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Copying resource directories into the bundle wrapper…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling PassByRootListController.m <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling PassByRootListController.m <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling PassByRootListController.m <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByPrefs <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByPrefs <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByPrefs <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByPrefs <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByPrefs <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByPrefs <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Merging bundle PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Signing PassByPrefs…
</span></span><span class="line"><span class="cl">&gt; Making all in passbyflipswitch…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Warning: Building <span class="k">for</span> iOS 9.0, but the current toolchain can’t produce arm64e binaries <span class="k">for</span> iOS earlier than 14.0. More information: https://theos.dev/docs/arm64e-deployment
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> bundle PassByFlipswitch…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Copying resource directories into the bundle wrapper…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Preprocessing Switch.xm…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Preprocessing Switch.xm…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Preprocessing Switch.xm…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling Switch.xm <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling Switch.xm <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByFlipswitch <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByFlipswitch…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByFlipswitch <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByFlipswitch <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByFlipswitch…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByFlipswitch <span class="o">(</span>armv7<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling Switch.xm <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByFlipswitch <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByFlipswitch…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByFlipswitch <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Merging bundle PassByFlipswitch…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Signing PassByFlipswitch…
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> tweak PassBy…
</span></span><span class="line"><span class="cl">&gt; Making stage in passbyprefs…
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> bundle PassByPrefs…
</span></span><span class="line"><span class="cl">&gt; Making stage in passbyflipswitch…
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> bundle PassByFlipswitch…
</span></span><span class="line"><span class="cl">dm.pl: building package <span class="sb">`</span>com.giorgioiavicoli.passby:iphoneos-arm<span class="s1">&#39; in `./packages/com.giorgioiavicoli.passby_1.9.1_iphoneos-arm.deb&#39;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>如上所示，我编译好的文件在当前目录的<code>packages/com.giorgioiavicoli.passby_1.9.1_iphoneos-arm.deb</code>位置。</p>
<p>注：如果出现用 <strong>Zebra</strong> 安装不生效时，修改一下版本号，打开PassBy根目录下的 <strong>control</strong> 文件，修改 <strong>Version</strong> 再打包安装即可。</p>
<h2 id="结果">结果</h2>
<p>经测试，我的 Amazfit GTS 2 能够正常解锁使用。因为我对 Obejective-c 语言并不熟悉，虽说步骤还是比较麻烦，但能够成功解决问题，我已是满足了。</p>
<h2 id="感谢">感谢</h2>
<p><a href="https://github.com/giorgioiavicoli/PassBy" target="_blank" rel="noopener">Github项目PassBy</a></p>
<p><a href="https://github.com/theos/theos" target="_blank" rel="noopener">Github项目theos</a></p>
<h2 id="更新1">更新1</h2>
<p>我在使用一段时间插件后发现我手机会出现点亮时多黑屏两三秒的情况。果然，在GitHub上这才发现也有人提了这个问题，限于我技术不行，不知道这是什么问题，怎么解决，遂放弃了这个插件。</p>
<p><a href="/article/passby-fix/image-20220114234532701_hu_3ab16f9b9b3fd6b3.webp" data-fancybox="gallery" data-src="/article/passby-fix/image-20220114234532701_hu_3ab16f9b9b3fd6b3.webp" data-caption="黑屏bug">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/passby-fix/image-20220114234532701_hu_7c442400687dff2d.webp 480w, /article/passby-fix/image-20220114234532701_hu_57f4f19bda8c5a3a.webp 720w, /article/passby-fix/image-20220114234532701_hu_b7633c0019d7c373.webp 960w, /article/passby-fix/image-20220114234532701_hu_b01ed813954dd79c.webp 1440w, /article/passby-fix/image-20220114234532701_hu_3ab16f9b9b3fd6b3.webp 1642w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1642"
                    height="1068"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/passby-fix/image-20220114234532701_hu_57f4f19bda8c5a3a.webp"
                    srcset="/article/passby-fix/image-20220114234532701_hu_7c442400687dff2d.webp 480w, /article/passby-fix/image-20220114234532701_hu_57f4f19bda8c5a3a.webp 720w, /article/passby-fix/image-20220114234532701_hu_b7633c0019d7c373.webp 960w, /article/passby-fix/image-20220114234532701_hu_b01ed813954dd79c.webp 1440w, /article/passby-fix/image-20220114234532701_hu_3ab16f9b9b3fd6b3.webp 1642w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="黑屏bug"
                    
                />
            </picture>
        </a></p>
<h2 id="更新2">更新2</h2>
<p>如果出现不能编译错误，提示 <strong>File Not Found</strong>，请进行编译章节中提示的操作：</p>
<blockquote>
<p>Copy the SDK folder(s) in sdks to $THEOS/sdks and the folder(s) in include to $THEOS/include.</p>
</blockquote>
<p>这一操作在SDK作者的GitHub的ReadME文件中也有展示，请详细阅读。</p>
<h2 id="更新3">更新3</h2>
<p>鉴于我技术不行，按照文章里这么修改的话，安全性方面似乎有些问题，目前我也不知道怎么改进。</p>
<p>如果不介意并且不会编译的话，可以评论区留言<strong>设备名称</strong>，我帮你编译。</p>
<p>安装后，插件设置的设备列表里面并不会出现该设备，也就是不会发生变化。只需要记住<em><strong>在 passbybt.plist 文件那里修改值为true即为开启，false即为关闭。</strong></em></p>
<h2 id="更新4">更新4</h2>
<p>我在新设备上编译该插件时频频报错，最终通过切换Xcode版本到12.5.1得以解决。</p>
<p>详情见：<a href="https://vccv.cc/article/switch-xcode-theos.html" target="_blank" rel="noopener">切换Xcode以编译未适配的theos插件</a>。</p>
]]></content:encoded>
    </item>
    <item>
      <title>Cactus代码块样式美化之旅</title>
      <link>https://vccv.cc/article/cactus-codeblock-beautify.html</link>
      <pubDate>Mon, 27 Dec 2021 15:42:28 +0000</pubDate>
      <guid>https://vccv.cc/article/cactus-codeblock-beautify.html</guid>
      <description>cactus原先的代码块样式我自己并不是很喜欢。因为以前使用过wordpress的主题，里面有仿mac的样式。但是cactus并没有代码块的样式设置，于是决定自己动手，改造主题！！！</description>
      <content:encoded><![CDATA[<h2 id="前因">前因</h2>
<p>cactus原先的代码块样式我自己并不是很喜欢。因为以前使用过wordpress的主题，里面有仿mac的样式。但是cactus并没有代码块的样式设置，于是决定自己动手，改造主题！！！</p>
<h2 id="经过">经过</h2>
<p>很庆幸在网上找到了相关的教程，虽然不是专属于cactus的手把手教程，但经过一段时间的努力，还是成功解决了哈哈哈😂在这里先感谢原作者啦。</p>
<p>按照惯例，分享给后来者，免得重复造轮子，浪费时间。</p>
<ol>
<li>
<p>建议先浏览一遍原教程：<a href="https://blog.imlete.cn/article/Hexo-add-CodeBlock.html" target="_blank" rel="noopener">Hexo-添加代码块边框</a>。</p>
</li>
<li>
<p>以下为特属于cactus主题的修改，仅供参考：</p>
<ul>
<li>
<p>在 <strong>source/css</strong> 目录找到主题的 <strong>style.styl</strong> 文件，代码对应位置修改如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-styl" data-lang="styl"><span class="line"><span class="cl"><span class="o">//</span> <span class="nt">Code</span>
</span></span><span class="line"><span class="cl"><span class="kp">@import</span> <span class="err">&#39;_highlight</span><span class="o">/</span><span class="err">codeFrame&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kp">@import</span> <span class="err">&#39;_highlight</span><span class="o">/</span><span class="err">theme&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kp">@import</span> <span class="err">&#39;_highlight</span><span class="o">/</span><span class="err">d</span><span class="k">if</span><span class="err">f&#39;</span>
</span></span><span class="line"><span class="cl"><span class="o">...................</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">highlight</span>
</span></span><span class="line"><span class="cl">	<span class="py">margin</span><span class="p">:</span> <span class="err">2rem</span> <span class="err">0</span> <span class="err">0</span> <span class="err">0</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>上述文件同一位置<code>.highlight</code>代码块中将</p>
<p><code>border-radius: 4px</code> 删除；</p>
<p><code>background: $color-background-code</code>删除。</p>
</li>
<li>
<p>同上在<code>.btn-copy</code>中添加属性 <code>top: 0.2rem</code></p>
</li>
</ul>
</li>
<li>
<p>最后我将 <strong>_highlight</strong> 文件夹里的原文件全部删除了，只剩下那三个新建文件。</p>
<p><a href="/article/cactus-codeblock-beautify/image-20211227223103409_hu_c40c003fe9ef374b.webp" data-fancybox="gallery" data-src="/article/cactus-codeblock-beautify/image-20211227223103409_hu_c40c003fe9ef374b.webp" data-caption="修改文件">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/cactus-codeblock-beautify/image-20211227223103409_hu_e920f01a04b58691.webp 480w, /article/cactus-codeblock-beautify/image-20211227223103409_hu_a6e4c1760b8282e5.webp 720w, /article/cactus-codeblock-beautify/image-20211227223103409_hu_c40c003fe9ef374b.webp 826w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="826"
                    height="160"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/cactus-codeblock-beautify/image-20211227223103409_hu_a6e4c1760b8282e5.webp"
                    srcset="/article/cactus-codeblock-beautify/image-20211227223103409_hu_e920f01a04b58691.webp 480w, /article/cactus-codeblock-beautify/image-20211227223103409_hu_a6e4c1760b8282e5.webp 720w, /article/cactus-codeblock-beautify/image-20211227223103409_hu_c40c003fe9ef374b.webp 826w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="修改文件"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>注意：</p>
<ul>
<li>原教程中第三步我发现可以直接跳过，因为cactus的代码块相关代码都在 <strong>style.styl</strong> 文件中。</li>
<li>更改代码块不同高亮样式只需要更改 <strong>diff.styl</strong> 文件。</li>
</ul>
</li>
</ol>
<h2 id="最终成果">最终成果</h2>
<p>修改前：</p>
<p><a href="/article/cactus-codeblock-beautify/image-20211227223503492_hu_ec63987de62c4a13.webp" data-fancybox="gallery" data-src="/article/cactus-codeblock-beautify/image-20211227223503492_hu_ec63987de62c4a13.webp" data-caption="修改前">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/cactus-codeblock-beautify/image-20211227223503492_hu_f153146d43e07c05.webp 480w, /article/cactus-codeblock-beautify/image-20211227223503492_hu_eb81d9b489aaae8d.webp 720w, /article/cactus-codeblock-beautify/image-20211227223503492_hu_ed3c7df325d83143.webp 960w, /article/cactus-codeblock-beautify/image-20211227223503492_hu_f1c7b33e28419c69.webp 1440w, /article/cactus-codeblock-beautify/image-20211227223503492_hu_ec63987de62c4a13.webp 1850w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1850"
                    height="1152"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/cactus-codeblock-beautify/image-20211227223503492_hu_eb81d9b489aaae8d.webp"
                    srcset="/article/cactus-codeblock-beautify/image-20211227223503492_hu_f153146d43e07c05.webp 480w, /article/cactus-codeblock-beautify/image-20211227223503492_hu_eb81d9b489aaae8d.webp 720w, /article/cactus-codeblock-beautify/image-20211227223503492_hu_ed3c7df325d83143.webp 960w, /article/cactus-codeblock-beautify/image-20211227223503492_hu_f1c7b33e28419c69.webp 1440w, /article/cactus-codeblock-beautify/image-20211227223503492_hu_ec63987de62c4a13.webp 1850w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="修改前"
                    
                />
            </picture>
        </a></p>
<p>修改后：</p>
<p><a href="/article/cactus-codeblock-beautify/image-20211227172137422_hu_520db2d451274999.webp" data-fancybox="gallery" data-src="/article/cactus-codeblock-beautify/image-20211227172137422_hu_520db2d451274999.webp" data-caption="修改后">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/cactus-codeblock-beautify/image-20211227172137422_hu_1c07735fa98b8cf0.webp 480w, /article/cactus-codeblock-beautify/image-20211227172137422_hu_f5e380d3c5491f3b.webp 720w, /article/cactus-codeblock-beautify/image-20211227172137422_hu_f75fbcd42f511de7.webp 960w, /article/cactus-codeblock-beautify/image-20211227172137422_hu_69758693d2b0250b.webp 1440w, /article/cactus-codeblock-beautify/image-20211227172137422_hu_520db2d451274999.webp 1876w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1876"
                    height="904"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/cactus-codeblock-beautify/image-20211227172137422_hu_f5e380d3c5491f3b.webp"
                    srcset="/article/cactus-codeblock-beautify/image-20211227172137422_hu_1c07735fa98b8cf0.webp 480w, /article/cactus-codeblock-beautify/image-20211227172137422_hu_f5e380d3c5491f3b.webp 720w, /article/cactus-codeblock-beautify/image-20211227172137422_hu_f75fbcd42f511de7.webp 960w, /article/cactus-codeblock-beautify/image-20211227172137422_hu_69758693d2b0250b.webp 1440w, /article/cactus-codeblock-beautify/image-20211227172137422_hu_520db2d451274999.webp 1876w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="修改后"
                    
                />
            </picture>
        </a></p>
<p>我个人还是比较满意滴，配色这些就全靠大家自行发挥了哈。</p>
]]></content:encoded>
    </item>
    <item>
      <title>iOS越狱设备也要玩原神</title>
      <link>https://vccv.cc/article/ios-jailbreak-genshin.html</link>
      <pubDate>Thu, 23 Dec 2021 22:29:23 +0000</pubDate>
      <guid>https://vccv.cc/article/ios-jailbreak-genshin.html</guid>
      <description>在2021-12-22 14:00，原神终于也对iOS越狱玩家出手了，iOS端原神开始检测越狱设备，提示“数据异常，请重新登录”。我在GitHub上搜索关键词发现一屏蔽越狱插件并修改完善后正常使用原神iOS端。</description>
      <content:encoded><![CDATA[<h2 id="更新3">更新3</h2>
<p>经评论区老哥反馈，截止2022/07/16的iOS原神最新版本，文章下载链接里的屏蔽插件还是可以正常使用。</p>
<p>鉴于BigBoss源插件的不稳定更新，建议使用文章下载链接里面的第一版插件。</p>
<h2 id="事情起因">事情起因</h2>
<p>iOS端原神终于也不当人了，在2021-12-22 14:00，iOS端原神开始检测越狱设备，提示“数据异常，请重新登录”。</p>
<p><a href="/article/ios-jailbreak-genshin/img_hu_f4c27533f76c2544.webp" data-fancybox="gallery" data-src="/article/ios-jailbreak-genshin/img_hu_f4c27533f76c2544.webp" data-caption="官方警告">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ios-jailbreak-genshin/img_hu_179a1059803b7455.webp 480w, /article/ios-jailbreak-genshin/img_hu_ad2d159bda1d13a0.webp 720w, /article/ios-jailbreak-genshin/img_hu_f4c27533f76c2544.webp 910w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="910"
                    height="430"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ios-jailbreak-genshin/img_hu_ad2d159bda1d13a0.webp"
                    srcset="/article/ios-jailbreak-genshin/img_hu_179a1059803b7455.webp 480w, /article/ios-jailbreak-genshin/img_hu_ad2d159bda1d13a0.webp 720w, /article/ios-jailbreak-genshin/img_hu_f4c27533f76c2544.webp 910w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="官方警告"
                    
                />
            </picture>
        </a></p>
<h2 id="经过">经过</h2>
<p>我在GitHub上搜索关键词发现一国外老哥在六天前发布过一个越狱插件。</p>
<p>但是！！！</p>
<p>原作者误将原神在国内的包名写错：</p>
<p><a href="/article/ios-jailbreak-genshin/error_hu_c2f469cfa55717da.webp" data-fancybox="gallery" data-src="/article/ios-jailbreak-genshin/error_hu_c2f469cfa55717da.webp" data-caption="错误代码">
            <picture>
                <source
                    type="image/webp"
                    srcset="/article/ios-jailbreak-genshin/error_hu_22262c7272ea2bc1.webp 480w, /article/ios-jailbreak-genshin/error_hu_14d482f6e42c3e2a.webp 720w, /article/ios-jailbreak-genshin/error_hu_c60ac2fefdf9df27.webp 960w, /article/ios-jailbreak-genshin/error_hu_65f656b816e1bc6a.webp 1440w, /article/ios-jailbreak-genshin/error_hu_c2f469cfa55717da.webp 1734w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1734"
                    height="136"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/article/ios-jailbreak-genshin/error_hu_14d482f6e42c3e2a.webp"
                    srcset="/article/ios-jailbreak-genshin/error_hu_22262c7272ea2bc1.webp 480w, /article/ios-jailbreak-genshin/error_hu_14d482f6e42c3e2a.webp 720w, /article/ios-jailbreak-genshin/error_hu_c60ac2fefdf9df27.webp 960w, /article/ios-jailbreak-genshin/error_hu_65f656b816e1bc6a.webp 1440w, /article/ios-jailbreak-genshin/error_hu_c2f469cfa55717da.webp 1734w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="错误代码"
                    
                />
            </picture>
        </a></p>
<h2 id="解决办法">解决办法</h2>
<p>原代码：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">{ Filter = { Bundles = ( &#34;com.miHoYo.GenshinImpact&#34;, &#34;com.miHoYo.Yanshen&#34; ); }; }
</span></span></code></pre></td></tr></table>
</div>
</div><p>更正为：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">{ Filter = { Bundles = ( &#34;com.miHoYo.GenshinImpact&#34;, &#34;com.miHoYo.Yuanshen&#34; ); }; }
</span></span></code></pre></td></tr></table>
</div>
</div><p>我将原作者打包的deb包解包修改后重新编译发布，做了一点微不足道的小事情。</p>
<h2 id="结果">结果</h2>
<p>经本人测试，原神国服已经能够正常运行，国际服待测。</p>
<blockquote>
<p>测试设备</p>
<p>机型：12mini</p>
<p>iOS版本：14.2.1</p>
<p>越狱软件：unc0ver</p>
</blockquote>
<h2 id="下载">下载</h2>
<p><a href="https://yuesir.lanzouo.com/iejurxwygaf" target="_blank" rel="noopener">蓝奏云</a></p>
<h2 id="感谢">感谢🙏</h2>
<p><a href="https://github.com/iVoider/GenshinJailbreakBypass" target="_blank" rel="noopener">Github作者iVoider</a></p>
<h2 id="更新1">更新1</h2>
<p>BigBoss源上已有作者上传维护插件，名为 <strong>原神（国服）屏蔽越狱</strong> 。经测试可以正常使用，请直接前去下载安装。</p>
<h2 id="更新2">更新2</h2>
<p>插件已经改名，叫做 <strong>原神防越狱检测</strong> 。</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
