<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>笔记本 Blog</title>
        <link>https://ituknown.github.io/blog/</link>
        <description>笔记本 Blog</description>
        <lastBuildDate>Thu, 25 Jun 2026 20:30:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh</language>
        <item>
            <title><![CDATA[命令行切换代理（Bash 与 PowerShell）]]></title>
            <link>https://ituknown.github.io/blog/命令行切换代理/</link>
            <guid>https://ituknown.github.io/blog/命令行切换代理/</guid>
            <pubDate>Thu, 25 Jun 2026 20:30:00 GMT</pubDate>
            <description><![CDATA[命令行工具（curl、wget、git 等）走代理靠的是一组环境变量：httpproxy / httpsproxy / all_proxy。手动 export 一次只管当前会话，端口一变就得重敲，关代理又得逐个 unset，繁琐还容易漏。]]></description>
            <content:encoded><![CDATA[<p>命令行工具（<code>curl</code>、<code>wget</code>、<code>git</code> 等）走代理靠的是一组环境变量：<code>http_proxy</code> / <code>https_proxy</code> / <code>all_proxy</code>。手动 <code>export</code> 一次只管当前会话，端口一变就得重敲，关代理又得逐个 <code>unset</code>，繁琐还容易漏。</p>
<p>把开关封装成一对函数写进 shell 配置文件，启动即常驻，敲一个命令完成切换。Bash 与 PowerShell 各一份对称实现，共同点三个：默认端口集中在顶部、大小写变量都设、开启后立即验证连通性并在失败时自动回滚。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="设计要点">设计要点<a href="https://ituknown.github.io/blog/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%88%87%E6%8D%A2%E4%BB%A3%E7%90%86/#%E8%AE%BE%E8%AE%A1%E8%A6%81%E7%82%B9" class="hash-link" aria-label="设计要点的直接链接" title="设计要点的直接链接" translate="no">​</a></h2>
<p><strong>默认端口集中配置。</strong> 端口写在脚本顶部的 <code>GLOBAL_DEFAULT_PROXY_PORT</code> 变量里，换端口只改这一处，所有调用点自动生效，避免硬编码散落各处。</p>
<p><strong>大小写变量都设。</strong> <code>http_proxy</code> 和 <code>HTTP_PROXY</code> 同时 <code>export</code>。不同工具读取的变量名并不统一：<code>curl</code>、<code>wget</code> 读小写，而 .NET、Go 的部分 HTTP 客户端读大写。两套都设上，覆盖面最广。</p>
<p><strong><code>all_proxy</code> 用 socks5。</strong> <code>http_proxy</code> / <code>https_proxy</code> 走 HTTP 代理，<code>all_proxy</code> 额外指定 socks5 入口，给那些支持 socks 的工具使用。</p>
<p><strong>开启即验证，失败自动回滚。</strong> <code>enable</code> 后立即请求一次 Google，3 秒超时。拿不到 200 就说明代理没通（端口写错、代理软件没开等），此时自动调用 <code>disable</code> 清理变量——否则环境里留着一组指向不通地址的代理变量，后续所有命令都会卡在连接超时上，排查很费时间。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="Bash-实现">Bash 实现<a href="https://ituknown.github.io/blog/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%88%87%E6%8D%A2%E4%BB%A3%E7%90%86/#Bash-%E5%AE%9E%E7%8E%B0" class="hash-link" aria-label="Bash 实现的直接链接" title="Bash 实现的直接链接" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># ================= 配置区 =================</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 修改常用默认端口，改一次全局生效</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">GLOBAL_DEFAULT_PROXY_PORT</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"7897"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ==========================================</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 关闭代理</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">proxy_disable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 同时卸载小写和大写的代理变量</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">unset</span><span class="token plain"> http_proxy https_proxy all_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[33m❌ 代理已关闭</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 开启代理</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 用法: proxy_enable [端口号]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">proxy_enable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 未指定端口时提示用法</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-z</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$1</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[90m💡 提示命令用法: proxy_enable &lt;端口号&gt;</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[36m🔄 检测到未指定端口，将使用默认端口: </span><span class="token string variable" style="color:#36acaa">${GLOBAL_DEFAULT_PROXY_PORT}</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fi</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># $1 为空则回退到全局默认端口</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">local</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">port</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">${1</span><span class="token variable operator" style="color:#393A34">:-</span><span class="token variable" style="color:#36acaa">$GLOBAL_DEFAULT_PROXY_PORT}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 设置代理变量（兼顾大小写）</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">http_proxy</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">https_proxy</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">all_proxy</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"socks5://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">HTTP_PROXY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">HTTPS_PROXY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">ALL_PROXY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"socks5://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[36m🚀 代理变量已设置 (端口: </span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">)，正在验证网络...</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 验证是否生效，3 秒超时</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">local</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">status_code</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">curl</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-I</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-s</span><span class="token variable" style="color:#36acaa"> --connect-timeout </span><span class="token variable number" style="color:#36acaa">3</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-w</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">"%{http_code}"</span><span class="token variable" style="color:#36acaa"> https://www.google.com </span><span class="token variable parameter variable" style="color:#36acaa">-o</span><span class="token variable" style="color:#36acaa"> /dev/null</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$status_code</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"200"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[32m✅ 代理连接成功！Google 响应正常。</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[31m❌ 代理连接失败 (状态码: </span><span class="token string variable" style="color:#36acaa">${status_code</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">超时</span><span class="token string variable operator" style="color:#393A34">/</span><span class="token string variable" style="color:#36acaa">无法连接}</span><span class="token string" style="color:#e3116c">)</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[33m🔄 正在自动清理代理环境变量...</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        proxy_disable</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fi</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>几个细节：</p>
<ul>
<li class=""><code>[ -z "$1" ]</code> 判断是否传了端口，没传就提示用法；<code>${1:-$GLOBAL_DEFAULT_PROXY_PORT}</code> 是参数默认值语法，<code>$1</code> 为空时回退到全局默认端口。</li>
<li class=""><code>unset</code> 一次性卸载大小写共六个变量。</li>
<li class=""><code>curl -I -s --connect-timeout 3 -w "%{http_code}" -o /dev/null</code>：只取响应头、静默、3 秒连接超时、末尾打印 HTTP 状态码、正文丢弃。拿到 <code>200</code> 即通。</li>
<li class="">失败分支先 <code>proxy_disable</code> 清理变量，再 <code>return 2</code>，用非零返回值标记失败，方便在脚本里判断。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="WSL宿主机地址不是-127001">WSL：宿主机地址不是 127.0.0.1<a href="https://ituknown.github.io/blog/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%88%87%E6%8D%A2%E4%BB%A3%E7%90%86/#WSL%E5%AE%BF%E4%B8%BB%E6%9C%BA%E5%9C%B0%E5%9D%80%E4%B8%8D%E6%98%AF-127001" class="hash-link" aria-label="WSL：宿主机地址不是 127.0.0.1的直接链接" title="WSL：宿主机地址不是 127.0.0.1的直接链接" translate="no">​</a></h3>
<p>WSL2 默认走独立的 NAT 网络，<code>127.0.0.1</code> 指向 WSL 自身而非 Windows 宿主机，直接连 <code>127.0.0.1:7897</code> 连不到宿主机上的代理。宿主机 IP 记在 <code>/etc/resolv.conf</code> 的 <code>nameserver</code> 一行里：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> nameserver /etc/resolv.conf </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">awk</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'{print $2}'</span><br></div></code></pre></div></div>
<p>要让上面的 <code>proxy_enable</code> 在 WSL 下也直接可用，在解析端口后加一段 host 判断：非 WSL 用 <code>127.0.0.1</code>，WSL 用宿主机 IP。<code>/proc/version</code> 里带 <code>microsoft</code> 字样即可识别 WSL：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token function-name function" style="color:#d73a49">proxy_enable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-z</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$1</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[90m💡 提示命令用法: proxy_enable &lt;端口号&gt;</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[36m🔄 检测到未指定端口，将使用默认端口: </span><span class="token string variable" style="color:#36acaa">${GLOBAL_DEFAULT_PROXY_PORT}</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fi</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">local</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">port</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">${1</span><span class="token variable operator" style="color:#393A34">:-</span><span class="token variable" style="color:#36acaa">$GLOBAL_DEFAULT_PROXY_PORT}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># ↓↓↓ 新增：WSL 下用宿主机 IP，否则 127.0.0.1 连不到宿主机代理</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">local</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">host</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"127.0.0.1"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-qi</span><span class="token plain"> microsoft /proc/version </span><span class="token operator file-descriptor important" style="color:#393A34">2</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain">/dev/null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token assign-left variable" style="color:#36acaa">host</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">grep</span><span class="token variable" style="color:#36acaa"> nameserver /etc/resolv.conf </span><span class="token variable operator" style="color:#393A34">|</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable function" style="color:#d73a49">awk</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">'{print $2}'</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[36m🌐 检测到 WSL，使用宿主机 IP: </span><span class="token string variable" style="color:#36acaa">${host}</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fi</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># ↑↑↑</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 6 个 export 把原来的 127.0.0.1 全部换成 ${host}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">http_proxy</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://</span><span class="token string variable" style="color:#36acaa">${host}</span><span class="token string" style="color:#e3116c">:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">https_proxy</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://</span><span class="token string variable" style="color:#36acaa">${host}</span><span class="token string" style="color:#e3116c">:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">all_proxy</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"socks5://</span><span class="token string variable" style="color:#36acaa">${host}</span><span class="token string" style="color:#e3116c">:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">HTTP_PROXY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://</span><span class="token string variable" style="color:#36acaa">${host}</span><span class="token string" style="color:#e3116c">:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">HTTPS_PROXY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"http://</span><span class="token string variable" style="color:#36acaa">${host}</span><span class="token string" style="color:#e3116c">:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">ALL_PROXY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"socks5://</span><span class="token string variable" style="color:#36acaa">${host}</span><span class="token string" style="color:#e3116c">:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[36m🚀 代理变量已设置 (</span><span class="token string variable" style="color:#36acaa">${host}</span><span class="token string" style="color:#e3116c">:</span><span class="token string variable" style="color:#36acaa">${port}</span><span class="token string" style="color:#e3116c">)，正在验证网络...</span><span class="token string entity" style="color:#36acaa">\033</span><span class="token string" style="color:#e3116c">[0m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 后续验证、回滚逻辑不变……</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>改动只有两处：插入一段 <code>host</code> 变量判断，再把 6 个 <code>export</code> 里的 <code>127.0.0.1</code> 换成 <code>${host}</code>。<code>proxy_disable</code> 不用动。Windows 侧代理软件还需开启「允许局域网连接（Allow LAN）」，否则宿主机会拒绝来自 WSL 网段的请求。</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="换-mirrored-模式127001-直接可用">换 mirrored 模式：127.0.0.1 直接可用<a href="https://ituknown.github.io/blog/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%88%87%E6%8D%A2%E4%BB%A3%E7%90%86/#%E6%8D%A2-mirrored-%E6%A8%A1%E5%BC%8F127001-%E7%9B%B4%E6%8E%A5%E5%8F%AF%E7%94%A8" class="hash-link" aria-label="换 mirrored 模式：127.0.0.1 直接可用的直接链接" title="换 mirrored 模式：127.0.0.1 直接可用的直接链接" translate="no">​</a></h3>
<p>不想改脚本的话，切到 WSL2 的 mirrored 网络模式更省事——该模式下 WSL 与宿主机共享网卡，<code>localhost</code> 互通，<code>127.0.0.1</code> 直接连到宿主机代理，上面的 host 判断也就不必加。前提是 <strong>Windows 11 22H2 及以上</strong>（Win10 不支持）。</p>
<p>在 Windows 用户目录（<code>%USERPROFILE%</code>）下新建 <code>.wslconfig</code>，写入：</p>
<div class="language-ini codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-ini codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">[wsl2]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">networkingMode=mirrored</span><br></div></code></pre></div></div>
<p>保存后执行 <code>wsl --shutdown</code> 关掉再重开 WSL 即可生效。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="PowerShell-实现">PowerShell 实现<a href="https://ituknown.github.io/blog/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%88%87%E6%8D%A2%E4%BB%A3%E7%90%86/#PowerShell-%E5%AE%9E%E7%8E%B0" class="hash-link" aria-label="PowerShell 实现的直接链接" title="PowerShell 实现的直接链接" translate="no">​</a></h2>
<div class="language-powershell codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-powershell codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># ================= 配置区 =================</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 修改常用默认端口，改一次全局生效</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token variable" style="color:#36acaa">$GLOBAL_DEFAULT_PROXY_PORT</span><span class="token plain"> = </span><span class="token string" style="color:#e3116c">"7897"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ==========================================</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 关闭代理</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> ProxyDisable </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 移除小写和大写的代理环境变量（不存在时静默忽略）</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">Remove-Item</span><span class="token plain"> env:http_proxy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> env:https_proxy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> env:all_proxy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> env:HTTP_PROXY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> env:HTTPS_PROXY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> env:ALL_PROXY </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ErrorAction SilentlyContinue</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">Write-Host</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"❌ 代理已关闭"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ForegroundColor Yellow</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 开启代理</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 用法: ProxyEnable [端口号]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> ProxyEnable </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">param</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token namespace" style="opacity:0.7">[string]</span><span class="token variable" style="color:#36acaa">$Port</span><span class="token plain"> = </span><span class="token variable" style="color:#36acaa">$GLOBAL_DEFAULT_PROXY_PORT</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 仅在用户未显式传参时提示用法</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">$PSBoundParameters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Count </span><span class="token operator" style="color:#393A34">-eq</span><span class="token plain"> 0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">Write-Host</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"💡 提示命令用法: ProxyEnable &lt;端口号&gt;"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ForegroundColor Gray</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">Write-Host</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"🔄 检测到未指定端口，将使用默认端口: </span><span class="token string variable" style="color:#36acaa">$GLOBAL_DEFAULT_PROXY_PORT</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ForegroundColor Cyan</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 设置代理变量（兼顾大小写）</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">$env</span><span class="token plain">:http_proxy = </span><span class="token string" style="color:#e3116c">"http://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">$Port</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">$env</span><span class="token plain">:https_proxy = </span><span class="token string" style="color:#e3116c">"http://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">$Port</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">$env</span><span class="token plain">:all_proxy = </span><span class="token string" style="color:#e3116c">"socks5://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">$Port</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">$env</span><span class="token plain">:HTTP_PROXY = </span><span class="token string" style="color:#e3116c">"http://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">$Port</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">$env</span><span class="token plain">:HTTPS_PROXY = </span><span class="token string" style="color:#e3116c">"http://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">$Port</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">$env</span><span class="token plain">:ALL_PROXY = </span><span class="token string" style="color:#e3116c">"socks5://127.0.0.1:</span><span class="token string variable" style="color:#36acaa">$Port</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">Write-Host</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"🚀 代理变量已设置 (端口: </span><span class="token string variable" style="color:#36acaa">$Port</span><span class="token string" style="color:#e3116c">)，正在验证网络..."</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ForegroundColor Cyan</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 验证是否生效，3 秒超时</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token variable" style="color:#36acaa">$response</span><span class="token plain"> = </span><span class="token function" style="color:#d73a49">Invoke-WebRequest</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">Uri </span><span class="token string" style="color:#e3116c">"https://www.google.com"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">TimeoutSec 3 </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">Method Head </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ErrorAction Stop</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token variable" style="color:#36acaa">$statusCode</span><span class="token plain"> = </span><span class="token variable" style="color:#36acaa">$response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">StatusCode</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token variable" style="color:#36acaa">$statusCode</span><span class="token plain"> = </span><span class="token string" style="color:#e3116c">"超时或无法连接"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token variable" style="color:#36acaa">$statusCode</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-eq</span><span class="token plain"> 200</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">Write-Host</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"✅ 代理连接成功！Google 响应正常。"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ForegroundColor Green</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">Write-Host</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"❌ 代理连接失败 (状态: </span><span class="token string variable" style="color:#36acaa">$statusCode</span><span class="token string" style="color:#e3116c">)"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ForegroundColor Red</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">Write-Host</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"🔄 正在自动清理代理环境变量..."</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">ForegroundColor Yellow</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ProxyDisable</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>几个细节：</p>
<ul>
<li class=""><code>param([string]$Port = $GLOBAL_DEFAULT_PROXY_PORT)</code> 给参数带默认值，不传也能跑。但「不传」和「传了一个等于默认值的参数」在 PowerShell 里是两回事——前者 <code>$PSBoundParameters</code>（实际绑定的参数字典）为空，后者非空。这里用 <code>$PSBoundParameters.Count -eq 0</code> 精确区分，只在用户真的没传时才打印用法提示。</li>
<li class=""><code>Remove-Item env:xxx -ErrorAction SilentlyContinue</code>：卸载变量时若某个变量本就不存在会报错，加 <code>SilentlyContinue</code> 静默忽略。</li>
<li class="">验证用 <code>Invoke-WebRequest -Method Head -TimeoutSec 3</code>。和 Bash 不同，PowerShell 里连接超时或请求失败是<strong>抛异常</strong>而非返回状态码，所以必须用 <code>try/catch</code> 接住，在 <code>catch</code> 里把状态记为失败，再走清理逻辑。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="加载到配置文件">加载到配置文件<a href="https://ituknown.github.io/blog/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%88%87%E6%8D%A2%E4%BB%A3%E7%90%86/#%E5%8A%A0%E8%BD%BD%E5%88%B0%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6" class="hash-link" aria-label="加载到配置文件的直接链接" title="加载到配置文件的直接链接" translate="no">​</a></h2>
<p>函数定义只有被 shell 启动时加载进会话，才能随时敲 <code>proxy_enable</code> / <code>ProxyEnable</code> 调用。两个脚本各自走自己平台的配置加载机制。</p>
<p>Bash 侧，把 <code>proxy.sh</code> 放进 <code>~/.profile.d/</code>，由 <code>~/.profile</code>（或 <code>.bashrc</code> / <code>.zshrc</code>）统一遍历加载：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> ~/.profile.d </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token for-or-select variable" style="color:#36acaa">f</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> ~/.profile.d/*.sh</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">do</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$f</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token builtin class-name">.</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$f</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">done</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token builtin class-name">unset</span><span class="token plain"> f</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fi</span><br></div></code></pre></div></div>
<p>具体的拆分思路与加载方式见 <a class="" href="https://ituknown.github.io/system/linux/Shell%20%E7%9F%A5%E8%AF%86/%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E6%AD%A3%E7%A1%AE%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/">配置文件正确使用姿势</a>。</p>
<p>PowerShell 侧，把 <code>Proxy.ps1</code> 放进 <code>$PROFILE</code> 同目录下的 <code>ProfileScripts/</code>，由主配置文件 dot-source 加载：</p>
<div class="language-powershell codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-powershell codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token variable" style="color:#36acaa">$ConfigDir</span><span class="token plain"> = </span><span class="token function" style="color:#d73a49">Join-Path</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">Split-Path</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">Parent </span><span class="token variable" style="color:#36acaa">$PROFILE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ProfileScripts"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">Get-ChildItem</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain">Path </span><span class="token variable" style="color:#36acaa">$ConfigDir</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token keyword" style="color:#00009f">Filter</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ps1 </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ForEach-Object</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><span class="token variable" style="color:#36acaa">$_</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">FullName </span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>完整结构与 dot-source 的作用见 <a class="" href="https://ituknown.github.io/system/windows/PowerShell%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/">PowerShell 配置文件最佳实践</a>。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="使用">使用<a href="https://ituknown.github.io/blog/%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%88%87%E6%8D%A2%E4%BB%A3%E7%90%86/#%E4%BD%BF%E7%94%A8" class="hash-link" aria-label="使用的直接链接" title="使用的直接链接" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">proxy_enable            </span><span class="token comment" style="color:#999988;font-style:italic"># 开启，用默认端口 7897</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">proxy_enable </span><span class="token number" style="color:#36acaa">10808</span><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic"># 开启，指定端口</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">proxy_disable           </span><span class="token comment" style="color:#999988;font-style:italic"># 关闭</span><br></div></code></pre></div></div>
<div class="language-powershell codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-powershell codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># PowerShell</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ProxyEnable             </span><span class="token comment" style="color:#999988;font-style:italic"># 开启，用默认端口 7897</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ProxyEnable 10808       </span><span class="token comment" style="color:#999988;font-style:italic"># 开启，指定端口</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ProxyDisable            </span><span class="token comment" style="color:#999988;font-style:italic"># 关闭</span><br></div></code></pre></div></div>
<p>开启时会打印当前端口并自动验证；代理不通则立即回滚并给出失败状态码。代理变量的含义以及 <code>no_proxy</code> 等其它相关变量，见 <a class="" href="https://ituknown.github.io/system/linux/%E7%BD%91%E7%BB%9C%E8%AE%BE%E7%BD%AE/Linux%20%E5%91%BD%E4%BB%A4%E8%A1%8C%E8%AE%BE%E7%BD%AE%E4%BB%A3%E7%90%86/">Linux 命令行设置代理</a>。</p>]]></content:encoded>
            <category>代理</category>
        </item>
        <item>
            <title><![CDATA[生成随机数时为什么需要设置 Seed]]></title>
            <link>https://ituknown.github.io/blog/生成随机数时为什么需要设置-Seed/</link>
            <guid>https://ituknown.github.io/blog/生成随机数时为什么需要设置-Seed/</guid>
            <pubDate>Thu, 01 Jan 2026 14:06:00 GMT</pubDate>
            <description><![CDATA[在计算机中，算法层面并不存在真正的随机数，凡是使用算法生成的随机数都是伪随机数（Pseudo-Random Numbers, PRNG）。]]></description>
            <content:encoded><![CDATA[<p>在计算机中，算法层面并不存在真正的随机数，凡是使用算法生成的随机数都是伪随机数（<a href="https://en.wikipedia.org/wiki/Pseudorandom_number_generator" target="_blank" rel="noopener noreferrer" class="">Pseudo-Random Numbers, PRNG</a>）。</p>
<p>在编程中用到的各种 random 库，都是通过算法进行一系列复杂的运算生成的序列。每次生成的结果其实都是可预测的，并不是真正的随机数。</p>
<p>真随机数（也被称为<a href="https://en.wikipedia.org/wiki/Hardware_random_number_generator" target="_blank" rel="noopener noreferrer" class="">硬件随机数</a>）是那种不依赖于任何逻辑算法，仅依赖于物理世界的不可预测性。计算机通过硬件捕捉真实环境中的熵（如热噪声、光电效应、放射性衰变等），转换得到的数字序列才是真随机数。各种编程语言提供的真随机数生成器（如 C++ 的 <code>std::random_device</code>），本质都是 CPU 提供的真随机数指令（如 Intel 的 RDRAND 指令）驱动硬件捕捉物理噪声源（电路上的电热噪声来产生熵）实现的。</p>
<p>算法生成伪随机数就是一次计算 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord mathnormal" style="margin-right:0.1076em">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 值的过程，正态分布（<a href="https://cplusplus.com/reference/random/normal_distribution/" target="_blank" rel="noopener noreferrer" class="">std::normal_distribution</a>）、均匀离散分布（<a href="https://cplusplus.com/reference/random/uniform_int_distribution/" target="_blank" rel="noopener noreferrer" class="">std::uniform_int_distribution</a>）和伯努利分布（<a href="https://cplusplus.com/reference/random/binomial_distribution/" target="_blank" rel="noopener noreferrer" class="">std::binomial_distribution</a>）这些复杂的算法可能不懂，但是简单的还是能轻松拿捏的，比如二次函数：</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mstyle mathsize="1.44em"><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi>a</mi><msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><mi>b</mi></mstyle></mrow><annotation encoding="application/x-tex">{\Large f(x) = ax^2 + b }</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.5992em;vertical-align:-0.36em"></span><span class="mord"><span class="mord mathnormal sizing reset-size6 size8" style="margin-right:0.1076em">f</span><span class="mopen sizing reset-size6 size8">(</span><span class="mord mathnormal sizing reset-size6 size8">x</span><span class="mclose sizing reset-size6 size8">)</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel sizing reset-size6 size8">=</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mord mathnormal sizing reset-size6 size8">a</span><span class="mord sizing reset-size6 size8"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8605em"><span style="top:-3.413em;margin-right:0.0347em"><span class="pstrut" style="height:3em"></span><span class="sizing reset-size8 size6 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin sizing reset-size6 size8">+</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mord mathnormal sizing reset-size6 size8">b</span></span></span></span></span></span>
<p>你不要在意 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">ax^2+b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em"></span><span class="mord mathnormal">a</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:0.6944em"></span><span class="mord mathnormal">b</span></span></span></span>，你需要将该函数想象为是一个正态分布函数，当输入 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em"></span><span class="mord mathnormal">x</span></span></span></span> 通过该函数能计算出一个“随机数”。之后将该“随机数”继续执行 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord mathnormal" style="margin-right:0.1076em">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 计算，又能得到一个新的“随机数”。然后无限套娃：</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mstyle mathsize="1.728em"><mi>f</mi><mo stretchy="false">(</mo></mstyle><mstyle mathsize="1.44em"><mi>f</mi><mo stretchy="false">(</mo></mstyle><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mstyle mathsize="1.44em"><mo stretchy="false">)</mo></mstyle><mstyle mathsize="1.728em"><mo stretchy="false">)</mo></mstyle></mrow><annotation encoding="application/x-tex">{\LARGE f(} {\Large f(} f(x){\Large )} {\LARGE )}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.728em;vertical-align:-0.432em"></span><span class="mord"><span class="mord mathnormal sizing reset-size6 size9" style="margin-right:0.1076em">f</span><span class="mopen sizing reset-size6 size9">(</span></span><span class="mord"><span class="mord mathnormal sizing reset-size6 size8" style="margin-right:0.1076em">f</span><span class="mopen sizing reset-size6 size8">(</span></span><span class="mord mathnormal" style="margin-right:0.1076em">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mord"><span class="mclose sizing reset-size6 size8">)</span></span><span class="mord"><span class="mclose sizing reset-size6 size9">)</span></span></span></span></span></span>
<p>这就是通过算法（数学公式）生成伪随机数的基本原理，每次计算的结果都是一个随机数，每一个随机数又是下一个随机数的输入值（也就是 seed）。只不过为了保证数字平均分布，实现的数学公式计算过程更加复杂而已。</p>
<p>到这里也能看出使用算法生成的的特点：<u>只要初始值相同，后续计算出来的序列就完全相同，也就是说伪随机数具有可预测（可复现）性（其中初始值就是 random 库中的 seed，即种子）</u>。</p>
<p>实际在使用时，为了让计算的序列表现的像“真随机”一样，在设置 seed 时都很有讲究。因为<u>伪随机数算法本质就是确定性算法，所以想让结果不确定就需要尽可能的保证 seed 不容易被预测</u>。常见的做法是选择当前系统的毫秒级（或微秒级）时间作为随机数的 seed，有些程序可能会使用进程ID作为 seed。</p>
<div style="text-align:center"><img src="https://media.ituknown.org/blog-media/PRNG/PRNG_f(x)_sketch.jpeg" style="width:95%" alt="PRNG_f(x)_sketch.jpeg"></div>
<p>另外，伪随机数生成器的可复现性在游戏和科研领域特别重要。比如游戏中除了角色之外就是 NPC，而这个 NPC 就是通过伪随机数生成的。在玩游戏时你会发现，特定的关卡不管重开多少次，NPC 出现的时间、场景以及动作总是固定的。作为玩家，可以根据游戏场景出专属攻略。如果游戏出现 bug，作为开发者也可以通过相同的 seed 复现场景解决 bug。</p>
<details open="" class="details_unQd alert alert--info details_J7LK" data-collapsed="false"><summary>为什么有些 random 库不需要设置 seed？</summary><div><div class="collapsibleContent_MGAI"><p>比如 Python 获取随机数 <code>random.random()</code>，在没有设置 Seed 的情况下依然得到了不同的随机数，这是为什么？</p><p>这是因为标准库帮开发者处理了，它内部会自动使用当前系统时间（精确到微秒或纳秒）作为默认 Seed。这样每次运行程序的时间几乎不可能完全相同，看起来像是真正的随机。不过如果出现bug了，也无法复现运行结果~</p></div></div></details>]]></content:encoded>
            <category>加密</category>
        </item>
        <item>
            <title><![CDATA[Cache Line 真伪共享以及对性能的影响]]></title>
            <link>https://ituknown.github.io/blog/Cache-Line-真伪共享以及对性能的影响/</link>
            <guid>https://ituknown.github.io/blog/Cache-Line-真伪共享以及对性能的影响/</guid>
            <pubDate>Tue, 30 Dec 2025 21:36:00 GMT</pubDate>
            <description><![CDATA[缓存行]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="缓存行">缓存行<a href="https://ituknown.github.io/blog/Cache-Line-%E7%9C%9F%E4%BC%AA%E5%85%B1%E4%BA%AB%E4%BB%A5%E5%8F%8A%E5%AF%B9%E6%80%A7%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D/#%E7%BC%93%E5%AD%98%E8%A1%8C" class="hash-link" aria-label="缓存行的直接链接" title="缓存行的直接链接" translate="no">​</a></h2>
<p>在多核编程中，真共享（True Sharing）和伪共享（False Sharing）是影响并发性能的两个核心概念，它们都与 CPU 数据交换的最小单位——缓存行（Cache Line）密切相关。</p>
<p>CPU 从主内存（DRAM）读取数据（到 CPU 缓存）不是按单个字节或变量读取，而是以“块”为单位加载，这个块就是 Cache Line。Cache Line 大小主要由 CPU 架构决定， 现代主流（Intel/AMD 处理器）的 CPU 架构（x86_64/ARM64）多为 ‌64 字节（<u>所以接下来都以 64 字节为例说明</u>）。</p>
<p>当 CPU 需要从主内存读取数据时，它不会只读取单个字节或单个字（word），而是一次性读取 Cache Line 大小到 CPU 缓存中。这表示即使你只需要一个 4 字节的整数（int32），CPU 也会把其相邻的 60 字节一并加载到缓存中。</p>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Note</div><div class="admonitionContent_Q31J"><p>决定 Cache Line 大小的是 CPU 架构，不是操作系统（OS）位数，这两者没有任何关联关系。Cache Line 大小是硬件（CPU 缓存）固定的，OS 位数只影响地址空间和指针大小。</p><p>在 Linux 上可以使用下面的命令查看 Cache Line 大小：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">getconf LEVEL1_DCACHE_LINESIZE</span><br></div></code></pre></div></div><p>示例：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">uname</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-a</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Linux debian </span><span class="token number" style="color:#36acaa">6.1</span><span class="token plain">.0-41-amd64 </span><span class="token comment" style="color:#999988;font-style:italic">#1 SMP PREEMPT_DYNAMIC Debian 6.1.158-1 (2025-11-09) x86_64 GNU/Linux</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ getconf LEVEL1_DCACHE_LINESIZE</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">64</span><br></div></code></pre></div></div></div></div>
<p>比如有如下结构体：</p>
<div class="language-rust codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-rust codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Data</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 8 字节</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 8 字节</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>因为 CPU 每次读取一“行”数据（64 字节），编译器并不保证结构体中的字段在内存中连续性，但如果 a 和 b 在内存中是连续的（或距离很近），那么在读取 a 时，b 极大概率会被同时加载进 CPU Cache Line 中：</p>
<div style="text-align:center"><img src="https://media.ituknown.org/blog-media/CpuCacheLine/CpuLoadCacheLine.png" style="width:80%" alt="CpuLoadCacheLine.png"></div>
<p>一次将两个数据都加载到同一个 CPU Cache Line 中，这带来一个好处：当需要访问 b 时不需要再次访问主内存，减少了 CPU 缓存与主内存的数据交换频率，可提高性能。</p>
<p>但如果是在多线程情况下，可能就是性能杀手。由于 a 和 b 都在同一“行”，分别被加载到 CPU 的不同核心：</p>
<ul>
<li class="">当核心 1 修改 a，由于缓存一致性协议（MESI），一个核心修改了该变量，必须通知其他核心将对应的缓存行失效</li>
<li class="">所以当其他核心读取 b 时，会发现该 Cache Line 已失效（即使 b 的值根本没变），就会重新从主内存中加载该“行”数据</li>
<li class="">反过来，当其他核心修改 b。由于缓存一致性（MESI），同样会导致核心 1 的 Cache Line 失效。如果后续核心 1 不需要访问 a 还好，一旦需要读写就需要重新从主内存中加载最新数据</li>
</ul>
<p>在多线程场景下，这种频繁的 MESI 通信就是拖慢程序性能的罪魁祸首（如下图）</p>
<div style="text-align:center"><img src="https://media.ituknown.org/blog-media/CpuCacheLine/CacheLineMESI.png" style="width:70%" alt="CacheLineMESI.png"></div>
<p>这就是真伪共享的问题。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="真共享">真共享<a href="https://ituknown.github.io/blog/Cache-Line-%E7%9C%9F%E4%BC%AA%E5%85%B1%E4%BA%AB%E4%BB%A5%E5%8F%8A%E5%AF%B9%E6%80%A7%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D/#%E7%9C%9F%E5%85%B1%E4%BA%AB" class="hash-link" aria-label="真共享的直接链接" title="真共享的直接链接" translate="no">​</a></h2>
<p>真共享是多个线程（核心）访问和修改同一个变量。</p>
<p>为了保证缓存一致性，缓存一致性协议（MESI 协议）会强制一个核心修改后，其他核心的缓存行失效，需要重新从内存或上级缓存加载。频繁的缓存同步，虽然逻辑上没错，但性能会大幅下降。</p>
<p>这是不可避免的，属于程序逻辑上的真实数据共享，只能通过减少共享或使用锁/无锁机制缓解。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="伪共享">伪共享<a href="https://ituknown.github.io/blog/Cache-Line-%E7%9C%9F%E4%BC%AA%E5%85%B1%E4%BA%AB%E4%BB%A5%E5%8F%8A%E5%AF%B9%E6%80%A7%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D/#%E4%BC%AA%E5%85%B1%E4%BA%AB" class="hash-link" aria-label="伪共享的直接链接" title="伪共享的直接链接" translate="no">​</a></h2>
<p>伪共享是多个线程（核心）访问不同的变量，但这些变量<u>恰好</u>位于同一个缓存行内。其中一个线程修改自己的变量，会导致整个缓存行在其他核心上失效（MESI 协议），即使其他线程访问的变量并未真正改变。</p>
<p>伪共享被称为“缓存行乒乓”（Cache Line Ping-Pong），会导致 CPU 性能大幅下降，甚至比单线程还慢。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="如何解决伪共享">如何解决伪共享<a href="https://ituknown.github.io/blog/Cache-Line-%E7%9C%9F%E4%BC%AA%E5%85%B1%E4%BA%AB%E4%BB%A5%E5%8F%8A%E5%AF%B9%E6%80%A7%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D/#%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%E4%BC%AA%E5%85%B1%E4%BA%AB" class="hash-link" aria-label="如何解决伪共享的直接链接" title="如何解决伪共享的直接链接" translate="no">​</a></h2>
<p>解决伪共享的核心思路是：空间换时间。也就是通过填充，让不同的变量位于不同的缓存行。</p>
<p>如下 Rust 结构体：</p>
<div class="language-rust codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-rust codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/// 存在伪共享</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">FalseSharing</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 8byte</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 8byte</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>编译器虽然不保证属性 a 和 b 在内存中的连续性，但是当 CPU 加载 a 时，b 极大概率也会被加载到同一缓存行中（因为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>+</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">a + b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:0.6944em"></span><span class="mord mathnormal">b</span></span></span></span> 占用的总字节数只有 16，远远小于缓存行 64 字节）。</p>
<p>为了保证 a 和 b 不被加载到同一 Cache Line，通常的做法是在 a 之后填充（Padding）一下无意义的字节，使其独占一个缓存行，这样 b 如果被加载，也是在新的 Cache Line 中。</p>
<p>Rust 中最直接的方式是使用 <code>#[repr(align(64))]</code> 强制一个结构体或其中的字段按照 64 字节内存对齐：</p>
<div class="language-rust codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-rust codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/// 自动填充 64 字节，消除伪共享</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[repr(align(64))]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Aligned</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">TureSharing</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Aligned</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">AtomicU64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Aligned</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">AtomicU64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_Q31J"><p>如果需要编写具有平台移植性的代码，推荐使用 <a href="https://crates.io/crates/crossbeam-utils" target="_blank" rel="noopener noreferrer" class="">crossbeam-utils</a> 库提供的 <code>CachePadded&lt;T&gt;</code> 包装类，它会自动根据目标平台的特性增加填充（CachePadded 会自动判断是 64 字节还是 128 字节）。</p></div></div>
<p>效果如下：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CpuCacheLine/CacheLineSharing.png" alt="CacheLineSharing.png" class="img_o99Q"></p>
<details class="details_unQd alert alert--info details_J7LK" data-collapsed="true"><summary>一个不专业的 Rust 测试例子</summary><div><div class="collapsibleContent_MGAI"><p>硬件信息：</p><div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">Microsoft Windows 10 Professional</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">13th Gen Intel(R) Core(TM) i7-13700KF</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">rustc 1.92.0 (ded5c06cf 2025-12-08)</span><br></div></code></pre></div></div><p>输出结果：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token assign-left variable" style="color:#36acaa">RUSTFLAGS</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"-C target-cpu=native"</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cargo</span><span class="token plain"> run </span><span class="token parameter variable" style="color:#36acaa">--release</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">伪共享地址差: 0x6000037a51b0 vs 0x6000037a51b8 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8</span><span class="token plain"> 字节</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">伪共享 </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">False Sharing</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">: </span><span class="token number" style="color:#36acaa">4</span><span class="token plain">.414882127s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">对齐后地址差: 0x7f91448040c0 vs 0x7f9144804100 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">64</span><span class="token plain">字节</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">非伪共享 </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">No False Sharing</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">: </span><span class="token number" style="color:#36acaa">502</span><span class="token plain">.600092ms</span><br></div></code></pre></div></div><p>可以看到，性能夸张的提升了 88.62%：</p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mfrac><mrow><msub><mi>T</mi><mrow><mn>4.414882127</mn><mi>s</mi></mrow></msub><mo>−</mo><msub><mi>T</mi><mrow><mn>502.600092</mn><mi>m</mi><mi>s</mi></mrow></msub></mrow><msub><mi>T</mi><mrow><mn>4.414882127</mn><mi>s</mi></mrow></msub></mfrac><mo>×</mo><mn>100</mn><mi mathvariant="normal">%</mi><mo>≈</mo><mn>88.62</mn><mi mathvariant="normal">%</mi></mrow><annotation encoding="application/x-tex">\frac{T_{4.414882127s} - T_{502.600092ms}}{T_{4.414882127s}} \times 100\% \approx  88.62\%</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.1963em;vertical-align:-0.836em"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em"><span style="top:-2.314em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4.414882127</span><span class="mord mathnormal mtight">s</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em"><span class="pstrut" style="height:3em"></span><span class="frac-line" style="border-bottom-width:0.04em"></span></span><span style="top:-3.677em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4.414882127</span><span class="mord mathnormal mtight">s</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">502.600092</span><span class="mord mathnormal mtight">m</span><span class="mord mathnormal mtight">s</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em"></span><span class="mord">100%</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em"></span><span class="mord">88.62%</span></span></span></span></span><p>当然这只是极端测试用例，不能代表真实业务场景。下面是用例代码：</p><div class="language-rust codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-rust codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">sync</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Arc</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">sync</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">atomic</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Ordering</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token plain">thread</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token namespace" style="opacity:0.7">time</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token class-name">Instant</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// 存在伪共享</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">FalseSharing</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/// 使用对其消除伪共享</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token attribute attr-name" style="color:#00a4db">#[repr(align(64))]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Aligned</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">T</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">TureSharing</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Aligned</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">AtomicU64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Aligned</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">AtomicU64</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">run_benchmark</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">F</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">str</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Arc</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">F</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">where</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">F</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Fn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Send</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Sync</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token lifetime-annotation symbol" style="color:#36acaa">'static</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> start </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Instant</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> threads </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Vec</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> func </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Arc</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">clone</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">f</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        threads</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">push</span><span class="token punctuation" style="color:#393A34">(</span><span class="token namespace" style="opacity:0.7">thread</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">spawn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">move</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> _ </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">100_000_000</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">func</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> t </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> threads </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}: {:?}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> start</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">elapsed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> fs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Arc</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">FalseSharing</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"伪共享地址差: {:p} vs {:p} = {} 字节"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">fs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">fs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">b</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">fs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">b </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> _ </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">fs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">a </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> _ </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">run_benchmark</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"伪共享 (False Sharing)"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Arc</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">move</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">i</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 强制 CPU 执行更严格的缓存一致性同步，放大伪共享延迟</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                fs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fetch_add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Ordering</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">SeqCst</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                fs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">b</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fetch_add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Ordering</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">SeqCst</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> ts </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Arc</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TureSharing</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Aligned</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Aligned</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AtomicU64</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"\n对齐后地址差: {:p} vs {:p} = {}字节"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">ts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">ts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">b</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">ts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">b </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> _ </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">ts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">a </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> _ </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">usize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">run_benchmark</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"非伪共享 (No False Sharing)"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Arc</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">move</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token closure-params">i</span><span class="token closure-params closure-punctuation punctuation" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                ts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">a</span><span class="token number" style="color:#36acaa">.0</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fetch_add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Ordering</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">SeqCst</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                ts</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">b</span><span class="token number" style="color:#36acaa">.0</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fetch_add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Ordering</span><span class="token punctuation" style="color:#393A34">::</span><span class="token class-name">SeqCst</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div><p>开启最激进的优化指令：</p><div class="language-toml codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_329y">Cargo.toml</div><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-toml codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">[profile.release]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">opt-level = 3          # 确保是最高等级优化</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lto = true             # 开启链接时优化 (Link Time Optimization)，跨模块优化</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">codegen-units = 1      # 限制并行编译单元，允许编译器进行更全局的优化</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">panic = 'abort'        # 去掉异常处理栈追踪，减小二进制体积并提速</span><br></div></code></pre></div></div></div></div></details>
<div class="theme-admonition theme-admonition-danger admonition_fnQa alert alert--danger"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>什么时候需要考虑伪共享问题？</div><div class="admonitionContent_Q31J"><p>除非你的业务场景是「高并发写 + IO 性能已经到瓶颈 + CPU 占用很高」，才真正需要考虑 Cache Line 的伪共享问题。</p><p>最典型的就是高并发场景下的计数器（状态位）：</p><div class="language-rust codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-rust codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">struct</span><span class="token plain"> </span><span class="token type-definition class-name">Stats</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    count_a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    count_b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div><p>如果只是些Web接口、DB查询、MQ通信、文件操作以及网络IO之类的业务，完全不需要考虑伪共享问题。对于这些业务，你需要优化的是IO延迟问题，Cache Line 再怎么抖，也不及IO延迟的万分之一。</p></div></div>]]></content:encoded>
            <category>性能</category>
        </item>
        <item>
            <title><![CDATA[使用 CloudFlare Pages 快速搭建网站]]></title>
            <link>https://ituknown.github.io/blog/使用-CloudFlare-Pages-快速搭建网站/</link>
            <guid>https://ituknown.github.io/blog/使用-CloudFlare-Pages-快速搭建网站/</guid>
            <pubDate>Thu, 27 Nov 2025 13:28:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="前言">前言<a href="https://ituknown.github.io/blog/%E4%BD%BF%E7%94%A8-CloudFlare-Pages-%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA%E7%BD%91%E7%AB%99/#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接链接" title="前言的直接链接" translate="no">​</a></h2>
<p>对于个人用户来说，建站最快方式就是使用赛博菩萨（<a href="https://cloudflare.com/" target="_blank" rel="noopener noreferrer" class="">CloudFlare</a>）提供的 <a href="https://pages.cloudflare.com/" target="_blank" rel="noopener noreferrer" class="">Pages</a>，只需要在界面简单点几下，就能快速的部署一个静态网站，而且每天提供 10W 次免费请求额度，对个人用户真就是“白嫖”。</p>
<p>加上其强大的 DNS，在全球任意一个地方基本上都能实现毫秒级访问。另外如果你有自己的专属域名，配合 <a href="https://pages.cloudflare.com/" target="_blank" rel="noopener noreferrer" class="">CloudFlare Pages</a> 简直不要太爽。</p>
<p>对于 IT 开发者来说，CloudFlare Pages 最常用的方式是搭建博客、知识文档一类的站点。接下来就以 <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> 为例，从头到尾的快速演示如何使用 CloudFlare Pages 搭建自己的知识网站。</p>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>小提示</div><div class="admonitionContent_Q31J"><p><a href="https://vitepress.dev/" target="_blank" rel="noopener noreferrer" class="">VitePress</a>、<a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> 和 <a href="https://gohugo.com.cn/" target="_blank" rel="noopener noreferrer" class="">HUGO</a> 都是主流的静态站点生成器，也都特别适合文档、博客类网站使用。可根据自己的喜好自行选择，这里我以 <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> 为例做说明，其他静态站点生成器也是同样操作步骤。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="创建-docusaurus-文档">创建 docusaurus 文档<a href="https://ituknown.github.io/blog/%E4%BD%BF%E7%94%A8-CloudFlare-Pages-%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA%E7%BD%91%E7%AB%99/#%E5%88%9B%E5%BB%BA-docusaurus-%E6%96%87%E6%A1%A3" class="hash-link" aria-label="创建 docusaurus 文档的直接链接" title="创建 docusaurus 文档的直接链接" translate="no">​</a></h2>
<p>首先我假设你已经安装过 <a href="https://nodejs.org/" target="_blank" rel="noopener noreferrer" class="">Node.js</a>，知道如何使用 npm 和 yarn。下面是我的 Node.js 信息：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">node</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">v24.11.1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">11.6</span><span class="token plain">.2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">yarn</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">1.22</span><span class="token plain">.22</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>小提示</div><div class="admonitionContent_Q31J"><p>yarn 和 npm 都是包管理工具，在使用体验没有任何区别。npm 是 Node.js 内置的包管理工具，无需额外安装。</p><p>虽然 Node.js 没有内置 yarn，但如果你想使用 yarn 也很简单，也不需要额外安装。只需要使用 Node.js 内置的 corepack 简单的执行两个命令就完事了：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># 启用 yarn</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ corepack </span><span class="token builtin class-name">enable</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">yarn</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 验证(实际是自动帮你下载安装)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">yarn</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-v</span><br></div></code></pre></div></div></div></div>
<p>首先使用 docusaurus 脚手架创建一个项目，命令如下：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">npx create-docusaurus@latest website classic </span><span class="token parameter variable" style="color:#36acaa">--typescript</span><br></div></code></pre></div></div>
<p>其中 <code>website</code> 是创建的项目名，可以随意指定。 <code>--typescript</code> 指定项目使用 typescript，如果不指定的话默认使用 javascript，这个随意即可。</p>
<p>命令执行完成后，你会得到类似如下的项目结构：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token builtin class-name">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── README.md</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── blog</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── docs</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── node_modules</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── docusaurus.config.ts</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── package-lock.json</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── package.json</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── sidebars.ts</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── src</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── static</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└── tsconfig.json</span><br></div></code></pre></div></div>
<p>运行 <code>npm run start</code> 等待编译完成，在浏览器中打开 <a href="http://localhost:3000/" target="_blank" rel="noopener noreferrer" class="">http://localhost:3000/</a> 你会看到如下界面：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_0_create_docusaurus.png" alt="step_0_create_docusaurus" class="img_o99Q"></p>
<p>现在一个简单的静态文档就生成好了~</p>
<p>接下来，关闭终端重新输入 <code>npm run build</code> 。等编译完成，就会发现项目根目录多了一个 build 文件夹，这个文件夹中的内容就是静态站点的全部信息，也是部署静态站点的内容。</p>
<p>之后将该项目上传到 <a href="https://github.com/" target="_blank" rel="noopener noreferrer" class="">Github</a> 或 <a href="https://gitlab.com/" target="_blank" rel="noopener noreferrer" class="">GitLab</a>，就可以到 <a href="https://pages.cloudflare.com/" target="_blank" rel="noopener noreferrer" class="">CloudFlare Pages</a> 部署静态站点了。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="CloudFlare-Pages-部署静态站点">CloudFlare Pages 部署静态站点<a href="https://ituknown.github.io/blog/%E4%BD%BF%E7%94%A8-CloudFlare-Pages-%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA%E7%BD%91%E7%AB%99/#CloudFlare-Pages-%E9%83%A8%E7%BD%B2%E9%9D%99%E6%80%81%E7%AB%99%E7%82%B9" class="hash-link" aria-label="CloudFlare Pages 部署静态站点的直接链接" title="CloudFlare Pages 部署静态站点的直接链接" translate="no">​</a></h2>
<p>进入 CloudFlare Pages，你会看到如下界面：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_1_choose_pages.png" alt="step_1_choose_pages" class="img_o99Q"></p>
<p>不要直接点击右侧的 <strong>Create application</strong> 按钮，该功能创建的是 Workers，并不是我们部署静态站点使用的 Pages。正确的姿势是依此点击 <strong>Add</strong> » <strong>Pages</strong>，接下来就会进入下图这个界面：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_2_import_git.png" alt="step_2_import_git" class="img_o99Q"></p>
<p>此时有两个选择，直接上传静态文档或者从 Git 导入构建。如果你想直接上传，只需要将前面生成的 build 文件夹上传即可。不过这种每次做修改时都需要手动执行一次上传，简直不要太麻烦。</p>
<p>我们需要的效果是，每次 Git 分支有新的提交就自动触发构建。所以，这里应该选择第一种 <strong>Import an existing Git repository</strong>。</p>
<p>接下来就需要关联自己的 Github 或 GitLab，根据自己上传的平台关联即可，关联成功后选择刚上传的项目：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_3_select_repository.png" alt="step_3_select_repository" class="img_o99Q"></p>
<p>继续下一步，开始设置 Pages 项目名和要构建的分支。项目名随意即可，分支的话推荐使用主分支：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_4_1_project_name.png" alt="step_4_1_project_name" class="img_o99Q"></p>
<p>继续向下，开始设置项目框架和构建命令（如下图）。CloudFlare 已经内置了所有主流的静态网站框架，你能想到的这里都有。我使用的是 <a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a> 所以我就选择该框架：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_4_2_build_command.png" alt="step_4_2_build_command" class="img_o99Q"></p>
<p>构建命令使用 <code>npm run build</code> 或 <code>yarn run build</code> ，实际上 CloudFlare Pages 已经根据项目框架自动帮你填充了。输出目录就指定 build 即可，这是 Node.js 默认的输出目录。</p>
<p>另外，最后别忘记设置一下 Node.js 的 Version 环境变量。CloudFlare Pages 默认使用的版本可能与你项目不一致，为了防止潜在的问题，建议设置下你构建项目时使用的版本。</p>
<p>所有设置都填写完成后，就可以点击保存部署了：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_5_deploy_log.png" alt="step_5_deploy_log" class="img_o99Q"></p>
<p>从构建日志中就可以看到使用了我们环境变量中配置的 Node.js 版本，构建完成后也就表示部署完成了。现在你就可以使用 CloudFlare 为你提供的域名访问你的静态站点了。</p>
<p>如果你有自己的域名，并想为该 Pages 设置自己的域名，可以继续点击下方的 <strong>Add custom domain</strong>：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_6_add_custom_domain.png" alt="step_6_add_custom_domain" class="img_o99Q"></p>
<p>直接点击 <strong>Set up a custom domain</strong>：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_7_set_up_a_custom_domain.png" alt="step_7_set_up_a_custom_domain" class="img_o99Q"></p>
<p>接下来就可以填写自己的域名了：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_8_input_custom_domain.png" alt="step_8_input_custom_domain" class="img_o99Q"></p>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>小提示</div><div class="admonitionContent_Q31J"><p>自定义域名可以是任意的，不一定非要设置一级域名，如果你的一级域名已经被占用设置二级域名也是可以正常访问的。比如我这里设置的是二级域名 <code>example.ituknown.org</code> 。</p></div></div>
<p>域名填写完成后还有一个激活步骤，点击激活即可：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_9_activate_domain.png" alt="step_9_activate_domain" class="img_o99Q"></p>
<details open="" class="details_unQd alert alert--info details_J7LK" data-collapsed="false"><summary>域名验证？</summary><div><div class="collapsibleContent_MGAI"><p>当自定义域名初始化完成之后，会进入 Verifying 阶段。如果你的域名是在 CloudFlare 上注册的（或已迁移到 CloudFlare），到这一步什么都不需要操作，CloudFlare 会自定执行验证。</p><p>但如果你的自定义域名还未迁移到 CloudFlare，此时需要按照下面的提示进入到你的域名服务商平台的管理页面，在域名 DNS 解析中添加一条 CNAME 记录。填写完成之后点击 <strong>Check DNS Records</strong>，如果信息无误，就完成激活验证了。</p><p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_10_domain_verifying.png" alt="step_10_domain_verifying" class="img_o99Q"></p></div></div></details>
<p>当激活成功之后就可以使用你的自定义域名访问网站了🎉🎉🎉🎉：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/CloudFlarePages/step_11_domain_activated.png" alt="step_11_domain_activated" class="img_o99Q"></p>
<p>接下来你提交到 Github 的任意变更都会触发 Pages 的自动构建，真是一劳永逸~</p>]]></content:encoded>
            <category>CloudFlare</category>
            <category>Node.js</category>
        </item>
        <item>
            <title><![CDATA[分辨率和屏幕尺寸]]></title>
            <link>https://ituknown.github.io/blog/分辨率和屏幕尺寸/</link>
            <guid>https://ituknown.github.io/blog/分辨率和屏幕尺寸/</guid>
            <pubDate>Sat, 12 Oct 2024 18:24:00 GMT</pubDate>
            <description><![CDATA[1. 分辨率的定义]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="1-分辨率的定义">1. 分辨率的定义<a href="https://ituknown.github.io/blog/%E5%88%86%E8%BE%A8%E7%8E%87%E5%92%8C%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8/#1-%E5%88%86%E8%BE%A8%E7%8E%87%E7%9A%84%E5%AE%9A%E4%B9%89" class="hash-link" aria-label="1. 分辨率的定义的直接链接" title="1. 分辨率的定义的直接链接" translate="no">​</a></h2>
<p><u>分辨率指的是屏幕上显示像素的数量</u>，通常用宽 × 高表示，例如：</p>
<ul>
<li class=""><strong>2K</strong> 分辨率像素点数量为 2560×1440（约 370 万）</li>
<li class=""><strong>4K</strong> 分辨率像素点数量为 3840×2160（约 830 万）</li>
</ul>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>NOTE</div><div class="admonitionContent_Q31J"><p>分辨率仅仅表示屏幕像素点总数量，跟屏幕尺寸大小没有任何关系。</p><p>固定屏幕尺寸下，分辨率越高，像素点越多，可以表现得细节越多，在视觉体验上就会感觉“更清晰、更细腻”。</p></div></div>
<details open="" class="details_unQd alert alert--info details_J7LK" data-collapsed="false"><summary><strong>常见分辨率对比</strong></summary><div><div class="collapsibleContent_MGAI"><table><thead><tr><th style="text-align:left">名称</th><th style="text-align:left">简称</th><th style="text-align:left">分辨率（像素）</th><th style="text-align:left">总像素点（约）</th></tr></thead><tbody><tr><td style="text-align:left">Full HD</td><td style="text-align:left">1080P</td><td style="text-align:left">1920×1080</td><td style="text-align:left">210 万</td></tr><tr><td style="text-align:left">Quad HD</td><td style="text-align:left">2K/1440P</td><td style="text-align:left">2560×1440</td><td style="text-align:left">370 万</td></tr><tr><td style="text-align:left">Ultra HD</td><td style="text-align:left">4K UHD</td><td style="text-align:left">3840 × 2160</td><td style="text-align:left">830 万</td></tr><tr><td style="text-align:left">8K UHD</td><td style="text-align:left">8K</td><td style="text-align:left">7680×4320</td><td style="text-align:left">3300 万</td></tr></tbody></table></div></div></details>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="2-屏幕尺寸与像素密度">2. 屏幕尺寸与像素密度<a href="https://ituknown.github.io/blog/%E5%88%86%E8%BE%A8%E7%8E%87%E5%92%8C%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8/#2-%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8%E4%B8%8E%E5%83%8F%E7%B4%A0%E5%AF%86%E5%BA%A6" class="hash-link" aria-label="2. 屏幕尺寸与像素密度的直接链接" title="2. 屏幕尺寸与像素密度的直接链接" translate="no">​</a></h2>
<p>分辨率影响的是像素点数量，屏幕尺寸决定了显示区域的物理大小，两者集合就会影响 <strong>像素密度（PPI，Pixels Per Inch）</strong>。</p>
<p>PPI (Pixels Per Inch，每英寸像素) 是衡量屏幕像素密度的指标，它表示在一英寸的屏幕对角线上容纳的像素点数量。</p>
<details open="" class="details_unQd alert alert--info details_J7LK" data-collapsed="false"><summary><strong>换个抽象一点的方法来形容 PPI</strong></summary><div><div class="collapsibleContent_MGAI"><p>你可以将像素点想象为大豆，而屏幕就是篮子。当大豆的数量固定是，此时决定大豆浓密的因素就是篮子的大小：</p><p>篮子越小，大豆分布越稠密，对应的画面显示的细节就更多。<br>
篮子越大，大豆分布越稀疏，对应的画面显示的细节就会越少。</p></div></div></details>
<p>所以：</p>
<ul>
<li class=""><strong>小屏幕+高分辨率</strong>：像素密度高，图像更细腻。</li>
<li class=""><strong>大屏幕+低分辨率</strong>：像素密度低，可能显得不够清晰。</li>
</ul>
<p>例如：</p>
<ul>
<li class="">24英寸的屏幕如果使用 4K 分辨率，图像会非常清晰，因为 PPI 很高。</li>
<li class="">55英寸的屏幕如果使用 4K 分辨率，图像可能看起来较模糊，因为 PPI 比较低。</li>
</ul>
<p><strong>如何计算 PPI 呢？计算公式如下：</strong></p>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>PPI 计算公式</div><div class="admonitionContent_Q31J"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>P</mi><mi>P</mi><mi>I</mi><mo>=</mo><mfrac><msqrt><mrow><msup><mi>W</mi><mn>2</mn></msup><mo>+</mo><msup><mi>H</mi><mn>2</mn></msup></mrow></msqrt><mi>D</mi></mfrac></mrow><annotation encoding="application/x-tex">PPI ={ \sqrt{W^2 + H^2}\over D}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em"></span><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord mathnormal" style="margin-right:0.0785em">I</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:2.2764em;vertical-align:-0.686em"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.5904em"><span style="top:-2.314em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0278em">D</span></span></span><span style="top:-3.23em"><span class="pstrut" style="height:3em"></span><span class="frac-line" style="border-bottom-width:0.04em"></span></span><span style="top:-3.677em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9134em"><span class="svg-align" style="top:-3em"><span class="pstrut" style="height:3em"></span><span class="mord" style="padding-left:0.833em"><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em">W</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7401em"><span style="top:-2.989em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0813em">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7401em"><span style="top:-2.989em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-2.8734em"><span class="pstrut" style="height:3em"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702
c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54
c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10
s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429
c69,-144,104.5,-217.7,106.5,-221
l0 -0
c5.3,-9.3,12,-14,20,-14
H400000v40H845.2724
s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7
c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z
M834 80h400000v40h-400000z"></path></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1266em"><span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></span><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>W</mi></mrow><annotation encoding="application/x-tex">W</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em"></span><span class="mord mathnormal" style="margin-right:0.1389em">W</span></span></span></span> 是屏幕的水平像素（3840）<br>
<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em"></span><span class="mord mathnormal" style="margin-right:0.0813em">H</span></span></span></span> 是屏幕的垂直像素（2160）<br>
<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em"></span><span class="mord mathnormal" style="margin-right:0.0278em">D</span></span></span></span> 是屏幕的对角线尺寸（英寸）</p></div></div>
<p>根据这个公式，我们就很容易比较 4K 分辨率下，27 英寸和 32 英寸屏幕那个画面细节更强：</p>
<details open="" class="details_unQd alert alert--info details_J7LK" data-collapsed="false"><summary>4K 27英寸屏和32英寸屏 PPI 比较</summary><div><div class="collapsibleContent_MGAI"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.16em" columnalign="left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>P</mi><mi>P</mi><msub><mi>I</mi><mn>27</mn></msub><mo>=</mo><mfrac><msqrt><mrow><msup><mn>3840</mn><mn>2</mn></msup><mo>+</mo><msup><mn>2160</mn><mn>2</mn></msup></mrow></msqrt><mn>27</mn></mfrac><mo>≅</mo><mn>163</mn><mi>P</mi><mi>P</mi><mi>I</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>P</mi><mi>P</mi><msub><mi>I</mi><mn>32</mn></msub><mo>=</mo><mfrac><msqrt><mrow><msup><mn>3840</mn><mn>2</mn></msup><mo>+</mo><msup><mn>2160</mn><mn>2</mn></msup></mrow></msqrt><mn>32</mn></mfrac><mo>≅</mo><mn>138</mn><mi>P</mi><mi>P</mi><mi>I</mi></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{array}{l}
  PPI_{27} ={ \sqrt{3840^2 + 2160^2}\over 27} \cong 163PPI \\
  \\
  PPI_{32} ={ \sqrt{3840^2 + 2160^2}\over 32} \cong 138PPI \\
\end{array}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.999em;vertical-align:-1.7495em"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.2495em"><span style="top:-4.2495em"><span class="pstrut" style="height:3.0395em"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0785em">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">27</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0395em"><span style="top:-2.655em"><span class="pstrut" style="height:3em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">27</span></span></span></span><span style="top:-3.23em"><span class="pstrut" style="height:3em"></span><span class="frac-line" style="border-bottom-width:0.04em"></span></span><span style="top:-3.394em"><span class="pstrut" style="height:3em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord sqrt mtight"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9221em"><span class="svg-align" style="top:-3em"><span class="pstrut" style="height:3em"></span><span class="mord mtight" style="padding-left:0.833em"><span class="mord mtight">384</span><span class="mord mtight"><span class="mord mtight">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em"><span style="top:-2.786em;margin-right:0.0714em"><span class="pstrut" style="height:2.5em"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight">216</span><span class="mord mtight"><span class="mord mtight">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em"><span style="top:-2.786em;margin-right:0.0714em"><span class="pstrut" style="height:2.5em"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-2.8821em"><span class="pstrut" style="height:3em"></span><span class="hide-tail mtight" style="min-width:0.853em;height:1.08em"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702
c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54
c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10
s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429
c69,-144,104.5,-217.7,106.5,-221
l0 -0
c5.3,-9.3,12,-14,20,-14
H400000v40H845.2724
s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7
c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z
M834 80h400000v40h-400000z"></path></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1179em"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">≅</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mord">163</span><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord mathnormal" style="margin-right:0.0785em">I</span></span></span><span style="top:-3.0495em"><span class="pstrut" style="height:3.0395em"></span><span class="mord"></span></span><span style="top:-1.65em"><span class="pstrut" style="height:3.0395em"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0785em">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">32</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0395em"><span style="top:-2.655em"><span class="pstrut" style="height:3em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">32</span></span></span></span><span style="top:-3.23em"><span class="pstrut" style="height:3em"></span><span class="frac-line" style="border-bottom-width:0.04em"></span></span><span style="top:-3.394em"><span class="pstrut" style="height:3em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord sqrt mtight"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9221em"><span class="svg-align" style="top:-3em"><span class="pstrut" style="height:3em"></span><span class="mord mtight" style="padding-left:0.833em"><span class="mord mtight">384</span><span class="mord mtight"><span class="mord mtight">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em"><span style="top:-2.786em;margin-right:0.0714em"><span class="pstrut" style="height:2.5em"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight">216</span><span class="mord mtight"><span class="mord mtight">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em"><span style="top:-2.786em;margin-right:0.0714em"><span class="pstrut" style="height:2.5em"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-2.8821em"><span class="pstrut" style="height:3em"></span><span class="hide-tail mtight" style="min-width:0.853em;height:1.08em"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702
c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54
c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10
s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429
c69,-144,104.5,-217.7,106.5,-221
l0 -0
c5.3,-9.3,12,-14,20,-14
H400000v40H845.2724
s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7
c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z
M834 80h400000v40h-400000z"></path></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1179em"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">≅</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mord">138</span><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord mathnormal" style="margin-right:0.1389em">P</span><span class="mord mathnormal" style="margin-right:0.0785em">I</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.7495em"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em"></span></span></span></span></span></span></span><p>由此可见，27寸屏幕的像素密度更高，画面的细腻程度会优于32寸屏幕。</p></div></div></details>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="3-屏幕尺寸对分辨率的实际要求">3. 屏幕尺寸对分辨率的实际要求<a href="https://ituknown.github.io/blog/%E5%88%86%E8%BE%A8%E7%8E%87%E5%92%8C%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8/#3-%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8%E5%AF%B9%E5%88%86%E8%BE%A8%E7%8E%87%E7%9A%84%E5%AE%9E%E9%99%85%E8%A6%81%E6%B1%82" class="hash-link" aria-label="3. 屏幕尺寸对分辨率的实际要求的直接链接" title="3. 屏幕尺寸对分辨率的实际要求的直接链接" translate="no">​</a></h2>
<p>屏幕尺寸越大，为了保持较高的清晰度（PPI），需要更高的分辨率。以下是一些推荐：</p>
<ul>
<li class=""><strong>小于24英寸</strong>：1080p 或 2K 分辨率通常足够。</li>
<li class=""><strong>24-32英寸</strong>：2K 分辨率适中，4K 分辨率提供更高细节。</li>
<li class=""><strong>超过32英寸</strong>：建议至少 4K 分辨率，尤其是近距离使用（如电脑显示器）。</li>
</ul>
<p>对于电视等远距离使用的大屏幕，4K 在 50英寸及以上会更有意义。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="4-用户体验与实际需求">4. 用户体验与实际需求<a href="https://ituknown.github.io/blog/%E5%88%86%E8%BE%A8%E7%8E%87%E5%92%8C%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8/#4-%E7%94%A8%E6%88%B7%E4%BD%93%E9%AA%8C%E4%B8%8E%E5%AE%9E%E9%99%85%E9%9C%80%E6%B1%82" class="hash-link" aria-label="4. 用户体验与实际需求的直接链接" title="4. 用户体验与实际需求的直接链接" translate="no">​</a></h2>
<ul>
<li class=""><strong>近距离使用（如电脑显示器）</strong>：高分辨率能提升细节，减少颗粒感。</li>
<li class=""><strong>远距离观看（如电视）</strong>：屏幕尺寸的物理限制让高分辨率的提升不如近距离明显（例如在3米外观看，4K 和 1080p 的差别可能不大）。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="5-屏幕尺寸与分辨率的权衡">5. 屏幕尺寸与分辨率的权衡<a href="https://ituknown.github.io/blog/%E5%88%86%E8%BE%A8%E7%8E%87%E5%92%8C%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8/#5-%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8%E4%B8%8E%E5%88%86%E8%BE%A8%E7%8E%87%E7%9A%84%E6%9D%83%E8%A1%A1" class="hash-link" aria-label="5. 屏幕尺寸与分辨率的权衡的直接链接" title="5. 屏幕尺寸与分辨率的权衡的直接链接" translate="no">​</a></h2>
<p>购买屏幕时，不仅要看分辨率，还要考虑：</p>
<ul>
<li class=""><strong>视距（观看距离）</strong>：近距离需要更高分辨率。</li>
<li class=""><strong>预算</strong>：高分辨率通常更贵。</li>
<li class=""><strong>硬件性能</strong>：更高分辨率需要更强大的显卡支持，特别是玩游戏时。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="6-总结">6. 总结<a href="https://ituknown.github.io/blog/%E5%88%86%E8%BE%A8%E7%8E%87%E5%92%8C%E5%B1%8F%E5%B9%95%E5%B0%BA%E5%AF%B8/#6-%E6%80%BB%E7%BB%93" class="hash-link" aria-label="6. 总结的直接链接" title="6. 总结的直接链接" translate="no">​</a></h2>
<p>分辨率和屏幕尺寸没有硬性要求，但它们影响显示效果。较大的屏幕通常需要更高的分辨率以保持良好的清晰度。购买时需综合屏幕尺寸、观看距离、使用需求和硬件性能做出选择。</p>]]></content:encoded>
            <category>软硬件</category>
        </item>
        <item>
            <title><![CDATA[Ventoy U盘启动工具]]></title>
            <link>https://ituknown.github.io/blog/Ventoy-U盘启动工具/</link>
            <guid>https://ituknown.github.io/blog/Ventoy-U盘启动工具/</guid>
            <pubDate>Sun, 24 Mar 2024 15:27:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="前言">前言<a href="https://ituknown.github.io/blog/Ventoy-U%E7%9B%98%E5%90%AF%E5%8A%A8%E5%B7%A5%E5%85%B7/#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接链接" title="前言的直接链接" translate="no">​</a></h2>
<p>Ventoy 是一个开源的多功能 U 盘启动工具，用于创建可引导的 USB 驱动器。与以往的刻录工具不同（一个U盘只能制作一个系统），它可以在一个U盘上存储多个操作系统安装文件、Live CD 镜像和其他实用工具，而无需重复格式化驱动器或重新制作引导镜像。</p>
<p><strong>最重要的是使用起来特别简单。</strong></p>
<p>首先在官网（<a href="https://www.ventoy.net/cn/download.html" target="_blank" rel="noopener noreferrer" class="">https://www.ventoy.net/cn/download.html</a>）或者 GitHub 发布页（<a href="https://github.com/ventoy/Ventoy/releases" target="_blank" rel="noopener noreferrer" class="">https://github.com/ventoy/Ventoy/releases</a>）进行下载 Ventoy。</p>
<p>下载完成后并解压，进入文件夹后会看到类似如下的文件结构：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── FOR_X64_ARM.txt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── Ventoy2Disk.exe</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── VentoyPlugson.exe</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── VentoyVlnk.exe</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── altexe</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│&nbsp;&nbsp; ├── Ventoy2Disk_ARM.exe</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│&nbsp;&nbsp; ├── Ventoy2Disk_ARM64.exe</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│&nbsp;&nbsp; ├── Ventoy2Disk_X64.exe</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│&nbsp;&nbsp; └── VentoyPlugson_X64.exe</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── boot</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── plugin</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└── ventoy</span><br></div></code></pre></div></div>
<p>其中，我们需要使用的就是 Ventoy2Disk.exe，直接双击运行，选择具体的U盘，就可以将Ventoy安装在U盘上。具体可以参考官网文档：<a href="https://www.ventoy.net/cn/doc_start.html" target="_blank" rel="noopener noreferrer" class="">https://www.ventoy.net/cn/doc_start.html</a>。</p>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>小提示</div><div class="admonitionContent_Q31J"><p>默认的 Ventoy2Disk.exe 是32位x86程序，同时支持最常见的32位和64位Windows系统，绝大部分情况下使用它就可以。</p><p>从1.0.58版本开始，Ventoy还同时提供了 Ventoy2Disk_X64.exe、Ventoy2Disk_ARM.exe 和 Ventoy2Disk_ARM64.exe，可以根据需要使用。</p><p>这些文件位于安装包内的 altexe 目录下，使用时需要将其拷贝到上一层目录（与Ventoy2Disk.exe同级）。</p></div></div>
<p>安装完成后，使用起来就特简单。只需要将系统镜像（或其他工具）直接拷贝到U盘就可以了：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/Ventoy/copy-iso-to-ventory.png" alt="copy-iso-to-ventory.png" class="img_o99Q"></p>
<p>之后其使用U盘启动时就会看到类似如下界面，选择某一个系统镜像即可：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/Ventoy/setup-select-images.png" alt="setup-select-images.png" class="img_o99Q"></p>
<p><strong>关于镜像超过4G的问题：</strong></p>
<p>在安装Ventoy时，默认会将U盘系统类型格式化为 exFAT，该格式支持直接拷贝4G大小镜像问题，所以这个问题理论上不存在。如果你发现无法拷贝，可能的原因就是系统格式选择了FAT32。这个时候你只需要重新打开 Ventoy2Disk.exe，在 “配置选项 — 分区设置” 中指定下分区格式重新安装即可：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/Ventoy/setting-file-system-format.png" alt="setting-file-system-format.png" class="img_o99Q"></p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="Verification-failed-0X1A-Security-violation">Verification failed: (0X1A) Security violation<a href="https://ituknown.github.io/blog/Ventoy-U%E7%9B%98%E5%90%AF%E5%8A%A8%E5%B7%A5%E5%85%B7/#Verification-failed-0X1A-Security-violation" class="hash-link" aria-label="Verification failed: (0X1A) Security violation的直接链接" title="Verification failed: (0X1A) Security violation的直接链接" translate="no">​</a></h2>
<p>在选择U盘启动时，如果遇到 “Verification failed: (0X1A) Security violation” 错误：<a href="https://forums.ventoy.net/showthread.php?tid=2280" target="_blank" rel="noopener noreferrer" class="">https://forums.ventoy.net/showthread.php?tid=2280</a></p>
<p>出现这个问题的原因是 BIOS 打开了安全启动模式。有两种解决方案：</p>
<p>1、直接禁用安全模式即可</p>
<p>2、按照官网文档说明进行操作：<a href="https://www.ventoy.net/cn/doc_secure.html" target="_blank" rel="noopener noreferrer" class="">https://www.ventoy.net/cn/doc_secure.html</a></p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="Normal-模式-or-GRUB2-模式">Normal 模式 or GRUB2 模式？<a href="https://ituknown.github.io/blog/Ventoy-U%E7%9B%98%E5%90%AF%E5%8A%A8%E5%B7%A5%E5%85%B7/#Normal-%E6%A8%A1%E5%BC%8F-or-GRUB2-%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="Normal 模式 or GRUB2 模式？的直接链接" title="Normal 模式 or GRUB2 模式？的直接链接" translate="no">​</a></h2>
<p>在安装时，需要选择一个安装模式：normal mode 或 grub2 mode。可能有点不知道该怎么选择，直接说答案：</p>
<p>1、只有在默认启动方式（Normal 模式）有问题的时候才需要用到 GRUB2 模式</p>
<p>2、GRUB2 模式只能用来启动含有 grub2 配置文件的 Linux 系统，不能启动 Windows/WinPE/Unix 等。</p>
<p>具体可以看下文档说明：<a href="https://www.ventoy.net/cn/doc_grub2boot.html" target="_blank" rel="noopener noreferrer" class="">https://www.ventoy.net/cn/doc_grub2boot.html</a></p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="关于镜像存放问题">关于镜像存放问题<a href="https://ituknown.github.io/blog/Ventoy-U%E7%9B%98%E5%90%AF%E5%8A%A8%E5%B7%A5%E5%85%B7/#%E5%85%B3%E4%BA%8E%E9%95%9C%E5%83%8F%E5%AD%98%E6%94%BE%E9%97%AE%E9%A2%98" class="hash-link" aria-label="关于镜像存放问题的直接链接" title="关于镜像存放问题的直接链接" translate="no">​</a></h2>
<p>我们通常将镜像放在U盘的根目录，因为有 Ventoy 的加持，我们可以正常的使用U盘（比如某种学习资料）。但是如果文件非常多的话，Ventoy 启动就会很慢（因为默认情况下，Ventoy 会遍历U盘中的所有目录及其子目录以找出所有支持的镜像文件。一般情况下U盘中的文件数目都不会很多，因此这个过程比较快，几乎感觉不到。但是如果你的U盘中有非常非常多文件的话，整个搜素过程就会很慢，就会卡很久才能进入启动菜单）。</p>
<p>一种简单的方式是，指定 Ventoy 扫描的具体目录！比如将上面示例中的镜像全部移动到 images 目录下：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── deb</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└── images</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> &nbsp;&nbsp; ├── debian-11.9.0-amd64-DVD-1.iso</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> &nbsp;&nbsp; ├── ubuntu-22.04.4-desktop-amd64.iso</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> &nbsp;&nbsp; ├── ubuntu-22.04.4-live-server-amd64.iso</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> &nbsp;&nbsp; ├── Win10_22H2_zh_CN_x64.iso</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> &nbsp;&nbsp; └── Win10_22H2_en_US_x64.iso</span><br></div></code></pre></div></div>
<p>之后双击 VentoyPlugson.exe，即可自动在网页上开发控制面板。之后再左侧菜单栏找到“全局控制插件”，并找到“指定搜索目录”。在设置中指定U盘中存放系统镜像的目录即可（必须是绝对路径）：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/Ventoy/ventoy-plugson_control-setting.png" alt="ventoy-plugson_control-setting.png" class="img_o99Q"></p>
<p>之后就会在U盘中根据路中自动创建一个 ventoy 文件夹，文件夹内的就是具体的配置内容。特别强调，不要手动修改！！！</p>
<p>具体可以参考官网文档：</p>
<p><a href="https://www.ventoy.net/cn/doc_search_path.html" target="_blank" rel="noopener noreferrer" class="">https://www.ventoy.net/cn/doc_search_path.html</a></p>
<p><a href="https://www.ventoy.net/cn/plugin_control.html" target="_blank" rel="noopener noreferrer" class="">https://www.ventoy.net/cn/plugin_control.html</a></p>]]></content:encoded>
            <category>Ventoy</category>
            <category>软硬件</category>
        </item>
        <item>
            <title><![CDATA[wrk 性能压测]]></title>
            <link>https://ituknown.github.io/blog/wrk-性能压测/</link>
            <guid>https://ituknown.github.io/blog/wrk-性能压测/</guid>
            <pubDate>Sat, 08 Jul 2023 13:38:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="前言">前言<a href="https://ituknown.github.io/blog/wrk-%E6%80%A7%E8%83%BD%E5%8E%8B%E6%B5%8B/#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接链接" title="前言的直接链接" translate="no">​</a></h2>
<p>wrk 是 HTTP 基准测试工具，在单个多核 CPU 上运行时能够产生大量负载，能充分利用CPU资源，是常用的压测工具，不过缺点是不支持 Windows。</p>
<p>对应的Github地址是：<a href="https://github.com/wg/wrk" target="_blank" rel="noopener noreferrer" class="">https://github.com/wg/wrk</a>。</p>
<p>类 UNIX 系统安装 wrk 非常简单，基本上都可以直接使用对应的包管理工具直接安装，具体可见：<a href="https://command-not-found.com/wrk" target="_blank" rel="noopener noreferrer" class="">https://command-not-found.com/wrk</a>。</p>
<p>如果你的发行版没有提供对应的安装方式，就只能选择编译安装了：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">git</span><span class="token plain"> clone https://github.com/wg/wrk.git</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">make</span><br></div></code></pre></div></div>
<p>make之后，会在项目路径下生成可执行文件wrk，随后就可以用其进行HTTP压测了。可以把这个可执行文件拷贝到某个已在path中的路径，比如/usr/local/bin，这样就可以在任何路径直接使用wrk了。</p>
<p>默认情况下wrk会使用自带的LuaJIT和OpenSSL，如果你想使用系统已安装的版本，可以使用WITH_LUAJIT和WITH_OPENSSL这两个选项来指定它们的路径。比如：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">make</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">WITH_LUAJIT</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">/usr </span><span class="token assign-left variable" style="color:#36acaa">WITH_OPENSSL</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">/usr</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="参数及使用方式">参数及使用方式<a href="https://ituknown.github.io/blog/wrk-%E6%80%A7%E8%83%BD%E5%8E%8B%E6%B5%8B/#%E5%8F%82%E6%95%B0%E5%8F%8A%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="参数及使用方式的直接链接" title="参数及使用方式的直接链接" translate="no">​</a></h2>
<p>wrk 命令基本语法如下：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ wrk </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">options</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">url</span><span class="token operator" style="color:#393A34">&gt;</span><br></div></code></pre></div></div>
<p>其中可选参数如下：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">-c, --connections &lt;N&gt;  TCP建立连接数</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-d, --duration    &lt;T&gt;  请求持续时间</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-t, --threads     &lt;N&gt;  使用线程数</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-H, --header      &lt;H&gt;  指定HTTP请求头</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --latency          打印延迟统计信息</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --timeout     &lt;T&gt;  超时时间</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-s, --script      &lt;S&gt;  Lua脚本(高级使用方式)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">&lt;N&gt; 代表数字参数, 支持国际单位 (1k, 1M, 1G)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">&lt;T&gt; 代表时间参数, 支持时间单位 (2s, 2m, 2h)</span><br></div></code></pre></div></div>
<p>基本使用：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ wrk </span><span class="token parameter variable" style="color:#36acaa">-t12</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-c400</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-d30s</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--latency</span><span class="token plain"> http://baidu.com</span><br></div></code></pre></div></div>
<p>以上命令使用400个连接，使用12个线程对 baidu 进行了30秒压测。下面是输出示例：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">Running 30s test @ http://baidu.com</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  12 threads and 400 connections</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  Thread Stats   Avg      Stdev     Max   +/- Stdev</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Latency     0.00us    0.00us   0.00us    -nan%</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Req/Sec     0.00      0.00     0.00      -nan%</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  Latency Distribution</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     50%    0.00us</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     75%    0.00us</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     90%    0.00us</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     99%    0.00us</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  0 requests in 30.06s, 0.00B read</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  Socket errors: connect 0, read 8446, write 0, timeout 0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Requests/sec:      0.00</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Transfer/sec:       0.00B</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="Lua-脚本">Lua 脚本<a href="https://ituknown.github.io/blog/wrk-%E6%80%A7%E8%83%BD%E5%8E%8B%E6%B5%8B/#Lua-%E8%84%9A%E6%9C%AC" class="hash-link" aria-label="Lua 脚本的直接链接" title="Lua 脚本的直接链接" translate="no">​</a></h2>
<p>上面这种简单的压测可能不能满足我们的需求。比如我们可能需要使用POST请求跟服务器交互；可能需要为每一次请求使用不同的参数，以更好的模拟服务的实际使用场景等。wrk支持用户使用指定Lua脚本，来定制压测过程，满足个性化需求。</p>
<p>wrk 提供了一些 Lua 脚本示例，具体可以参考：</p>
<p><a href="https://github.com/wg/wrk/tree/master/scripts" target="_blank" rel="noopener noreferrer" class="">https://github.com/wg/wrk/tree/master/scripts</a></p>
<p>想要了解更多就需要稍微花点时间研究 Lua 脚本如何编写了~</p>
<p>下面是一个 POST JSON 请求示例：</p>
<p>post.lua：</p>
<div class="language-lua codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-lua codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">wrk.method = "POST"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">wrk.body = '{"seqname": "commons"}'</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">wrk.headers["Content-Type"] = "application/json"</span><br></div></code></pre></div></div>
<p>wrk POST 请求压测示例：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ wrk </span><span class="token parameter variable" style="color:#36acaa">-s</span><span class="token plain"> post.lua </span><span class="token parameter variable" style="color:#36acaa">-t8</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-c200</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-d30s</span><span class="token plain">  http:://localhost:8080/adduser</span><br></div></code></pre></div></div>]]></content:encoded>
            <category>软硬件</category>
            <category>性能</category>
        </item>
        <item>
            <title><![CDATA[Rsa 密匙对生成]]></title>
            <link>https://ituknown.github.io/blog/Rsa 密匙对生成/</link>
            <guid>https://ituknown.github.io/blog/Rsa 密匙对生成/</guid>
            <pubDate>Mon, 23 Jan 2023 16:27:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="前言">前言<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接链接" title="前言的直接链接" translate="no">​</a></h2>
<p>生成 rsa 密匙对有许多中方式，而在系统中使用最多的就是 <code>openssl</code>。如果你的操作系统还没有 openssl，就需要手动安装。</p>
<p>Windows 用户需要到官网 <a href="https://www.openssl.org/" target="_blank" rel="noopener noreferrer" class="">https://www.openssl.org</a> 进行下载安装。</p>
<p>Unix 用户可以直接使用默认的包管理工具进行安装。具体可以参考：<a href="https://command-not-found.com/openssl" target="_blank" rel="noopener noreferrer" class="">https://command-not-found.com/openssl</a>，这里提供了各种发行版对应的安装命令。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="OpenSSL-生成-RSA-密钥对">OpenSSL 生成 RSA 密钥对<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#OpenSSL-%E7%94%9F%E6%88%90-RSA-%E5%AF%86%E9%92%A5%E5%AF%B9" class="hash-link" aria-label="OpenSSL 生成 RSA 密钥对的直接链接" title="OpenSSL 生成 RSA 密钥对的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="生成私钥">生成私钥<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E7%94%9F%E6%88%90%E7%A7%81%E9%92%A5" class="hash-link" aria-label="生成私钥的直接链接" title="生成私钥的直接链接" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ openssl genrsa </span><span class="token parameter variable" style="color:#36acaa">-out</span><span class="token plain"> private_key.pem length</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>private_key.pem</code>：输出的私钥文件名</li>
<li class=""><code>length</code>：指定私钥长度（如 1024、2048），越长表示加密性越强。</li>
</ul>
<p><code>openssl genrsa</code> 命令默认生成的是 PEM 格式私钥文件，PEM (Privacy-Enhanced Mail) 是一种常见的密钥和证书格式，它使用 Base64 编码的 ASCII 文本表示密钥和证书，并且通常以 .pem 作为文件扩展名。</p>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_Q31J"><p>需要特别说明说明的一点是，openssl 在 3.0 之前 <code>openssl genrsa</code> 命令生成的私钥文件默认使用的是 PKCS#1 标准。但是从 3.0 开始，默认为 PKCS#8 标准。</p></div></div>
<p>如何区分生成的私钥是 PKCS#1 标准还是 PKCS#8 标准呢？只需要打开生成的私钥文件，看开头和结尾内容标识即可：</p>
<p>PKCS#1 标准文件内容开头和结尾标识：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">-----BEGIN RSA PRIVATE KEY-----</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">.....</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-----END RSA PRIVATE KEY-----</span><br></div></code></pre></div></div>
<p>PKCS#8 标准文件内容开头和结尾标识：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">-----BEGIN PRIVATE KEY-----</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">.....</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-----END PRIVATE KEY-----</span><br></div></code></pre></div></div>
<p><strong>示例：</strong></p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ openssl genrsa </span><span class="token parameter variable" style="color:#36acaa">-out</span><span class="token plain"> private_key.pem </span><span class="token number" style="color:#36acaa">2048</span><br></div></code></pre></div></div>
<p>命令执行完成之后就会看到在当前目录下多了一个 private_key.pem 私钥文件：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">ls</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">private_key.pem</span><br></div></code></pre></div></div>
<p>如果私钥文件内容以 “-----BEGIN RSA PRIVATE KEY-----” 开头，“-----END RSA PRIVATE KEY-----” 结尾，说明私钥是 PKCS#1 标准。</p>
<p>如果私钥文件内容以 “-----BEGIN PRIVATE KEY-----” 开头，“-----END PRIVATE KEY-----” 结尾，说明私钥是 PKCS#8 标准。</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="导出公钥默认X509格式">导出公钥（默认X.509格式）<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E5%AF%BC%E5%87%BA%E5%85%AC%E9%92%A5%E9%BB%98%E8%AE%A4X509%E6%A0%BC%E5%BC%8F" class="hash-link" aria-label="导出公钥（默认X.509格式）的直接链接" title="导出公钥（默认X.509格式）的直接链接" translate="no">​</a></h3>
<p>从 rsa 私钥中提取公钥，命令如下：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ openssl rsa </span><span class="token parameter variable" style="color:#36acaa">-in</span><span class="token plain"> private_key.pem </span><span class="token parameter variable" style="color:#36acaa">-pubout</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-out</span><span class="token plain"> public_key.pem</span><br></div></code></pre></div></div>
<p><code>private_key.pem</code> 就是之前生成的私钥的文件名（公钥生成规则是通过计算私钥数值）。<code>public_key.pem</code> 表示要导出的公钥的文件。</p>
<p>之后的就产生了对应的公钥文件 id_rsa_pub：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">ls</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">private_key.pem  public_key.pem</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="私钥转-PKCS8-格式">私钥转 PKCS8 格式<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E7%A7%81%E9%92%A5%E8%BD%AC-PKCS8-%E6%A0%BC%E5%BC%8F" class="hash-link" aria-label="私钥转 PKCS8 格式的直接链接" title="私钥转 PKCS8 格式的直接链接" translate="no">​</a></h3>
<p>PKCS#8 格式是一种更通用的私钥格式标准（如果你使用的是 Java、C## 开发语言就需要将私钥转换为 PKCS8 格式），相比 PKCS#1 更加通用，可以表示任意类型的私钥，不仅限于 RSA。</p>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>特别说明</div><div class="admonitionContent_Q31J"><p>如果你的 openssl 版本大于或等于 3.0，那么生成的私钥本身就是 PKCS#8 标准格式，无需再执行格式转换！</p></div></div>
<p>命令如下：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ openssl pkcs8 </span><span class="token parameter variable" style="color:#36acaa">-topk8</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-inform</span><span class="token plain"> PEM </span><span class="token parameter variable" style="color:#36acaa">-in</span><span class="token plain"> private_key.pem </span><span class="token parameter variable" style="color:#36acaa">-outform</span><span class="token plain"> PEM </span><span class="token parameter variable" style="color:#36acaa">-out</span><span class="token plain"> private_key_pkcs8.pem </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">-nocrypt</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>private_key_pkcs8.pem</code>：要输出的 PSCK#8 格式文件</li>
<li class=""><code>-nocrypt</code>：用于指定不对 PKCS#8 文件内容加密（根据实际需要使用，不过通常都会加上该参数）。如果不指定该参数，那么 OpenSSL 会提示你输入一个密码来加密私钥。通常提示信息如下：</li>
</ul>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">Enter Encryption Password:</span><br></div></code></pre></div></div>
<p>现在除了私钥公钥之外，当前目录下还多了一个 PKCS8 格式私钥文件：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">ls</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">private_key.pem  public_key.pem  private_key_pkcs8.pem</span><br></div></code></pre></div></div>
<p>因为 PEM 格式内容本身就是 Base64 编码的 ASCII 文本。如果程序不想以文件的形式读取 private_key_pkcs8.pem 文件，而是通过字符串的形式使用，只需要删除文件首尾两行并去除换行即可。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="DER-和-PEM-格式区别">DER 和 PEM 格式区别<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#DER-%E5%92%8C-PEM-%E6%A0%BC%E5%BC%8F%E5%8C%BA%E5%88%AB" class="hash-link" aria-label="DER 和 PEM 格式区别的直接链接" title="DER 和 PEM 格式区别的直接链接" translate="no">​</a></h2>
<p>rsa 密匙对除了 PEM 格式之外，还有 DER 格式。简单地说，他们之间的区别只是内容形式不同。<u>DER 使用二进制编码，文件内容是原始的二进制数据。而 PEM 使用 Base64 编码，文件内容是 Base64 编码的文本。</u>另外：</p>
<table><thead><tr><th style="text-align:left"><strong>格式</strong></th><th style="text-align:left"><strong>可读性</strong></th><th style="text-align:left"><strong>文件扩展名</strong></th><th style="text-align:left"><strong>应用场景</strong></th></tr></thead><tbody><tr><td style="text-align:left">DER</td><td style="text-align:left">不可读，需要使用特定的工具才能查看内容</td><td style="text-align:left">通常使用 .der 或 .cer 作为扩展名</td><td style="text-align:left">常用于程序和系统内部使用，因为二进制更高效、更紧凑</td></tr><tr><td style="text-align:left">PEM</td><td style="text-align:left">可读，可以直接查看文件内容</td><td style="text-align:left">通常使用 .pem 作为扩展名</td><td style="text-align:left">常用于人工查看和编辑，因为它是 Base64 编码的 ASCII 字符，更易读</td></tr></tbody></table>
<div class="theme-admonition theme-admonition-danger admonition_fnQa alert alert--danger"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>特别强调</div><div class="admonitionContent_Q31J"><p>DER 是二进制格式数据，PEM 是 Base64 编码文本数据。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="格式转换">格式转换<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2" class="hash-link" aria-label="格式转换的直接链接" title="格式转换的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="PKCS1-转-DER">PKCS#1 转 DER<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#PKCS1-%E8%BD%AC-DER" class="hash-link" aria-label="PKCS#1 转 DER的直接链接" title="PKCS#1 转 DER的直接链接" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">openssl rsa </span><span class="token parameter variable" style="color:#36acaa">-in</span><span class="token plain"> private_key.pem </span><span class="token parameter variable" style="color:#36acaa">-outform</span><span class="token plain"> DER </span><span class="token parameter variable" style="color:#36acaa">-out</span><span class="token plain"> private_key.der</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="PKCS1-转-PKCS8">PKCS#1 转 PKCS#8<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#PKCS1-%E8%BD%AC-PKCS8" class="hash-link" aria-label="PKCS#1 转 PKCS#8的直接链接" title="PKCS#1 转 PKCS#8的直接链接" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">openssl pkcs8 </span><span class="token parameter variable" style="color:#36acaa">-topk8</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-inform</span><span class="token plain"> PEM </span><span class="token parameter variable" style="color:#36acaa">-in</span><span class="token plain"> private_key.pem </span><span class="token parameter variable" style="color:#36acaa">-outform</span><span class="token plain"> PEM </span><span class="token parameter variable" style="color:#36acaa">-out</span><span class="token plain"> private_key_pkcs8.pem </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">-nocrypt</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="PKCS8-转-DER">PKCS#8 转 DER<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#PKCS8-%E8%BD%AC-DER" class="hash-link" aria-label="PKCS#8 转 DER的直接链接" title="PKCS#8 转 DER的直接链接" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">openssl pkcs8 </span><span class="token parameter variable" style="color:#36acaa">-topk8</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-in</span><span class="token plain"> private_key.pem </span><span class="token parameter variable" style="color:#36acaa">-outform</span><span class="token plain"> DER </span><span class="token parameter variable" style="color:#36acaa">-out</span><span class="token plain"> private_key_pkcs8.der </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">-nocrypt</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="公钥为什么不需要做格式转换">公钥为什么不需要做格式转换<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E5%85%AC%E9%92%A5%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E9%9C%80%E8%A6%81%E5%81%9A%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2" class="hash-link" aria-label="公钥为什么不需要做格式转换的直接链接" title="公钥为什么不需要做格式转换的直接链接" translate="no">​</a></h2>
<p>公钥不需要像私钥那样转换格式的主要原因有以下几点：</p>
<details open="" class="details_unQd alert alert--info details_J7LK" data-collapsed="false"><summary><strong>公钥格式标准化</strong></summary><div><div class="collapsibleContent_MGAI"><p>公钥通常采用 X.509 标准。即以 “-----BEGIN PUBLIC KEY-----” 开头，“-----END PUBLIC KEY-----” 结尾的 PEM 格式。这已经成为公钥表示的事实标准。</p><p>相比私钥，公钥格式更加统一和简单，不需要像私钥那样有多种不同的表示方式。</p></div></div></details>
<details open="" class="details_unQd alert alert--info details_J7LK" data-collapsed="false"><summary><strong>公钥用途单一</strong></summary><div><div class="collapsibleContent_MGAI"><p>公钥主要用于加密数据和验证数字签名。它不像私钥那样需要用于解密或生成签名等多种操作。因此公钥的格式要求相对简单，无需像私钥那样有多种表示方式来适应不同的应用场景。</p></div></div></details>
<details open="" class="details_unQd alert alert--info details_J7LK" data-collapsed="false"><summary><strong>不涉及敏感信息</strong></summary><div><div class="collapsibleContent_MGAI"><p>公钥是公开的，不涉及任何敏感信息。因此在使用时不需要像私钥那样需要特殊的安全处理。相比之下，私钥包含了敏感的密钥材料，需要采取更加谨慎的措施进行保护和管理。</p></div></div></details>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="扩展">扩展<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E6%89%A9%E5%B1%95" class="hash-link" aria-label="扩展的直接链接" title="扩展的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="使用Java生成RSA密匙对">使用Java生成RSA密匙对<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E4%BD%BF%E7%94%A8Java%E7%94%9F%E6%88%90RSA%E5%AF%86%E5%8C%99%E5%AF%B9" class="hash-link" aria-label="使用Java生成RSA密匙对的直接链接" title="使用Java生成RSA密匙对的直接链接" translate="no">​</a></h3>
<p>Java 程序生成的 RSA 密匙对私钥默认为 PKCS#8 格式，公钥则是 X.509 格式。具体的代码也很简单，直接上码：</p>
<div class="language-java codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-java codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">genKeyPair</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">genKeyPair</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">KeyPairGenerator</span><span class="token plain"> keyPairGen </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">KeyPairGenerator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    keyPairGen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">initialize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">2048</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 密匙长度</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">KeyPair</span><span class="token plain"> keyPair </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> keyPairGen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generateKeyPair</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">RSAPrivateKey</span><span class="token plain"> privateKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RSAPrivateKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> keyPair</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPrivate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">RSAPublicKey</span><span class="token plain"> publicKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RSAPublicKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> keyPair</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPublic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">out</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">println</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"私钥格式:"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> privateKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFormat</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// PKCS#8</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">out</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">println</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"公钥格式:"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> publicKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFormat</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// X.509</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">out</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">println</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"私钥内容: \n"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">encodeToString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">privateKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEncoded</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">out</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">println</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"公钥内容: \n"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">encodeToString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">publicKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEncoded</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">encodeToString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> encoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Base64</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEncoder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">encodeToString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decodeToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> decoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Base64</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getDecoder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">decoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="使用-Go-生成RSA密匙对">使用 Go 生成RSA密匙对<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E4%BD%BF%E7%94%A8-Go-%E7%94%9F%E6%88%90RSA%E5%AF%86%E5%8C%99%E5%AF%B9" class="hash-link" aria-label="使用 Go 生成RSA密匙对的直接链接" title="使用 Go 生成RSA密匙对的直接链接" translate="no">​</a></h3>
<p>使用 Go 生成 rsa 密匙对需要使用 <code>golang.org/x/crypto</code> 密码库：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">go </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> golang.org/x/crypto</span><br></div></code></pre></div></div>
<p>相比较 Java，使用 Go 生成 rsa 密匙对就方便很多，而且将公钥和私钥转换为其他格式也特别简单，下面是示例：</p>
<div class="language-go codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-go codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">package</span><span class="token plain"> main</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token string" style="color:#e3116c">"crypto/rand"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token string" style="color:#e3116c">"crypto/rsa"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token string" style="color:#e3116c">"crypto/x509"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token string" style="color:#e3116c">"encoding/pem"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token string" style="color:#e3116c">"os"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// 生成私钥</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	privateKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">_</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> rsa</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">GenerateKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rand</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Reader</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2048</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// 输出 pkcs1 私钥</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	pem</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Encode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">os</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Stdout</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">pem</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Block</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">    </span><span class="token string" style="color:#e3116c">"RSA PRIVATE KEY"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Headers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Bytes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">   x509</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">MarshalPKCS1PrivateKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">privateKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// 输出 pkcs8 私钥</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	pkcs8Private</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">_</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> x509</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">MarshalPKCS8PrivateKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">privateKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	pem</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Encode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">os</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Stdout</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">pem</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Block</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">    </span><span class="token string" style="color:#e3116c">"PRIVATE KEY"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Headers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Bytes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">   pkcs8Private</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// 输出 X.509 公钥</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	x509Public</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">_</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:=</span><span class="token plain"> x509</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">MarshalPKIXPublicKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">privateKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">PublicKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	pem</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Encode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">os</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Stdout</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">pem</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Block</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">    </span><span class="token string" style="color:#e3116c">"PUBLIC KEY"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Headers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">nil</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">		Bytes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">   x509Public</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="参考资料">参考资料<a href="https://ituknown.github.io/blog/Rsa%20%E5%AF%86%E5%8C%99%E5%AF%B9%E7%94%9F%E6%88%90/#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99" class="hash-link" aria-label="参考资料的直接链接" title="参考资料的直接链接" translate="no">​</a></h2>
<p><a href="https://www.cryptosys.net/pki/rsakeyformats.html" target="_blank" rel="noopener noreferrer" class="">https://www.cryptosys.net/pki/rsakeyformats.html</a></p>
<p><a href="https://stackoverflow.com/questions/10783366/how-to-generate-pkcs1-rsa-keys-in-pem-format" target="_blank" rel="noopener noreferrer" class="">https://stackoverflow.com/questions/10783366/how-to-generate-pkcs1-rsa-keys-in-pem-format</a></p>]]></content:encoded>
            <category>加密</category>
        </item>
        <item>
            <title><![CDATA[SSH Key 和 SSL Key 区别]]></title>
            <link>https://ituknown.github.io/blog/SSH Key 和 SSL Key 区别/</link>
            <guid>https://ituknown.github.io/blog/SSH Key 和 SSL Key 区别/</guid>
            <pubDate>Mon, 23 Jan 2023 15:01:00 GMT</pubDate>
            <description><![CDATA[SSH key 和通过 OpenSSL 生成的 SSL key 尽管都基于公钥加密技术，但是是两种不同用途的密钥。以下是它们的主要区别和用途：]]></description>
            <content:encoded><![CDATA[<p>SSH key 和通过 OpenSSL 生成的 SSL key 尽管都基于公钥加密技术，但是是两种不同用途的密钥。以下是它们的主要区别和用途：</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="SSH-Key">SSH Key<a href="https://ituknown.github.io/blog/SSH%20Key%20%E5%92%8C%20SSL%20Key%20%E5%8C%BA%E5%88%AB/#SSH-Key" class="hash-link" aria-label="SSH Key的直接链接" title="SSH Key的直接链接" translate="no">​</a></h2>
<p><strong>用途：</strong></p>
<p>典型的应用是 SSH 客户端远程连接（登录）服务器、SCP（安全复制）和 SFTP（安全文件传输）</p>
<p><strong>协议：</strong> 基于 SSH 协议</p>
<p><strong>典型场景：</strong></p>
<ol>
<li class="">登录远程服务器时用于身份验证（无密码登录）</li>
<li class="">Git 代码托管平台（如 GitHub、GitLab）上的身份验证</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="OpenSSH-格式推荐">OpenSSH 格式（推荐）<a href="https://ituknown.github.io/blog/SSH%20Key%20%E5%92%8C%20SSL%20Key%20%E5%8C%BA%E5%88%AB/#OpenSSH-%E6%A0%BC%E5%BC%8F%E6%8E%A8%E8%8D%90" class="hash-link" aria-label="OpenSSH 格式（推荐）的直接链接" title="OpenSSH 格式（推荐）的直接链接" translate="no">​</a></h3>
<p>这是现代 OpenSSH 客户端（如 ssh-keygen）的默认格式，尤其对于较新的算法如 Ed25519。</p>
<p><strong>公钥文件 (Public Key)：</strong></p>
<ol>
<li class="">通常以 .pub 结尾（例如：id_rsa.pub）。</li>
<li class="">是一个单行文本，包含算法类型、Base64 编码的公钥数据以及一个可选的注释（Comment）。</li>
</ol>
<p><strong>私钥文件 (Private Key)：</strong></p>
<ol>
<li class="">通常没有文件扩展名（例如：id_rsa）或使用 .key。</li>
<li class="">从 <u>OpenSSH 7.8</u> 版本开始，默认使用一种新的、更安全的 OpenSSH 私钥格式，该格式比旧的 PEM 格式更安全。</li>
<li class="">新格式是一种带报头的 ASCII 文本块，格式本身是专用于 SSH 协议的。</li>
</ol>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>NOTE</div><div class="admonitionContent_Q31J"><p>使用 ssh-keygen 生成的公私钥默认保存在 <code>~/.ssh</code> 目录，公钥默认文件命名通常为 <code>id_rsa.pub</code> ，私钥默认文件名通常为 <code>id_rsa</code>。</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="PEM-格式传统兼容性">PEM 格式（传统/兼容性）<a href="https://ituknown.github.io/blog/SSH%20Key%20%E5%92%8C%20SSL%20Key%20%E5%8C%BA%E5%88%AB/#PEM-%E6%A0%BC%E5%BC%8F%E4%BC%A0%E7%BB%9F%E5%85%BC%E5%AE%B9%E6%80%A7" class="hash-link" aria-label="PEM 格式（传统/兼容性）的直接链接" title="PEM 格式（传统/兼容性）的直接链接" translate="no">​</a></h3>
<p>PEM（Privacy-Enhanced Mail）格式是一种通用容器格式，最初是为电子邮件安全设计的，但现在广泛用于存储加密密钥和证书。</p>
<p><strong>特点：</strong> 以 Base64 编码的文本形式存储，并由明确的文本报头和报尾包围，便于在系统之间复制和传输。</p>
<p><strong>旧的私钥格式：</strong> 旧版本的 ssh-keygen（在 <u>OpenSSH 7.8</u> 之前）默认生成的是 PEM 格式私钥。</p>
<div class="theme-admonition theme-admonition-danger admonition_fnQa alert alert--danger"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>注意</div><div class="admonitionContent_Q31J"><p>为了兼容性和安全性，现代 SSH 客户端推荐使用 OpenSSH 格式，并可以通过如下命令将旧的 PEM 私钥升级为新格式：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">ssh-keygen </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> id_rsa</span><br></div></code></pre></div></div></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="SSL-Key">SSL Key<a href="https://ituknown.github.io/blog/SSH%20Key%20%E5%92%8C%20SSL%20Key%20%E5%8C%BA%E5%88%AB/#SSL-Key" class="hash-link" aria-label="SSL Key的直接链接" title="SSL Key的直接链接" translate="no">​</a></h2>
<p><strong>用途：</strong></p>
<p>主要用于建立客户端（如网页浏览器）和服务器之间的安全通道，以加密传输中的数据，防止窃听和篡改。典型的应用是 HTTPS，也用于 SMTPS (安全邮件) 和 FTPS (安全文件传输)。</p>
<p><strong>协议：</strong> 基于 TLS/SSL 协议</p>
<p><strong>典型场景：</strong></p>
<ol>
<li class="">为网站配置 HTTPS。</li>
<li class="">在 Web 服务器（如 Apache、Nginx）中用于加密通信。</li>
<li class="">生成服务器证书或客户端证书。</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="格式">格式<a href="https://ituknown.github.io/blog/SSH%20Key%20%E5%92%8C%20SSL%20Key%20%E5%8C%BA%E5%88%AB/#%E6%A0%BC%E5%BC%8F" class="hash-link" aria-label="格式的直接链接" title="格式的直接链接" translate="no">​</a></h3>
<p>所有 SSL/TLS 证书（包括公钥）都必须符合 X.509 标准，这是一个定义了公钥证书格式的 ITU-T 标准。</p>
<p>证书包含信息：X.509 证书不只包含公钥，它还包括：版本号、序列号、签名算法、公钥、主题（Subject，如域名）、颁发者（Issuer，如 CA 名称）、有效期、CA 的数字签名等。</p>
<p>虽然证书结构是 X.509，但却可以以不同的编码方式和容器格式存储。</p>
<table><thead><tr><th style="text-align:left">格式名称</th><th style="text-align:left">编码方式</th><th style="text-align:left">常见扩展名</th><th style="text-align:left">主要用途和特点</th></tr></thead><tbody><tr><td style="text-align:left">PEM（常用格式）</td><td style="text-align:left">Base64 编码（ASCII 文本）</td><td style="text-align:left">.pem、.crt、.cer、.key</td><td style="text-align:left">以 <code>-----BEGIN XXXXX-----</code> 开头，以 <code>-----END XXXXX-----</code> 结尾。<br><br>其中 XXXXX 可以是 CERTIFICATE（证书）、RSA PRIVATE KEY（私钥）等。<br><br>适用于 Linux/Unix 服务器和许多 Web 服务器</td></tr><tr><td style="text-align:left">DER</td><td style="text-align:left">二进制编码</td><td style="text-align:left">.der、.cer</td><td style="text-align:left">通常用于 Java 平台和某些网络设备。不包含可读的文本报头</td></tr><tr><td style="text-align:left">PKCS#12<br>(PFX/P12)</td><td style="text-align:left">二进制容器</td><td style="text-align:left">.pfx、.p12</td><td style="text-align:left">一个受密码保护的容器，用于将私钥与其对应的证书（和可选的证书链）打包在一个文件中。<br><br>主要用于 Windows/IIS 服务器导入和导出密钥和证书。</td></tr><tr><td style="text-align:left">PKCS#7<br>(P7B)</td><td style="text-align:left">Base64 编码容器</td><td style="text-align:left">.p7b、.p7c</td><td style="text-align:left">仅包含证书和证书链（不包含私钥）。<br><br>常用于在 Microsoft Windows 和 Java Tomcat 之间传输证书链。</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="核心区别">核心区别<a href="https://ituknown.github.io/blog/SSH%20Key%20%E5%92%8C%20SSL%20Key%20%E5%8C%BA%E5%88%AB/#%E6%A0%B8%E5%BF%83%E5%8C%BA%E5%88%AB" class="hash-link" aria-label="核心区别的直接链接" title="核心区别的直接链接" translate="no">​</a></h2>
<table><thead><tr><th><strong>属性</strong></th><th><strong>SSH Key</strong></th><th><strong>SSL Key</strong></th></tr></thead><tbody><tr><td><strong>主要用途</strong></td><td>身份验证、远程登录</td><td>安全通信、数据加密</td></tr><tr><td><strong>协议</strong></td><td>SSH</td><td>TLS/SSL</td></tr><tr><td><strong>生成工具</strong></td><td>ssh-keygen</td><td>OpenSSL</td></tr><tr><td><strong>文件扩展名</strong></td><td><code>.pub</code>（公钥），无扩展名或 <code>.pem</code>（私钥）</td><td><code>.key</code>，<code>.pem</code></td></tr><tr><td><strong>加密目标</strong></td><td>用户身份、访问权限验证</td><td>加密传输数据、保护通信</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="总结">总结<a href="https://ituknown.github.io/blog/SSH%20Key%20%E5%92%8C%20SSL%20Key%20%E5%8C%BA%E5%88%AB/#%E6%80%BB%E7%BB%93" class="hash-link" aria-label="总结的直接链接" title="总结的直接链接" translate="no">​</a></h2>
<ol>
<li class="">如果你要通过 SSH 远程连接服务器，请使用 SSH key。</li>
<li class="">如果你要为网站配置 HTTPS，请使用 SSL key。</li>
</ol>]]></content:encoded>
            <category>加密</category>
        </item>
        <item>
            <title><![CDATA[非对称加密算法与应用场景]]></title>
            <link>https://ituknown.github.io/blog/非对称加密算法与应用场景/</link>
            <guid>https://ituknown.github.io/blog/非对称加密算法与应用场景/</guid>
            <pubDate>Mon, 23 Jan 2023 13:57:00 GMT</pubDate>
            <description><![CDATA[简介]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="简介">简介<a href="https://ituknown.github.io/blog/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/#%E7%AE%80%E4%BB%8B" class="hash-link" aria-label="简介的直接链接" title="简介的直接链接" translate="no">​</a></h2>
<p>非对称加密算法是密码学的一种算法，它需要两个密钥，一个是公开密钥（简称为：公钥），另一个是私有密钥（简称为：私钥）；一个用作加密，另一个则用作解密。</p>
<p>使用其中一个密钥把明文加密后所得的密文，只能用相对应的另一个密钥才能解密得到原本的明文；甚至连最初用来加密的密钥也不能用作解密。</p>
<p>由于加密和解密需要两个不同的密钥，故被称为非对称加密；不同于加密和解密都使用同一个密钥的对称加密。</p>
<p>虽然两个密钥在数学上相关，但如果知道了其中一个，并不能凭此计算出另一个；因此其中一个可以公开，称为公钥，任意向外发布；不公开的密钥称为私钥，必须由用户自行严格秘密保管，绝不透过任何途径向任何人提供，也不会透露给被信任的要通信的另一方。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="应用场景">应用场景<a href="https://ituknown.github.io/blog/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF" class="hash-link" aria-label="应用场景的直接链接" title="应用场景的直接链接" translate="no">​</a></h2>
<p>非对称密码算法，所谓非对称，就是指该算法需要一对密钥，使用其中一个加密，则需要用另一个才能解密。</p>
<p>非对称加密主要应用于两个场景：数据加密和签名</p>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>加密和签名的区别</div><div class="admonitionContent_Q31J"><p>加密和签名都是为了安全性考虑，但有所不同。<strong>加密是为了防止信息被泄露，签名是为了防止信息被篡改。</strong></p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="加密过程">加密过程<a href="https://ituknown.github.io/blog/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/#%E5%8A%A0%E5%AF%86%E8%BF%87%E7%A8%8B" class="hash-link" aria-label="加密过程的直接链接" title="加密过程的直接链接" translate="no">​</a></h3>
<ol>
<li class="">A生成一对密钥（公钥和私钥），私钥不公开，A自己保留。公钥为公开的，任何人可以获取。<br></li>
<li class="">A传递自己的公钥给B，B使用A的公钥对消息进行加密。<br></li>
<li class="">A接收到B加密的消息，利用A自己的私钥对消息进行解密。<br></li>
</ol>
<p>整个过程中，只用A的私钥才能对消息进行解密，防止消息被泄露。</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="签名过程">签名过程<a href="https://ituknown.github.io/blog/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/#%E7%AD%BE%E5%90%8D%E8%BF%87%E7%A8%8B" class="hash-link" aria-label="签名过程的直接链接" title="签名过程的直接链接" translate="no">​</a></h3>
<ol>
<li class="">A生成一对密钥（公钥和私钥），私钥不公开，A自己保留。公钥为公开的，任何人可以获取。<br></li>
<li class="">A用自己的私钥对消息进行加签，形成签名，并将签名和消息本身一起传递给B。<br></li>
<li class="">B收到消息后，通过A的公钥进行验签，如果验签成功，则证明消息是A发送的。<br></li>
</ol>
<p>整个过程，只有使用A私钥签名的消息才能被验签成功。即使知道了消息内容，也无法伪造签名，防止消息被篡改。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="Java-代码示例">Java 代码示例<a href="https://ituknown.github.io/blog/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/#Java-%E4%BB%A3%E7%A0%81%E7%A4%BA%E4%BE%8B" class="hash-link" aria-label="Java 代码示例的直接链接" title="Java 代码示例的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="Rsa-加解密工具类">Rsa 加解密工具类<a href="https://ituknown.github.io/blog/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/#Rsa-%E5%8A%A0%E8%A7%A3%E5%AF%86%E5%B7%A5%E5%85%B7%E7%B1%BB" class="hash-link" aria-label="Rsa 加解密工具类的直接链接" title="Rsa 加解密工具类的直接链接" translate="no">​</a></h3>
<div class="language-java codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-java codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">javax</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">crypto</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">Cipher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">nio</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">charset</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">interfaces</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">RSAPrivateKey</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">interfaces</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">RSAPublicKey</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">spec</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">PKCS8EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">spec</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">X509EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">util</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">HashMap</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">util</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">Map</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Rsa 非对称加密解密工具类</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">RsaUtil</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 公钥加密</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param plaintext 明文</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pubKey    公钥</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">encrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PublicKey</span><span class="token plain"> pubKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Cipher</span><span class="token plain"> cipher </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Cipher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        cipher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Cipher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">ENCRYPT_MODE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pubKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> encrypted </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cipher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doFinal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plaintext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 密文</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encrypted</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 公钥加密</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pubKeyBase64 base64格式公钥</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">encrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pubKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 公钥证书</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">X509EncodedKeySpec</span><span class="token plain"> keySpec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">X509EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pubKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PublicKey</span><span class="token plain"> publicKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">KeyFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generatePublic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySpec</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">encrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> publicKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 加密</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 公钥加密</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pubKeyBase64 base64格式公钥</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">encryptToBase64String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pubKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 公钥证书</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">X509EncodedKeySpec</span><span class="token plain"> keySpec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">X509EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pubKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PublicKey</span><span class="token plain"> publicKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">KeyFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generatePublic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySpec</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">encrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> publicKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RsaUtil</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">toBase64String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 加密</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 私钥解密</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param encrypted 密文</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param priKey    私钥</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> encrypted</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PrivateKey</span><span class="token plain"> priKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Cipher</span><span class="token plain"> cipher </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Cipher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        cipher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Cipher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DECRYPT_MODE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> priKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> decrypted </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cipher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doFinal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encrypted</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">decrypted</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decryptToString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> encrypted</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PrivateKey</span><span class="token plain"> priKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encrypted</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> priKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token operator" style="color:#393A34">::</span><span class="token keyword" style="color:#00009f">new</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 私钥解密</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param priKeyBase64 base64格式私钥</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> encryptedText</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> priKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 私钥证书</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PKCS8EncodedKeySpec</span><span class="token plain"> keySpec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">PKCS8EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PrivateKey</span><span class="token plain"> privateKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">KeyFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generatePrivate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySpec</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encryptedText</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> privateKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decryptToString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> encryptedText</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> privateKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decrypt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encryptedText</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> privateKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token operator" style="color:#393A34">::</span><span class="token keyword" style="color:#00009f">new</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">toBase64String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> encoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name namespace" style="opacity:0.7">java</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name namespace" style="opacity:0.7">util</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name">Base64</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEncoder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">encodeToString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> decoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name namespace" style="opacity:0.7">java</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name namespace" style="opacity:0.7">util</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name">Base64</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getDecoder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">decoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@FunctionalInterface</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the function result</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 生成密匙对</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param keySize 密钥大小</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">KeyPair</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">generateKeyPair</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> keySize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 初始化一个RSA算法的密钥对生成器</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">KeyPairGenerator</span><span class="token plain"> keyGen </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">KeyPairGenerator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        keyGen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">initialize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> keyGen</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generateKeyPair</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">generateBase64KeyPair</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> keySize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">KeyPair</span><span class="token plain"> keyPair </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">generateKeyPair</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySize</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RSAPublicKey</span><span class="token plain"> pubKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RSAPublicKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> keyPair</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPublic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RSAPrivateKey</span><span class="token plain"> priKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RSAPrivateKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> keyPair</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPrivate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> keyMap </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HashMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        keyMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"private"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">toBase64String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEncoded</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        keyMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"public"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">toBase64String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pubKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEncoded</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> keyMap</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="Rsa-签名验签工具类">Rsa 签名验签工具类<a href="https://ituknown.github.io/blog/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/#Rsa-%E7%AD%BE%E5%90%8D%E9%AA%8C%E7%AD%BE%E5%B7%A5%E5%85%B7%E7%B1%BB" class="hash-link" aria-label="Rsa 签名验签工具类的直接链接" title="Rsa 签名验签工具类的直接链接" translate="no">​</a></h3>
<div class="language-java codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-java codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">nio</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">charset</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">spec</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">InvalidKeySpecException</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">spec</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">PKCS8EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">spec</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">X509EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">util</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">concurrent</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">Callable</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;p&gt;该类提供常见的 HashWithRSA 组合算法，用于提供数据签名和验签。&lt;/p&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;p&gt;HashWithRSA 指的是使用 RSA 加密算法结合哈希函数进行数字签名或数据加密。</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * RSA（Rivest–Shamir–Adleman）是一种非对称加密算法，而哈希函数则用于生成消息</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 摘要（即签名）。&lt;/p&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;p&gt;加密和签名的区别:</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 加密和签名都是为了安全性考虑，但有所不同。加密是为了防止信息被泄露，签名是为了防止信息被篡改。&lt;/p&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;h3&gt;加密过程：&lt;/h3&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;ul&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;li&gt;A生成一对密钥（公钥和私钥）。私钥不公开，A自己保留。公钥为公开的，任何人可以获取。&lt;/li&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;li&gt;A传递自己的公钥给B，B使用A的&lt;em&gt;公钥对消息进行加密&lt;/em&gt;。&lt;/li&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;li&gt;A接收到B加密的消息，利用A自己的&lt;em&gt;私钥对消息进行解密&lt;/em&gt;&lt;/li&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;/ul&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;p&gt;整个过程中，只用A的私钥才能对消息进行解密，防止消息被泄露。&lt;/p&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;h3&gt;签名过程:&lt;/h3&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;ul&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;li&gt;A生成一对密钥(公钥和私钥)。私钥不公开，A自己保留。公钥为公开的，任何人可以获取。&lt;/li&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;li&gt;A用自己的私钥对消息进行加签，形成签名，并将签名和消息本身一起传递给B。&lt;/li&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;li&gt;B收到消息后，通过A的公钥进行验签。如果验签成功，则证明消息是A发送的。&lt;/li&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;/ul&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;p&gt;整个过程，只有使用A私钥签名的消息才能被验签成功。即使知道了消息内容，也无法伪造签名，防止消息被篡改。</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">enum</span><span class="token plain"> </span><span class="token class-name">HashWithRSA</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">MD5withRSA</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"MD5withRSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">SHA1withRSA</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"SHA1withRSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">SHA256withRSA</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"SHA256withRSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">SHA384withRSA</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"SHA384withRSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">SHA512withRSA</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"SHA512withRSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">HashWithRSA</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">algorithm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 私钥签名</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param priKey    私钥</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param plaintext 原文</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> priKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeySpecException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SignatureException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 私钥证书</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PKCS8EncodedKeySpec</span><span class="token plain"> keySpec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">PKCS8EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PrivateKey</span><span class="token plain"> privateKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">KeyFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generatePrivate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySpec</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 进行签名</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Signature</span><span class="token plain"> spi </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Signature</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">algorithm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        spi</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">initSign</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">privateKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        spi</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">update</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> spi</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sign</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> priKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Callable</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> priKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Callable</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Callable</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> priKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Callable</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> priKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> priKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">signature</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">priKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 验签</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pubKey    公钥</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param plaintext 原文</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param signature 私钥签名{@link #signature(byte[], byte[])}</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> pubKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> signature</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeySpecException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SignatureException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 公钥证书</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">X509EncodedKeySpec</span><span class="token plain"> keySpec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">X509EncodedKeySpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pubKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PublicKey</span><span class="token plain"> publicKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">KeyFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"RSA"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generatePublic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySpec</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Signature</span><span class="token plain"> spi </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Signature</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">algorithm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        spi</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">initVerify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">publicKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        spi</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">update</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 验签</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> spi</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">signature</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> pubKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> signature</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeySpecException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SignatureException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pubKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> signature</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> pubKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> signature</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeySpecException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SignatureException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pubKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> signature</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> pubKeyBase64</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> signature</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeySpecException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SignatureException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pubKeyBase64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> signature</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">toBase64String</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> encoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name namespace" style="opacity:0.7">java</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name namespace" style="opacity:0.7">util</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name">Base64</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEncoder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">encodeToString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">encoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decodeBase64ToByte</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> decoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name namespace" style="opacity:0.7">java</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name namespace" style="opacity:0.7">util</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name">Base64</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getDecoder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">decoded</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@FunctionalInterface</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the function result</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="HMAC-工具类">HMAC 工具类<a href="https://ituknown.github.io/blog/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E4%B8%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF/#HMAC-%E5%B7%A5%E5%85%B7%E7%B1%BB" class="hash-link" aria-label="HMAC 工具类的直接链接" title="HMAC 工具类的直接链接" translate="no">​</a></h3>
<div class="language-java codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-java codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">org</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">apache</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">commons</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">codec</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">binary</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">Base64</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">org</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">apache</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">commons</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">codec</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">binary</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">Hex</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">javax</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">crypto</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">Mac</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">javax</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">crypto</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">spec</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">SecretKeySpec</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">nio</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">charset</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">InvalidKeyException</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token import namespace" style="opacity:0.7">java</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import namespace" style="opacity:0.7">security</span><span class="token import namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token import class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;p&gt;HMAC(Hash-based Message Authentication Code)是一种使用哈希函数</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 和秘密密钥来生成消息认证码的算法.&lt;/p&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;p&gt;HMAC通过将密钥混入哈希运算中,提供了一种更强大的消息认证方法,防范了一</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 些针对普通哈希的攻击.&lt;/p&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * &lt;p&gt;用于验证消息的完整性和认证消息发送者的身份.&lt;/p&gt;</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">enum</span><span class="token plain"> </span><span class="token class-name">Hmac</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">MD5</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"HmacMD5"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">SHA1</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"HmacSHA1"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">SHA256</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"HmacSHA256"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">SHA384</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"HmacSHA384"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">SHA512</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"HmacSHA512"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Hmac</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">algorithm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hmac</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> secret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Mac</span><span class="token plain"> mac </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Mac</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SecretKeySpec</span><span class="token plain"> keySpec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SecretKeySpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">secret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        mac</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySpec</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> mac</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doFinal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hmac</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> secret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Mac</span><span class="token plain"> mac </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Mac</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SecretKeySpec</span><span class="token plain"> keySpec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SecretKeySpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">secret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        mac</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keySpec</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> production</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mac</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doFinal</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hmacHex</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> secret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hmac</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">secret</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Hex</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">encodeHexString</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hmacBase64</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> secret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hmac</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">secret</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Base64</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">encodeBase64String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@FunctionalInterface</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">Production</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the function result</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">R</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">NoSuchAlgorithmException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InvalidKeyException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> secret </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"f$s1f@9."</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> plaintext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hello,world"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">out</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">println</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SHA1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">hmacHex</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">secret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">out</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">println</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SHA1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">hmacBase64</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">secret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plaintext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>]]></content:encoded>
            <category>加密</category>
        </item>
        <item>
            <title><![CDATA[分区表 GPT vs MBR]]></title>
            <link>https://ituknown.github.io/blog/分区表-GPT-vs-MBR/</link>
            <guid>https://ituknown.github.io/blog/分区表-GPT-vs-MBR/</guid>
            <pubDate>Sat, 14 Jan 2023 21:57:00 GMT</pubDate>
            <description><![CDATA[关于 GPT 和 MBR]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="关于-GPT-和-MBR">关于 GPT 和 MBR<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#%E5%85%B3%E4%BA%8E-GPT-%E5%92%8C-MBR" class="hash-link" aria-label="关于 GPT 和 MBR的直接链接" title="关于 GPT 和 MBR的直接链接" translate="no">​</a></h2>
<p>在做磁盘分区时，经常会看到类似使用 GPT 分区还是 MBR 分区的提示，对电脑不熟悉的用户来说，并不清楚 GPT 和 MBR 是什么，区别是什么，更不知道如何选择。</p>
<p><strong>MBR分区：</strong></p>
<p>MBR是单词 master boot record 的缩写，通常被称为主引导记录或主引导扇区。</p>
<p>它的运行机制存在于硬件的基础之上，是存在于磁盘驱动器开始部分的一个特殊的启动扇区。这个扇区包含了已安装的操作系统的启动信息，并用来启动系统。如果你安装了Windows，其启动信息就放在这一段代码中。</p>
<p>如果MBR的信息损坏或被误删，就会导致不能正常启动Windows（比如启动蓝屏）。这个时候你就需要找一个引导修复软件工具来修复它就可以了。</p>
<p>而在 Linux 系统中MBR通常会是GRUB加载器（比如在安装 ubuntu 时，安装到最后一步时通常会询问是否安装 GURB 引导）。</p>
<p>当一台电脑启动时，它会先启动主板自带的BIOS系统，bios加载MBR，MBR再启动操作系统（Windows 或 Linux），这就是mbr的启动过程。</p>
<p><strong>GPT：</strong></p>
<p>GPT的意思是GUID Partition Table，即“全局唯一标识磁盘分区表”。他是另外一种更加先进新颖的磁盘组织方式，一种使用UEFI启动的磁盘组织方式。</p>
<p>最开始是为了更好的兼容性，后来因为其更大的内存支持（mbr分区最多支持2T的磁盘），更多的兼容而被广泛使用，特别是苹果的MAC系统全部使用gpt分区。</p>
<p>gtp不在有分区的概念，所有CDEF盘都在一段信息中存储。可以简单的理解为更先进但是使用不够广泛的技术。</p>
<p>不过因为兼容问题，gpt其实在引导的最开始部分也有一段mbr引导，也叫做“保护引导”，为了防止设备不支持 uefi。</p>
<p><strong>优缺点：</strong></p>
<p>1）MBR分区表最多只能识别2TB左右的空间，大于2TB的容量将无法识别从而导致硬盘空间浪费；GPT分区表理论上是没有上限的。</p>
<p>2）MBR分区表最多只能支持4个主分区或三个主分区+1个扩展分区(逻辑分区不限制)；GPT分区表在Windows系统下可以支持128个主分区。</p>
<p>3）在MBR中，分区表的大小是固定的；在GPT分区表头中可自定义分区数量的最大值，也就是说GPT分区表的大小不是固定的。</p>
<p><strong>该如何选择？</strong></p>
<p>建议一：如果你对电脑不太懂，那么建议你直接使用MBR，因为大多数电脑默认都是MBR bios启动，如果你选择了gpt那么你必须在bios下设置启动项，对于一个新人来说比较复杂，每家电脑的主板还有不同无疑增加了难度。</p>
<p>建议二：如果你的硬盘超过2T，那么你必须选择GPT+UEFI，2t以下就无所谓了。</p>
<p>建议三：分区类型与主板也有关系，如果你的电脑是传统的BIOS主板，那建议继续使用MBR分区模式，若是UEFI主板的话，则推荐使用GPT。</p>
<p>建议四：如果需要重装系统，在重装前要了解清楚所安装的系统版本是否支持MBR或者UEFI，这就是所谓的“兼容性”（比如 win11 已经不支持 MBR 了）。</p>
<p>最后：如果你对电脑比较精通，建议你直接淦gpt。毕竟gpt代表了未来，可以预见早晚uefi会会替代掉bios。</p>
<p>总结下来就是：BIOS主板 + MBR，UEFI主板 + GPT。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="查看操作系统是uefi启动还是bios启动">查看操作系统是uefi启动还是bios启动<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#%E6%9F%A5%E7%9C%8B%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%98%AFuefi%E5%90%AF%E5%8A%A8%E8%BF%98%E6%98%AFbios%E5%90%AF%E5%8A%A8" class="hash-link" aria-label="查看操作系统是uefi启动还是bios启动的直接链接" title="查看操作系统是uefi启动还是bios启动的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="Windows-系统">Windows 系统<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#Windows-%E7%B3%BB%E7%BB%9F" class="hash-link" aria-label="Windows 系统的直接链接" title="Windows 系统的直接链接" translate="no">​</a></h3>
<p>使用快捷键 win+R 打开命令提示符，输入 <code>msinfo32</code> 并点击确认：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/GPTvsMBR/msinfo32-1673242441xDDNU8SPCS.png" alt="msinfo32-1673242441xDDNU8SPCS.png" class="img_o99Q"></p>
<p>然后在右侧找到 “BIOS模式” 行，查看其是 “传统” 还是 “UEFI”（传统表示的就是 BIOS）。</p>
<p>UEFI 示例：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/GPTvsMBR/sysinfo-uefi-1673319414qK0cbuV5.png" alt="sysinfo-uefi-1673319414qK0cbuV5.png" class="img_o99Q"></p>
<p>传统BIOS 示例：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/GPTvsMBR/sysinfo-bios-1673242395plN1tppTTo.png" alt="sysinfo-bios-1673242395plN1tppTTo.png" class="img_o99Q"></p>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>NOTE</div><div class="admonitionContent_Q31J"><p>也可以直接在 Windows 搜索栏中输入“系统信息”快速打开。</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="Linux-系统">Linux 系统<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#Linux-%E7%B3%BB%E7%BB%9F" class="hash-link" aria-label="Linux 系统的直接链接" title="Linux 系统的直接链接" translate="no">​</a></h3>
<p>在直接 Terminal 中运行以下命令即可，查看系统是 BIOS 引导还是 UEFI 引导：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> /sys/firmware/efi </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> UEFI </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> BIOS</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>NOTE</div><div class="admonitionContent_Q31J"><p><code>-d</code> 判断目录是否存在，存在为真不存在为假。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="查看磁盘分区类型">查看磁盘分区类型<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#%E6%9F%A5%E7%9C%8B%E7%A3%81%E7%9B%98%E5%88%86%E5%8C%BA%E7%B1%BB%E5%9E%8B" class="hash-link" aria-label="查看磁盘分区类型的直接链接" title="查看磁盘分区类型的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="Windows-系统-1">Windows 系统<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#Windows-%E7%B3%BB%E7%BB%9F-1" class="hash-link" aria-label="Windows 系统的直接链接" title="Windows 系统的直接链接" translate="no">​</a></h3>
<p>使用快捷键 win+R 打开命令提示符，输入 <code>diskpart</code> 并点击确认来启动 diskpart 实用程序命令行工具：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/GPTvsMBR/diskpart-16732558517qAstK6w.png" alt="diskpart-16732558517qAstK6w.png" class="img_o99Q"></p>
<p>然后，在命令行中键入 <code>list disk</code> 命令，然后按 Enter：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/GPTvsMBR/wincmd-list-disk-1673319250sP9z52y4.png" alt="wincmd-list-disk-1673319250sP9z52y4.png" class="img_o99Q"></p>
<p>在上面的示例中，注意看“Gpt”列信息。如果有符号 <code>*</code> 则表示该行对应的磁盘使用的是 GPT 分区类型，否者就是 MBR。比如我这里有符号 <code>*</code> 就表示 GPT 分区类型。</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="Linux-系统-1">Linux 系统<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#Linux-%E7%B3%BB%E7%BB%9F-1" class="hash-link" aria-label="Linux 系统的直接链接" title="Linux 系统的直接链接" translate="no">​</a></h3>
<p>查看所有磁盘分区类型：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">parted</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Model: ATA MXPG2D80-240GH </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">scsi</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Disk /dev/sda: 240GB</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Sector size </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">logical/physical</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">: 512B/512B</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Partition Table: gpt                         </span><span class="token comment" style="color:#999988;font-style:italic">## 分区类型 GPT, 如果是 MBR 这里显示的就是 msdos 或 dos</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Disk Flags:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Number  Start   End    Size   File system  Name                  Flags</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain">      1049kB  538MB  537MB  fat32        EFI System Partition  boot, esp</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain">      538MB   240GB  240GB  ext4</span><br></div></code></pre></div></div>
<p>也可以查看指定磁盘的分区类型（以 /dev/sda 为例）：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">parted</span><span class="token plain"> /dev/sda print</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="修改分区类型">修改分区类型<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#%E4%BF%AE%E6%94%B9%E5%88%86%E5%8C%BA%E7%B1%BB%E5%9E%8B" class="hash-link" aria-label="修改分区类型的直接链接" title="修改分区类型的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="Windows-系统-2">Windows 系统<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#Windows-%E7%B3%BB%E7%BB%9F-2" class="hash-link" aria-label="Windows 系统的直接链接" title="Windows 系统的直接链接" translate="no">​</a></h3>
<p>使用快捷键 win+R 打开命令提示符，输入 <code>diskpart</code> 并点击确认来启动 diskpart 实用程序命令行工具：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/GPTvsMBR/diskpart-16732558517qAstK6w.png" alt="diskpart-16732558517qAstK6w.png" class="img_o99Q"></p>
<p>使用 <code>list disk</code> 命令确认下当前磁盘分区（比如我这里是 GPT）：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/GPTvsMBR/wincmd-list-disk-1673319250sP9z52y4.png" alt="wincmd-list-disk-1673319250sP9z52y4.png" class="img_o99Q"></p>
<p>想要修改磁盘分区只需使用 <code>convert</code> 命令修改为目标分区即可。</p>
<p>转换成 MBR 分区：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">convert mbr</span><br></div></code></pre></div></div>
<p>转换成 GPT 分区：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">convert gpt</span><br></div></code></pre></div></div>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/GPTvsMBR/win-convert-disktable-1673704205sR286tjh.png" alt="win-convert-disktable-1673704205sR286tjh.png" class="img_o99Q"></p>
<p>因为演示，我这里就不去真正的执行了~</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="Linux-系统-2">Linux 系统<a href="https://ituknown.github.io/blog/%E5%88%86%E5%8C%BA%E8%A1%A8-GPT-vs-MBR/#Linux-%E7%B3%BB%E7%BB%9F-2" class="hash-link" aria-label="Linux 系统的直接链接" title="Linux 系统的直接链接" translate="no">​</a></h3>
<p>在 Linux 上，修改分区类型一般都使用 <code>parted</code> 命令。以 <code>/dev/sda</code> 为例：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">parted</span><span class="token plain"> /dev/sda</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">GNU Parted </span><span class="token number" style="color:#36acaa">3.3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Using /dev/sda</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Welcome to GNU Parted</span><span class="token operator" style="color:#393A34">!</span><span class="token plain"> Type </span><span class="token string" style="color:#e3116c">'help'</span><span class="token plain"> to view a list of commands.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parted</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>如果不知道该怎么使用，可以通过输入 help 命令来获取帮助。</p>
<p>使用 <code>mktable</code> 命令将磁盘分区类型修改为 msdos：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parted</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> mktable</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">New disk label type? msdos</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Warning: The existing disk label on /dev/sda will be destroyed and all data on this disk will be lost. Do you want to continue?</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Yes/No? </span><span class="token function" style="color:#d73a49">yes</span><br></div></code></pre></div></div>
<p><strong>特别说明：</strong> 按照习惯来说MBR格式在 Linux 下通常称作dos，如果在“New disk label type?”后输入dos或者mbr会提示无效命令，这时候要用 <code>help mktable</code> 查看帮助信息来确认MBR分区在 parted 命令中具体的名称，示例：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parted</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token builtin class-name">help</span><span class="token plain"> mktable</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  mklabel,mktable LABEL-TYPE               create a new disklabel </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">partition table</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">LABEL-TYPE is one of: aix, amiga, bsd, dvh, gpt, mac, msdos, pc98, sun, atari, loop</span><br></div></code></pre></div></div>]]></content:encoded>
            <category>软硬件</category>
        </item>
        <item>
            <title><![CDATA[YAML 语法]]></title>
            <link>https://ituknown.github.io/blog/YAML-语法/</link>
            <guid>https://ituknown.github.io/blog/YAML-语法/</guid>
            <pubDate>Sat, 18 Jun 2022 17:37:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="前言">前言<a href="https://ituknown.github.io/blog/YAML-%E8%AF%AD%E6%B3%95/#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接链接" title="前言的直接链接" translate="no">​</a></h2>
<p>本文档旨在作为一个简短的 YAML 教程，足以让你开始使用YAML语言。</p>
<p>YAML是一种基于缩进的标记语言，其目标是既易于阅读又易于编写。许多项目使用它是因为它的可读性、简单性以及对许多编程语言的良好支持。</p>
<p>YAML 示例：</p>
<div class="language-yaml codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-yaml codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">execution</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">concurrency</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">hold-for</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 5m</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ramp-up</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 2m</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">scenario</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> yaml_example</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">scenarios</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">yaml_example</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">retrieve-resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">requests</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//example.com/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">reporting</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">module</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> final</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">stats</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">module</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> console</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">settings</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">check-interval</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 5s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">default-executor</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> jmeter</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">provisioning</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> local</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>注意</div><div class="admonitionContent_Q31J"><p>冒号后面必须有空格。</p></div></div>
<p>从示例中可以看到，YAML使用缩进来表示文档结构（与JSON相反，JSON使用括号和大括号）。除此之外，JSON 和 YAML 非常相似。下面是将上面 YAML 转换为 JSON 后的数据：</p>
<div class="language-json codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-json codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"execution"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"concurrency"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"hold-for"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"5m"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"ramp-up"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"2m"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"scenario"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"json_example"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"scenarios"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"json_example"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"retrieve-resources"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"requests"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"http://example.com/"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"reporting"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"module"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"final-stats"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"module"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"console"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"settings"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"check-interval"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"5s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"default-executor"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"jmeter"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"provisioning"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"local"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="普通值数字字符串布尔值">普通值：数字、字符串、布尔值<a href="https://ituknown.github.io/blog/YAML-%E8%AF%AD%E6%B3%95/#%E6%99%AE%E9%80%9A%E5%80%BC%E6%95%B0%E5%AD%97%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%83%E5%B0%94%E5%80%BC" class="hash-link" aria-label="普通值：数字、字符串、布尔值的直接链接" title="普通值：数字、字符串、布尔值的直接链接" translate="no">​</a></h2>
<div class="language-yaml codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-yaml codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">number-value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">42</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">floating-point-value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.141592</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">boolean-value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">## strings can be both 'single-quoted` and "double-quoted"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">string-value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Bonjour'</span><br></div></code></pre></div></div>
<p>对应的 JSON 数据：</p>
<div class="language-json codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-json codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"number-value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">42</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"floating-point-value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.141592</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"boolean-value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"string-value"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Bonjour"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>出于方便的原因，YAML语法还允许不带引号的字符串值：</p>
<div class="language-yaml codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-yaml codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">unquoted-string</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Hello World</span><br></div></code></pre></div></div>
<p>对应的 JSON 数据：</p>
<div class="language-json codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-json codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"unquoted-string"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Hello World"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="集合和字典">集合和字典<a href="https://ituknown.github.io/blog/YAML-%E8%AF%AD%E6%B3%95/#%E9%9B%86%E5%90%88%E5%92%8C%E5%AD%97%E5%85%B8" class="hash-link" aria-label="集合和字典的直接链接" title="集合和字典的直接链接" translate="no">​</a></h2>
<p>集合中的每个元素都必须缩进，并以 <code>-</code> 和空格开头：</p>
<div class="language-yaml codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-yaml codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">jedis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> Yoda</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> Qui</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Gon Jinn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> Obi</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Wan Kenobi</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> Luke Skywalker</span><br></div></code></pre></div></div>
<p>对应的 JSON 数据：</p>
<div class="language-json codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-json codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"jedis"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"Yoda"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"Qui-Gon Jinn"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"Obi-Wan Kenobi"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"Luke Skywalker"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>字典是键值映射的集合，所有 key 都区分大小写：</p>
<div class="language-yaml codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-yaml codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">jedi</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Obi</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Wan Kenobi</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">home-planet</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Stewjon</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">species</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> human</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">master</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Qui</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Gon Jinn</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">height</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 1.82m</span><br></div></code></pre></div></div>
<p>对应的 JSON 数据：</p>
<div class="language-json codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-json codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"jedi"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Obi-Wan Kenobi"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"home-planet"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Stewjon"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"species"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"human"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"master"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Qui-Gon Jinn"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"height"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"1.82m"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>另外，字典和集合可以互相嵌套，反之亦然：</p>
<div class="language-yaml codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-yaml codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">requests</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># first item of `requests` list is just a string</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//example.com/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># second item of `requests` list is a dictionary</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">url</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//example.com/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">method</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> GET</span><br></div></code></pre></div></div>
<p>对应的 JSON 数据：</p>
<div class="language-json codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-json codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"requests"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"http:\/\/example.com\/"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"url"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http:\/\/example.com\/"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"method"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"GET"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>如果需要，还可以对列表和字典使用内联语法：</p>
<div class="language-yaml codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-yaml codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">episodes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">7</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">best-jedi</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Obi</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Wan</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">side</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> light</span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-json codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-json codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"episodes"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">7</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"best-jedi"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"name"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Obi-Wan"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"side"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"light"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>]]></content:encoded>
            <category>YAML</category>
        </item>
        <item>
            <title><![CDATA[进制转换]]></title>
            <link>https://ituknown.github.io/blog/进制转换/</link>
            <guid>https://ituknown.github.io/blog/进制转换/</guid>
            <pubDate>Thu, 24 Feb 2022 10:31:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="前言">前言<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接链接" title="前言的直接链接" translate="no">​</a></h2>
<p>在我们的各种计算机编程语言中，对于数值通常都有四种进制表示。分别是：二进制、八进制、十进制以及十六进制。</p>
<p>千万不要被这些名词吓住了，其实所谓的几进制就是逢几进一的意思。比如我们在日常生活中使用的阿拉伯表示的几百几千，就是十进制表示法。</p>
<p>为什么说是十进制表示法呢？因为它的数字范围是 0-9，要想表示十这个数只能使用 10 表示。也就是满 10 进 1，将低位重置归 0 来计算。</p>
<p>同理，二进制表示法就是满 2 进 1，也就是它的数字范围是 0 和 1。比如二进制的 10 表示的其实是阿拉伯数字 2。特别强调的一点是，在当前的计算机各大编程语言中是没有对应的二进制表示法的，它属于计算机底层知识。虽然没法表示，但是我们需要知道二进制的原理。</p>
<p>不同于二进制，对于八进制和十六进制在各种编程语言中是可以直接书写的。八进制的数字范围是 0-7，满 8 进 1。在编程语言中通常使用 0 做前缀表示八进制，比如 010 就是八进制表示法，它对应的阿拉伯数字是 8，011 自然就是 9 了。</p>
<p>十六进制使用 0-9 及 A-F 表示。A 表示的就是十进制的 10，以此类推 F 表示的就是十进制的 15 了（A-F 不区分大小写）。在编程编程语言中使用 0x 或 0X 作为前缀表示十六进制。比如 0x1A 就是十进制的 26 了。</p>
<p>为了更方便于理解进制的关系我们来使用一个 table 表格看下 0-20 在十进制、二进制、八进制以及十六进制中分别如何表示：</p>
<table><thead><tr><th style="text-align:left"><strong>十进制</strong></th><th style="text-align:left"><strong>二进制</strong></th><th style="text-align:left"><strong>八进制</strong></th><th style="text-align:left"><strong>十六进制</strong></th></tr></thead><tbody><tr><td style="text-align:left">0</td><td style="text-align:left">0</td><td style="text-align:left">0</td><td style="text-align:left">0</td></tr><tr><td style="text-align:left">1</td><td style="text-align:left">1</td><td style="text-align:left">1</td><td style="text-align:left">1</td></tr><tr><td style="text-align:left">2</td><td style="text-align:left">10</td><td style="text-align:left">2</td><td style="text-align:left">2</td></tr><tr><td style="text-align:left">3</td><td style="text-align:left">11</td><td style="text-align:left">3</td><td style="text-align:left">3</td></tr><tr><td style="text-align:left">4</td><td style="text-align:left">20</td><td style="text-align:left">4</td><td style="text-align:left">4</td></tr><tr><td style="text-align:left">5</td><td style="text-align:left">21</td><td style="text-align:left">5</td><td style="text-align:left">5</td></tr><tr><td style="text-align:left">6</td><td style="text-align:left">30</td><td style="text-align:left">6</td><td style="text-align:left">6</td></tr><tr><td style="text-align:left">7</td><td style="text-align:left">31</td><td style="text-align:left">7</td><td style="text-align:left">7</td></tr><tr><td style="text-align:left">8</td><td style="text-align:left">40</td><td style="text-align:left">10</td><td style="text-align:left">8</td></tr><tr><td style="text-align:left">9</td><td style="text-align:left">41</td><td style="text-align:left">11</td><td style="text-align:left">9</td></tr><tr><td style="text-align:left">10</td><td style="text-align:left">50</td><td style="text-align:left">12</td><td style="text-align:left">A</td></tr><tr><td style="text-align:left">11</td><td style="text-align:left">51</td><td style="text-align:left">13</td><td style="text-align:left">B</td></tr><tr><td style="text-align:left">12</td><td style="text-align:left">60</td><td style="text-align:left">14</td><td style="text-align:left">C</td></tr><tr><td style="text-align:left">13</td><td style="text-align:left">61</td><td style="text-align:left">15</td><td style="text-align:left">D</td></tr><tr><td style="text-align:left">14</td><td style="text-align:left">70</td><td style="text-align:left">16</td><td style="text-align:left">E</td></tr><tr><td style="text-align:left">15</td><td style="text-align:left">71</td><td style="text-align:left">17</td><td style="text-align:left">F</td></tr><tr><td style="text-align:left">16</td><td style="text-align:left">80</td><td style="text-align:left">20</td><td style="text-align:left">10</td></tr><tr><td style="text-align:left">17</td><td style="text-align:left">81</td><td style="text-align:left">21</td><td style="text-align:left">11</td></tr><tr><td style="text-align:left">18</td><td style="text-align:left">90</td><td style="text-align:left">22</td><td style="text-align:left">12</td></tr></tbody></table>
<p>知道了十进制与其他进制的对应关系后我们再来看下在编程语言中如何表示八进制、十进制以及十六进制。下面以 Java 语言为例来看下数字 20 如何表示：</p>
<div class="language-java codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-java codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 八进制</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> octal </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">024</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 十进制</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> decimal </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 十六进制</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> hex </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0x14</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>提示</div><div class="admonitionContent_Q31J"><p>特别强调的一点是，编程语言是没有二进制表示法的。二进制属于计算机底层的东西，高级编程语言无法表示。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="其他进制转十进制">其他进制转十进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%85%B6%E4%BB%96%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%8D%81%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="其他进制转十进制的直接链接" title="其他进制转十进制的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="二进制转十进制">二进制转十进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E4%BA%8C%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%8D%81%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="二进制转十进制的直接链接" title="二进制转十进制的直接链接" translate="no">​</a></h3>
<p><strong>规则：</strong> 从最低为开始（右边的表示低位），将每个位置上的数提取出来，乘以2的（位数-1）次方，然后求和。</p>
<p>案例：</p>
<img alt="BinaryToDecimalExample-1645670305uAsR3E" width="50%" src="https://media.ituknown.org/blog-media/BinaryConversion/ToDecimal/BinaryToDecimalExample-1645670305uAsR3E.png">
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="八进制转十进制">八进制转十进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%85%AB%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%8D%81%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="八进制转十进制的直接链接" title="八进制转十进制的直接链接" translate="no">​</a></h3>
<p><strong>规则：</strong> 从最低为开始（右边的表示低位），将每个位置上的数提取出来，乘以8的（位数-1）次方，然后求和。</p>
<p>案例：</p>
<img alt="OctalToDecimalExample-164567036278x12U" width="50%" src="https://media.ituknown.org/blog-media/BinaryConversion/ToDecimal/OctalToDecimalExample-164567036278x12U.png">
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="十六进制转十进制">十六进制转十进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%8D%81%E5%85%AD%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%8D%81%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="十六进制转十进制的直接链接" title="十六进制转十进制的直接链接" translate="no">​</a></h3>
<p><strong>规则：</strong> 从最低为开始（右边的表示低位），将每个位置上的数提取出来，乘以16的（位数-1）次方，然后求和。</p>
<p>案例：</p>
<img alt="HexToDecimalExample-1645670349WjWC1S" width="50%" src="https://media.ituknown.org/blog-media/BinaryConversion/ToDecimal/HexToDecimalExample-1645670349WjWC1S.png">
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="其他进制转二进制">其他进制转二进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%85%B6%E4%BB%96%E8%BF%9B%E5%88%B6%E8%BD%AC%E4%BA%8C%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="其他进制转二进制的直接链接" title="其他进制转二进制的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="十进制转二进制">十进制转二进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%8D%81%E8%BF%9B%E5%88%B6%E8%BD%AC%E4%BA%8C%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="十进制转二进制的直接链接" title="十进制转二进制的直接链接" translate="no">​</a></h3>
<img alt="DecimalToBinaryExample-1645682713zWlbtk" height="250" src="https://media.ituknown.org/blog-media/BinaryConversion/ToBinary/DecimalToBinaryExample-1645682713zWlbtk.png">
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="八进制转二进制">八进制转二进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%85%AB%E8%BF%9B%E5%88%B6%E8%BD%AC%E4%BA%8C%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="八进制转二进制的直接链接" title="八进制转二进制的直接链接" translate="no">​</a></h3>
<img alt="OctalToBinaryExample-1645694398WWlBKH" height="250" src="https://media.ituknown.org/blog-media/BinaryConversion/ToBinary/OctalToBinaryExample-1645694398WWlBKH.png">
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="十六进制转二进制">十六进制转二进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%8D%81%E5%85%AD%E8%BF%9B%E5%88%B6%E8%BD%AC%E4%BA%8C%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="十六进制转二进制的直接链接" title="十六进制转二进制的直接链接" translate="no">​</a></h3>
<img alt="HexToBinaryExample-1645693837u7rGEE" height="250" src="https://media.ituknown.org/blog-media/BinaryConversion/ToBinary/HexToBinaryExample-1645693837u7rGEE.png">
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="其他进制转十六进制">其他进制转十六进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%85%B6%E4%BB%96%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%8D%81%E5%85%AD%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="其他进制转十六进制的直接链接" title="其他进制转十六进制的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="二进制转十六进制">二进制转十六进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E4%BA%8C%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%8D%81%E5%85%AD%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="二进制转十六进制的直接链接" title="二进制转十六进制的直接链接" translate="no">​</a></h3>
<img alt="BinaryToHexExample-1645695762RhnsuO" height="250" src="https://media.ituknown.org/blog-media/BinaryConversion/ToHex/BinaryToHexExample-1645695762RhnsuO.png">
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="十进制转十六进制">十进制转十六进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%8D%81%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%8D%81%E5%85%AD%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="十进制转十六进制的直接链接" title="十进制转十六进制的直接链接" translate="no">​</a></h3>
<img alt="DecimalToHexExample-1645769621ISs7S2" height="250" src="https://media.ituknown.org/blog-media/BinaryConversion/ToHex/DecimalToHexExample-1645769621ISs7S2.png">
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="其他进制转八进制">其他进制转八进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%85%B6%E4%BB%96%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%85%AB%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="其他进制转八进制的直接链接" title="其他进制转八进制的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="二进制转八进制">二进制转八进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E4%BA%8C%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%85%AB%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="二进制转八进制的直接链接" title="二进制转八进制的直接链接" translate="no">​</a></h3>
<img alt="BinaryToOctal-1645695842xVUzg9" height="250" src="https://media.ituknown.org/blog-media/BinaryConversion/ToOctal/BinaryToOctal-1645695842xVUzg9.png">
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="十进制转八进制">十进制转八进制<a href="https://ituknown.github.io/blog/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/#%E5%8D%81%E8%BF%9B%E5%88%B6%E8%BD%AC%E5%85%AB%E8%BF%9B%E5%88%B6" class="hash-link" aria-label="十进制转八进制的直接链接" title="十进制转八进制的直接链接" translate="no">​</a></h3>
<img alt="DecimalToOctal-1645775748XFPsZ3" height="250" src="https://media.ituknown.org/blog-media/BinaryConversion/ToOctal/DecimalToOctal-1645775748XFPsZ3.png">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[yt-dlp 工具常用方式]]></title>
            <link>https://ituknown.github.io/blog/yt-dlp-工具常用方式/</link>
            <guid>https://ituknown.github.io/blog/yt-dlp-工具常用方式/</guid>
            <pubDate>Thu, 17 Feb 2022 21:20:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="前言">前言<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接链接" title="前言的直接链接" translate="no">​</a></h2>
<p><a href="https://github.com/yt-dlp/yt-dlp" target="_blank" rel="noopener noreferrer" class="">yt-dlp</a> 是一款基于 <a href="https://github.com/ytdl-org/youtube-dl" target="_blank" rel="noopener noreferrer" class="">youtube-dl</a> 和 <a href="https://github.com/blackjack4494/yt-dlc" target="_blank" rel="noopener noreferrer" class="">youtube-dlc</a> 二次开发的命令行下的视频下载工具。</p>
<p>在此之前，大家可能用的都是 youtube-dl，不可否认我也在用。但实在受不了 youtube-dl 的下载速度，当我知道 yt-dlp 后立马将 youtube-dl 抛弃了。</p>
<p>yt-dlp 工具将 youtube-dl 与 youtube-dlc 做了整合，同时内部增加了多线程下载并做了一些定制化修改。我在使用过发现 yt-dlp 能将速度提到极致。</p>
<p>下面以某国漫（<a href="https://www.youtube.com/watch?v=lHvamusTCK0" target="_blank" rel="noopener noreferrer" class="">https://www.youtube.com/watch?v=lHvamusTCK0</a>）为例，使用 youtube-dl 和 yt-dlp 的下载速度对比：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/yt-dlp/yt-dlp-vs-youtube-dl-1645151899Jfx19M.png" alt="yt-dlp-vs-youtube-dl-1645151899Jfx19M" class="img_o99Q"></p>
<p>很明显，yt-dlp 的下载速度将 youtube-dl 甩了几条街。</p>
<p>yt-dlp 是基于 youtube-dl 二次开发，<strong>是 YouTube 的专属下载工具</strong>。另外，该工具还支持其他的视频网站。比如国内的优酷、爱奇艺、 bilibili 等。</p>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>小提示</div><div class="admonitionContent_Q31J"><p>因为 yt-dlp 是基于 youtube-dl 和 youtube-dlc 做的二次开发，所以在使用时他们的命令及参数基本一致。所以下面的命令说明同样适用于 youtube-dl 和 youtube-dlc。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="下载及安装">下载及安装<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E4%B8%8B%E8%BD%BD%E5%8F%8A%E5%AE%89%E8%A3%85" class="hash-link" aria-label="下载及安装的直接链接" title="下载及安装的直接链接" translate="no">​</a></h2>
<p>yt-dlp 的 Github 仓库地址是：<a href="https://github.com/yt-dlp/yt-dlp" target="_blank" rel="noopener noreferrer" class="">https://github.com/yt-dlp/yt-dlp</a>。</p>
<p>在仓库的 README 说明中有介绍各种操作系统（Unix/Mac/Windows）的安装方式。另外，也可以直接到 <a href="https://github.com/yt-dlp/yt-dlp/releases" target="_blank" rel="noopener noreferrer" class="">releases</a> 页面下载二进制安装包进行安装。</p>
<p>不过，推荐使用 pip 包管理安装：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">pip3 </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-U</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"yt-dlp[default]"</span><br></div></code></pre></div></div>
<p>后续如果想升级，再执行一次该命令即可。</p>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>不想使用 pip 包管理？</div><div class="admonitionContent_Q31J"><p>如果你不想使用 pip，在 Unix（MacOS、Linux、BSD）上也可以使用 <code>curl</code>、<code>wget</code> 及 <code>aria2c</code> 等工具下载，之后直接设置执行权限即可：</p><p>curl：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-L</span><span class="token plain"> https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> /usr/local/bin/yt-dlp</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">chmod</span><span class="token plain"> a+rx /usr/local/bin/yt-dlp</span><br></div></code></pre></div></div><p>wget：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">wget</span><span class="token plain"> https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-O</span><span class="token plain"> /usr/local/bin/yt-dlp</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">chmod</span><span class="token plain"> a+rx /usr/local/bin/yt-dlp</span><br></div></code></pre></div></div><p>aria2c：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> aria2c https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp </span><span class="token parameter variable" style="color:#36acaa">--dir</span><span class="token plain"> /usr/local/bin </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> yt-dlp</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">chmod</span><span class="token plain"> a+rx /usr/local/bin/yt-dlp</span><br></div></code></pre></div></div><p>另外，MacOS 如果使用了 HomeBrew 包管理工具的话，也可以直接使用 brew 命令进行安装：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">brew </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> yt-dlp</span><br></div></code></pre></div></div><p>对于 Windows 系统，也可以直接到 <a href="https://github.com/yt-dlp/yt-dlp/releases" target="_blank" rel="noopener noreferrer" class="">releases</a> 页面下载二进制程序包，之后配置下环境变量也行。</p></div></div>
<div class="theme-admonition theme-admonition-danger admonition_fnQa alert alert--danger"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>注意</div><div class="admonitionContent_Q31J"><p>yt-dlp 在视频合成时基于 ffmpeg，虽然在程序包中有内置 ffmpeg。但还是推荐在操作系统上单独安装一次，防止视频下载后在进行合并音视频的出现未知错误。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="音视频下载">音视频下载<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E9%9F%B3%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD" class="hash-link" aria-label="音视频下载的直接链接" title="音视频下载的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="默认方式下载命令">默认方式下载命令<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E9%BB%98%E8%AE%A4%E6%96%B9%E5%BC%8F%E4%B8%8B%E8%BD%BD%E5%91%BD%E4%BB%A4" class="hash-link" aria-label="默认方式下载命令的直接链接" title="默认方式下载命令的直接链接" translate="no">​</a></h3>
<p>yt-dlp 下载 Youtube 视频很简单，只需要拷贝浏览器地址栏上的视频链接即可：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp https://www.youtube.com/watch?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">lHvamusTCK0</span><br></div></code></pre></div></div>
<p>默认情况下，yt-dlp 会自动选择一个视频。</p>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Note</div><div class="admonitionContent_Q31J"><p>YouTube 上的视频都是使用 v 参数指定（就是 av 的意思，同 bilibili）。v 后面的值就是视频号，我们可以直接通过视频号找到指定视频。对于视频专栏（系列视频）则使用 list 参数指定系列号。</p></div></div>
<p>需要特别强调了是：YouTube 上的视频采用音视频分离的方式。如果安装了 ffmpeg，yt-dlp 默认会下载质量最高的视频和音频并进行合并，这也是为什么在之前推荐单独安装 ffmpeg 的原因。</p>
<p>默认情况下，yt-dlp 会自动下载适合的音视频进行合并（如果操作系统中有 ffmpeg 的话默认会下载质量最高的音视频），不过我们也可以借助 <code>-F</code> 和 <code>-f</code> 参数选择下载指定质量的音视频。</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="列出所有的音视频文件">列出所有的音视频文件<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E7%9A%84%E9%9F%B3%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6" class="hash-link" aria-label="列出所有的音视频文件的直接链接" title="列出所有的音视频文件的直接链接" translate="no">​</a></h3>
<p>使用 <code>-F</code> 参数可以列出指定视频链接的全部音视频文件：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-F</span><span class="token plain"> https://www.youtube.com/watch?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">lHvamusTCK0</span><br></div></code></pre></div></div>
<p>输出示例：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/yt-dlp/yt-dlp-v-F-1645153235ABnGuv.png" alt="yt-dlp-v-F-1645153235ABnGuv" class="img_o99Q"></p>
<p>注意看输出示例中的 VCODEC 栏信息，共分为三类，分别是 images、audio only 和 videi only。也就是说 Youtube 上的视频是音视频分开的。如果你仅仅下载 video only 文件是只有画面没有声音，只下载 audio only 文件则只有声音没有画面。因此在下载时需要同时下载一个 audio only 文件和一个 video only 文件（yt-dlp 默认下载方式会自动下载音视频文件）。</p>
<p>另外，video only 文件分为两类流媒体格式，分别是 mp4 和 webm。webm 是谷歌推出的流媒体格式，与 mp4 区别不大，可以参考文章最后的 webm 文件说明。</p>
<p>输出栏中还有一列 ID 字段，这个是流媒体文件标识，如果想要下载指定的质量的流媒体就需要使用 <code>-f</code> 参数指定该 ID（下面会进行说明）。</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="下载指定音视频文件">下载指定音视频文件<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E4%B8%8B%E8%BD%BD%E6%8C%87%E5%AE%9A%E9%9F%B3%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6" class="hash-link" aria-label="下载指定音视频文件的直接链接" title="下载指定音视频文件的直接链接" translate="no">​</a></h3>
<p><code>-f</code> 参数则用于下载指定的文件。比如上面示例中的 1920x1080 的 mp4 视频文件，对应的 ID 为 137：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">137 mp4   1920x1080   25 │    1.24GiB 1158k https │ avc1.640028   1158k video only              1080p, mp4_dash</span><br></div></code></pre></div></div>
<p>下载命令如下：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">137</span><span class="token plain"> https://www.youtube.com/watch?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">lHvamusTCK0</span><br></div></code></pre></div></div>
<p>另外， <code>-f</code> 参数可同时指定下载多个文件，也可以指定范围下载文件。示例：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">-f 399,137,248: 下载指定文件</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-f 135-137,248-250: 下载指定范围文件(ID 不存在没关系, 会在你指定的范围内查找要下载的 ID 文件)</span><br></div></code></pre></div></div>
<p>需要强调的一点是，Youtube 上的流媒体文件是音视频分离的。因此，你如果使用 <code>-f</code> 这种方式下载视频文件必须同时指定要下载的音频文件，否则下载完成后的视频要么只要画面没有声音要么只有声音没有画面。</p>
<p>视频文件和音频文件使用 <code>+</code> 分隔，比如要下载的视频文件 ID 为 137，音频文件为 140。则命令如下：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">137</span><span class="token plain">+140 https://www.youtube.com/watch?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">lHvamusTCK0</span><br></div></code></pre></div></div>
<p>不要担心下载完成后会有两个文件，yt-dlp 会使用 ffmpeg 工具自动将下载完成后的视频和音频进行合并成一个流媒体文件。</p>
<p><code>-f</code> 参数除了直接指定 ID 外还可以使用下面这种语法（也是 yt-dlp 默认下载形式）：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> bestvideo+bestaudio</span><br></div></code></pre></div></div>
<p>这种语法会自动下载质量最高的音视频文件并进行合并（前提是安装了 ffmpeg ）。比如上面的示例中 1920x1080 的视频文件有两个：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">137 mp4   1920x1080   25 │    1.24GiB 1158k https │ avc1.640028   1158k video only              1080p, mp4_dash</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">248 webm  1920x1080   25 │    1.08GiB 1014k https │ vp9           1014k video only              1080p, webm_dash</span><br></div></code></pre></div></div>
<p>bestvideo 形式默认会自动选择 webm 格式，因此我们可以使用下面的语法指定如果没有 mp4 格式的视频文件的话再选择 webm 视频文件：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> bestvide</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ext</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">mp4</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">/bestvideo</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ext</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">webm</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">+bestaudio</span><br></div></code></pre></div></div>
<p>对于音频文件也是一样的，可以指定优选选择 m4a 还是 webm 的音频文件（默认选择 webm）：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> bestvideo</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ext</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">mp4</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">/bestvideo</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ext</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">webm</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">+bestaudio</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ext</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">m4a</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">/bestaudio</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">ext</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">webm</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="音视频文件合并">音视频文件合并<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E9%9F%B3%E8%A7%86%E9%A2%91%E6%96%87%E4%BB%B6%E5%90%88%E5%B9%B6" class="hash-link" aria-label="音视频文件合并的直接链接" title="音视频文件合并的直接链接" translate="no">​</a></h3>
<p>有时候使用 <code>-f</code> 参数指定具体音视频文件虽然下载完成了，但是不会自动合并，比如使用下面的命令：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> bestvide+bestaudio https://www.youtube.com/video?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">PLpljE1hzFbZxxx</span><br></div></code></pre></div></div>
<p>得到两个音视频文件：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">bestvide.mp4</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">bestaudio.m4a</span><br></div></code></pre></div></div>
<p>遇到这种情况不用担心，我们可以使用 <code>ffmpeg</code> 手动执行下合并，命令如下：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">ffmpeg </span><span class="token parameter variable" style="color:#36acaa">-i</span><span class="token plain"> bestvide.mp4 </span><span class="token parameter variable" style="color:#36acaa">-i</span><span class="token plain"> bestaudio.m4a </span><span class="token parameter variable" style="color:#36acaa">-c:a</span><span class="token plain"> copy </span><span class="token parameter variable" style="color:#36acaa">-c:v</span><span class="token plain"> copy output.mp4</span><br></div></code></pre></div></div>
<p>其中 <code>bestvide.mp4</code> 就是你下载后的视频文件， <code>bestaudio.m4a</code> 是你下载后的音频文件，而最后的 <code>output.mp4</code> 就是你合并之后输出的文件了。</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="下载播放列表">下载播放列表<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E4%B8%8B%E8%BD%BD%E6%92%AD%E6%94%BE%E5%88%97%E8%A1%A8" class="hash-link" aria-label="下载播放列表的直接链接" title="下载播放列表的直接链接" translate="no">​</a></h3>
<p>Youtube 视频下载怎么能缺少专栏呢（就是常说的电视剧，在 Youtube 上叫播放列表 playlist）。播放列表的 URL 通常是下面的形式：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">https://www.youtube.com/playlist?list=PLpljE1hzFbZZMIEUSB_XL7UKr3iAwq7X_</span><br></div></code></pre></div></div>
<p>yt-dlp 也可以直接下载播放列表：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp https://www.youtube.com/playlist?list</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">PLpljE1hzFbZZMIEUSB_XL7UKr3iAwq7X_</span><br></div></code></pre></div></div>
<p>这样会自动下载播放列表中的全部视频，另外也可以使用 <code>--playlist</code> 相关参数下载播放列表指定起始位置：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">--playlist-start NUM            下载播放列表起始位置, 默认1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--playlist-end NUM              下载播放列表结束位置, 默认 last</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--playlist-items ITEM_SPEC      下载播放列表里的特定选集. 如 --playlist-items 1,3,5,7-10, 就会下载 1,3,5,7,8,9,10 集</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_fnQa alert alert--success"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>小提示</div><div class="admonitionContent_Q31J"><p>在下载播放列表指定集之前可以先使用 <code>-F</code> 参数看下有哪些选集。</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="断点续传">断点续传<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0" class="hash-link" aria-label="断点续传的直接链接" title="断点续传的直接链接" translate="no">​</a></h3>
<p>如果在下载过程中网络突然断了是一件很麻烦的视频（如下日志）：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">[youtube] Q6rCpelpwIk: Downloading webpage</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">WARNING: [youtube] &lt;urlopen error EOF occurred in violation of protocol (_ssl.c:1131)&gt;. Retrying ...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">[youtube] lUqJ7uFEXEQ: Downloading android player API JSON (retry #1)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ERROR: unable to download video data: HTTP Error 403: Forbidden</span><br></div></code></pre></div></div>
<p>难道要重新下载？不需要，可以使用 <code>-c</code> 参数指定断点续传。加上该参数之后就会自动接着上次下载的位置下载了：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">137</span><span class="token plain">+140 https://www.youtube.com/watch?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">lHvamusTCK0</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="视频封面">视频封面<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E8%A7%86%E9%A2%91%E5%B0%81%E9%9D%A2" class="hash-link" aria-label="视频封面的直接链接" title="视频封面的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="下载视频封面">下载视频封面<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E4%B8%8B%E8%BD%BD%E8%A7%86%E9%A2%91%E5%B0%81%E9%9D%A2" class="hash-link" aria-label="下载视频封面的直接链接" title="下载视频封面的直接链接" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp --skip-download --write-thumbnail </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">视频链接</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="下载封面并且转为png">下载封面并且转为png<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E4%B8%8B%E8%BD%BD%E5%B0%81%E9%9D%A2%E5%B9%B6%E4%B8%94%E8%BD%AC%E4%B8%BApng" class="hash-link" aria-label="下载封面并且转为png的直接链接" title="下载封面并且转为png的直接链接" translate="no">​</a></h3>
<p>某些视频网站默认下载下来是webp格式，如果想要转换成其他格式（如 png）可以加上 <code>--convert-thumbnail</code> 参数：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp --skip-download --write-thumbnail --convert-thumbnail png </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">视频链接</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="内嵌视频封面">内嵌视频封面<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E5%86%85%E5%B5%8C%E8%A7%86%E9%A2%91%E5%B0%81%E9%9D%A2" class="hash-link" aria-label="内嵌视频封面的直接链接" title="内嵌视频封面的直接链接" translate="no">​</a></h3>
<p>经常看到某些视频的封面特别biu特否，但当你将视频下载下来时发现那个biu特否的封面没了~</p>
<p>这个时候你可能需要使用使用 <code>--embed-thumbnail</code> 参数将封面嵌入到下载的视频文件中。</p>
<p>示例：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp --embed-thumbnail </span><span class="token parameter variable" style="color:#36acaa">--output</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"output_file.mp4"</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"https://www.youtube.com/watch?v=VIDEO_ID"</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="视频字幕">视频字幕<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E8%A7%86%E9%A2%91%E5%AD%97%E5%B9%95" class="hash-link" aria-label="视频字幕的直接链接" title="视频字幕的直接链接" translate="no">​</a></h2>
<p>有些 Youtube 视频字幕也是分离的，所以对于某些视频来说我们还需要下载下对应的字幕。字幕主要有下面这些参数：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">--list-subs               列出所有字幕</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--write-sub               下载字幕文件</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--all-subs                下载所有可用字幕</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--write-auto-sub          下载自动生成的字幕文件</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--sub-lang LANGS          下载指定语言的字幕, 多种语言字符之间使用逗号分隔(如: --sub-lang "")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--sub-format FORMAT       字幕文件格式, 如 "srt" 或 "ass/srt/vtt"(首选 ass 格式, 没有就选择 srt. 以此类推)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--embed-sub               把字幕合并到视频中，只支持 mp4、mkv 和 webm 格式的视频</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--skip-download           不下载视频(适用于仅下载字幕时使用)</span><br></div></code></pre></div></div>
<p>下面的示例都以 <a href="https://www.youtube.com/channel/UC_7WrbZTCODu1o_kfUMq88g" target="_blank" rel="noopener noreferrer" class="">MIT 6.824: Distributed Systems</a> 第十三节课（ <code>https://www.youtube.com/watch?v=4eW5SWBi7vs</code> ）为例做说明。</p>
<p><strong>特别强调：</strong> <code>--write-auto-sub</code> 参数用于下载自动生成的字幕文件，意思就是某些视频本身没有字幕，但是 youtube 比较牛逼，可以自动生成多语言字幕。对于这种本身没有字幕的视频我们就可以借助 <code>--write-auto-sub</code> 参数来实现字幕下载。因此，在下载 youtube 视频时推荐都加上 <code>--write-auto-sub</code> 参数。</p>
<p>看下示例：</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="列出可用字幕">列出可用字幕<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E5%88%97%E5%87%BA%E5%8F%AF%E7%94%A8%E5%AD%97%E5%B9%95" class="hash-link" aria-label="列出可用字幕的直接链接" title="列出可用字幕的直接链接" translate="no">​</a></h3>
<p>通常，youtube 自动生成比较多，所以在列出字幕时可以过滤下，比如我只过滤可用的中/英文字幕：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp --list-subs https://www.youtube.com/watch</span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain">?v</span><span class="token punctuation" style="color:#393A34">\</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">4eW5SWBi7vs </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">egrep</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'en|zh'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">hy       Armenian              vtt, ttml, srv3, srv2, srv1, json3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">zh-Hans  Chinese </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Simplified</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  vtt, ttml, srv3, srv2, srv1, json3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">zh-Hant  Chinese </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Traditional</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> vtt, ttml, srv3, srv2, srv1, json3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">en-orig  English </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Original</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">    vtt, ttml, srv3, srv2, srv1, json3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">en       English               vtt, ttml, srv3, srv2, srv1, json3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">fr       French                vtt, ttml, srv3, srv2, srv1, json3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">sl       Slovenian             vtt, ttml, srv3, srv2, srv1, json3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">tk       Turkmen               vtt, ttml, srv3, srv2, srv1, json3</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="字幕文件下载">字幕文件下载<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E5%AD%97%E5%B9%95%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD" class="hash-link" aria-label="字幕文件下载的直接链接" title="字幕文件下载的直接链接" translate="no">​</a></h3>
<p>有时我们可能仅需要下载视频的字幕文件，对于这种场景我们可以加上 <code>--skip-download</code> 参数，表示不下载视频仅下载字幕。</p>
<p>比如我下载自动生成的中文和英文字幕文件：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp --write-auto-sub --sub-lang </span><span class="token string" style="color:#e3116c">"zh-Hans,en"</span><span class="token plain"> --skip-download https://www.youtube.com/watch</span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain">?v</span><span class="token punctuation" style="color:#393A34">\</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">4eW5SWBi7vs</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> 4eW5SWBi7vs: Downloading subtitles: zh-Hans, en</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> 4eW5SWBi7vs: Downloading </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> format</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">: </span><span class="token number" style="color:#36acaa">243</span><span class="token plain">+251</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Writing video subtitles to: Lecture </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">： Spanner </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">4eW5SWBi7vs</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.zh-Hans.vtt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">download</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Destination: Lecture </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">： Spanner </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">4eW5SWBi7vs</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.zh-Hans.vtt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">download</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token plain">% of  </span><span class="token number" style="color:#36acaa">512</span><span class="token plain">.36KiB </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> 00:00:01 at </span><span class="token number" style="color:#36acaa">410</span><span class="token plain">.79KiB/s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Writing video subtitles to: Lecture </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">： Spanner </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">4eW5SWBi7vs</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.en.vtt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">download</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> Destination: Lecture </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">： Spanner </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">4eW5SWBi7vs</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.en.vtt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">download</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token plain">% of  </span><span class="token number" style="color:#36acaa">551</span><span class="token plain">.15KiB </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> 00:00:01 at </span><span class="token number" style="color:#36acaa">526</span><span class="token plain">.30KiB/s</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ </span><span class="token function" style="color:#d73a49">ls</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Lecture </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">： Spanner </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">4eW5SWBi7vs</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.en.vtt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Lecture </span><span class="token number" style="color:#36acaa">13</span><span class="token plain">： Spanner </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">4eW5SWBi7vs</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">.zh-Hans.vtt</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="将字幕内嵌到视频">将字幕内嵌到视频<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E5%B0%86%E5%AD%97%E5%B9%95%E5%86%85%E5%B5%8C%E5%88%B0%E8%A7%86%E9%A2%91" class="hash-link" aria-label="将字幕内嵌到视频的直接链接" title="将字幕内嵌到视频的直接链接" translate="no">​</a></h3>
<p>另外，我们也可以在下载视频时直接将自动生成的字幕文件内嵌到视频中，这里我选择将中/英文字幕直接内嵌到视频中：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp --write-auto-sub --sub-lang </span><span class="token string" style="color:#e3116c">"zh-Hans,en"</span><span class="token plain"> --embed-sub https://www.youtube.com/watch?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">4eW5SWBi7vs</span><br></div></code></pre></div></div>
<p>另外，如果你对字幕格式有特殊要求还可以使用 <code>--convert-subs</code> 将字幕转换为指定格式，以 ass 字幕格式为例：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp --write-auto-sub --convert-subs</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">ass --sub-lang </span><span class="token string" style="color:#e3116c">"zh-Hans,en"</span><span class="token plain"> --embed-sub https://www.youtube.com/watch?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">4eW5SWBi7vs</span><br></div></code></pre></div></div>
<p>现在，当我们播放视频时就可以随意切换字幕了：</p>
<p><img decoding="async" loading="lazy" src="https://media.ituknown.org/blog-media/yt-dlp/yt-dlp-embed-subtitle-to-video.png" alt="yt-dlp-embed-subtitle-to-video" class="img_o99Q"></p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="网络设置">网络设置<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E7%BD%91%E7%BB%9C%E8%AE%BE%E7%BD%AE" class="hash-link" aria-label="网络设置的直接链接" title="网络设置的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="设置代理">设置代理<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E8%AE%BE%E7%BD%AE%E4%BB%A3%E7%90%86" class="hash-link" aria-label="设置代理的直接链接" title="设置代理的直接链接" translate="no">​</a></h3>
<p>既然下载 Youtube 上的视频怎们能少的了代理呢？</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token parameter variable" style="color:#36acaa">--proxy</span><span class="token plain"> URL</span><br></div></code></pre></div></div>
<p>示例：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">--proxy</span><span class="token plain"> sockss://127.0.0.1:8889 </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">137</span><span class="token plain">+140 https://www.youtube.com/watch?v</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">lHvamusTCK0</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="超时时间">超时时间<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E8%B6%85%E6%97%B6%E6%97%B6%E9%97%B4" class="hash-link" aria-label="超时时间的直接链接" title="超时时间的直接链接" translate="no">​</a></h3>
<p>另外还可以设置连接超时时间：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">--socket-timeout </span><span class="token environment constant" style="color:#36acaa">SECONDS</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="限制下载速度">限制下载速度<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E9%99%90%E5%88%B6%E4%B8%8B%E8%BD%BD%E9%80%9F%E5%BA%A6" class="hash-link" aria-label="限制下载速度的直接链接" title="限制下载速度的直接链接" translate="no">​</a></h3>
<p>如果在上班时偷偷使用 yt-dlp 下载 Youtube 上的视频，每秒几十兆几十兆的下载很容易被网管监控到。所以聪明的做法应该限制一下 yt-dlp 的最大下载速度：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">-r, --limit-rate      MAX_RATE</span><br></div></code></pre></div></div>
<p>参数 <code>MAX_RATE</code> 就是你指定的每秒下载速度上限，如 50K、4.2M、1024G。</p>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="设置请求时间间隔">设置请求时间间隔<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E8%AE%BE%E7%BD%AE%E8%AF%B7%E6%B1%82%E6%97%B6%E9%97%B4%E9%97%B4%E9%9A%94" class="hash-link" aria-label="设置请求时间间隔的直接链接" title="设置请求时间间隔的直接链接" translate="no">​</a></h3>
<p>在油管上，如果批量下载视频（如播放列表）容易触发请求限制，导致无法访问：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">This content isn't available, try again later</span><br></div></code></pre></div></div>
<p>可以设置如下参数，在每个视频下载完成后增加 5 ~ 20 秒的延迟，再下载下一个视频：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sleep</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_fnQa alert alert--info"><div class="admonitionHeading_Dclw"><span class="admonitionIcon_o6fI"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>NOTE</div><div class="admonitionContent_Q31J"><p><code>-t sleep</code> 是 yt-dlp 提供的内置别名预设，他是完整命令是：</p><div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">--sleep-subtitles 5 --sleep-requests 0.75</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--sleep-interval 10 --max-sleep-interval 20</span><br></div></code></pre></div></div><p>如果不想直接会用预设，也可以基于完整命令做适当修改。</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="用户认证">用户认证<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E7%94%A8%E6%88%B7%E8%AE%A4%E8%AF%81" class="hash-link" aria-label="用户认证的直接链接" title="用户认证的直接链接" translate="no">​</a></h2>
<p><code>yt-dlp</code> 提供了通用的网络协议认证方式（即指定用户和密码），参数如下：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">-u, --username USERNAME          指定用户名</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-p, --password PASSWORD          指定用户密码</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="使用-cookies">使用 cookies<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E4%BD%BF%E7%94%A8-cookies" class="hash-link" aria-label="使用 cookies的直接链接" title="使用 cookies的直接链接" translate="no">​</a></h3>
<p>基于用户和密码的认证方式适用于普通的的文件协议（如 FTP）。对于视频网站来说肯定是不行的，因为这种明文的方式对网站来说毫无安全感，因此我们可以采用 cookies 认证：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">--cookies FILE        Netscape 格式的 cookies 文件</span><br></div></code></pre></div></div>
<p><code>--cookies</code> 参数指定的 cookies 文件内容必须是 Netscape 格式才行。很多浏览器都支持插件，如 <code>EditThisCookie</code> 插件就提供了导出 cookies 的功能。</p>
<p>下面是 Netscape 格式的 cookies 内容示例：</p>
<div class="language-Netscape language-netscape codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-netscape codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">## Netscape HTTP Cookie File</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">## This file is generated by yt-dlp.  Do not edit.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">.bilibili.com	TRUE	/	FALSE	0	sid	7rds5eer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">www.bilibili.com	FALSE	/	FALSE	0	theme_style	light</span><br></div></code></pre></div></div>
<p>现在有了这个大会员 cookies 文件我就可以下载任意 1080P 的视频了，示例：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp </span><span class="token parameter variable" style="color:#36acaa">--cookies</span><span class="token plain"> cookies.txt </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> https://www.bilibili.com/video/BV1AG4y1k7jX</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="使用模板变量">使用模板变量<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E4%BD%BF%E7%94%A8%E6%A8%A1%E6%9D%BF%E5%8F%98%E9%87%8F" class="hash-link" aria-label="使用模板变量的直接链接" title="使用模板变量的直接链接" translate="no">​</a></h2>
<p><code>yt-dlp</code> 默认下载的文件名冗余信息特别多（如多余的番号ID信息），下载完成之后可能还需要多额外的重命名操作，总觉得特别麻烦。</p>
<p>不过 yt-dlp 它内置了一些模板变量便于你来重新组织下载的文件名（是不是特别懂你~）。下面是基本的模板变量：</p>
<table><thead><tr><th style="text-align:left"><strong>模板变量</strong></th><th style="text-align:left"><strong>说明</strong></th></tr></thead><tbody><tr><td style="text-align:left"><code>{title}</code></td><td style="text-align:left">视频的标题</td></tr><tr><td style="text-align:left"><code>{id}</code></td><td style="text-align:left">视频的唯一标识符（就是BV号）</td></tr><tr><td style="text-align:left"><code>{uploader}</code></td><td style="text-align:left">视频上传者的用户名</td></tr><tr><td style="text-align:left"><code>{ext}</code></td><td style="text-align:left">文件扩展名</td></tr><tr><td style="text-align:left"><code>{playlist_index}</code></td><td style="text-align:left">当前视频在播放列表中的索引</td></tr><tr><td style="text-align:left"><code>{resolution}</code></td><td style="text-align:left">视频分辨率</td></tr></tbody></table>
<p>例如，如果你想将文件名设置为 “视频标题_上传者.ext”，可以使用以下命令：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"%(title)s_%(uploader)s.%(ext)s"</span><span class="token plain"> 视频链接</span><br></div></code></pre></div></div>
<p>在实际下载中如果不确定自定义的文件名是否符合自己的要求，可以使用 <code>--print</code> 或 <code>--skip-download --get-filename</code> 做输出测试。</p>
<p>以《宇宙 第三季》为例，我重组的文件名格式为：“索引 文件名. 扩展名”。另外，我额外的在索引前面加了一个字母 “P”。同时指定索引为两位数，如果不够两位数就使用 “0” 进行填充。命令如下：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp </span><span class="token parameter variable" style="color:#36acaa">--print</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"P%(playlist_index)02d｜%(title)s.%(ext)s"</span><span class="token plain"> https://www.bilibili.com/video/BV1vx411C7hk</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 或</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp --skip-download --get-filename </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"P%(playlist_index)02d｜%(title)s.%(ext)s"</span><span class="token plain"> https://www.bilibili.com/video/BV1vx411C7hk</span><br></div></code></pre></div></div>
<p>输出的信息如下：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">P01 宇宙 第三季【全12集】 p01 太空灾难.mp4</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">P12 宇宙 第三季【全12集】 p12 宇宙现象.mp4</span><br></div></code></pre></div></div>
<p>看起来已经符合我的要求了，之后就可以下载啦：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"P%(playlist_index)02d｜%(title)s.%(ext)s"</span><span class="token plain"> https://www.bilibili.com/video/BV1vx411C7hk</span><br></div></code></pre></div></div>
<details class="details_unQd alert alert--info details_J7LK" data-collapsed="true"><summary><strong>常用的模板变量</strong></summary><div><div class="collapsibleContent_MGAI"><p>下面是一些常用的模板变量，你可以根据需要自由组合这些变量来构建输出文件名的模板。要查看 yt-dlp 的完整模板变量列表和详细信息，你可以查看 yt-dlp 的官方文档（<a href="https://github.com/yt-dlp/yt-dlp#output-template" target="_blank" rel="noopener noreferrer" class="">https://github.com/yt-dlp/yt-dlp#output-template</a>）。文档通常包含有关每个变量的用法和示例。</p><table><thead><tr><th style="text-align:left"><strong>模板变量</strong></th><th style="text-align:left"><strong>说明</strong></th></tr></thead><tbody><tr><td style="text-align:left"><code>{id}</code></td><td style="text-align:left">视频的唯一标识符（就是BV号）</td></tr><tr><td style="text-align:left"><code>{title}</code></td><td style="text-align:left">视频的标题</td></tr><tr><td style="text-align:left"><code>{uploader}</code></td><td style="text-align:left">视频上传者的用户名</td></tr><tr><td style="text-align:left"><code>{uploader_id}</code></td><td style="text-align:left">视频上传者的唯一标识符</td></tr><tr><td style="text-align:left"><code>{channel}</code></td><td style="text-align:left">视频所属的频道名称</td></tr><tr><td style="text-align:left"><code>{channel_id}</code></td><td style="text-align:left">视频所属的频道唯一标识符</td></tr><tr><td style="text-align:left"><code>{upload_date}</code></td><td style="text-align:left">视频上传的日期（格式为 YYYYMMDD）</td></tr><tr><td style="text-align:left"><code>{duration}</code></td><td style="text-align:left">视频的时长，以秒为单位</td></tr><tr><td style="text-align:left"><code>{view_count}</code></td><td style="text-align:left">视频的观看次数</td></tr><tr><td style="text-align:left"><code>{like_count}</code></td><td style="text-align:left">视频的点赞数</td></tr><tr><td style="text-align:left"><code>{dislike_count}</code></td><td style="text-align:left">视频的踩数</td></tr><tr><td style="text-align:left"><code>{comment_count}</code></td><td style="text-align:left">视频的评论数</td></tr><tr><td style="text-align:left"><code>{thumbnail}</code></td><td style="text-align:left">视频的缩略图链接</td></tr><tr><td style="text-align:left"><code>{categories}</code></td><td style="text-align:left">视频的类别</td></tr><tr><td style="text-align:left"><code>{tags}</code></td><td style="text-align:left">视频的标签</td></tr><tr><td style="text-align:left"><code>{formats}</code></td><td style="text-align:left">视频的可用格式</td></tr><tr><td style="text-align:left"><code>{ext}</code></td><td style="text-align:left">文件扩展名</td></tr><tr><td style="text-align:left"><code>{playlist}</code></td><td style="text-align:left">视频所属的播放列表名称</td></tr><tr><td style="text-align:left"><code>{playlist_index}</code></td><td style="text-align:left">当前视频在播放列表中的索引</td></tr><tr><td style="text-align:left"><code>{webpage_url}</code></td><td style="text-align:left">当前视频对应网页链接</td></tr><tr><td style="text-align:left"><code>{autonumber}</code></td><td style="text-align:left">用于递增计数，通常与播放列表结合使用</td></tr><tr><td style="text-align:left"><code>{description}</code></td><td style="text-align:left">视频的描述</td></tr></tbody></table></div></div></details>
<details class="details_unQd alert alert--info details_J7LK" data-collapsed="true"><summary><strong>模板变量最佳实战</strong></summary><div><div class="collapsibleContent_MGAI"><p>下载前先确定重组文件名是否 ok：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">--print</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"P%(playlist_index)02d｜%(title)s.%(ext)s"</span><span class="token plain"> 视频链接</span><br></div></code></pre></div></div><p>执行下载：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sleep</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--embed-thumbnail </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> bestvideo+bestaudio </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"P%(playlist_index)02d｜%(title)s.%(ext)s"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">--cookies</span><span class="token plain"> cookies_svip.txt </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">视频链接</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div><p>如果是 youtube 的话，可以考虑内嵌字幕什么的：</p><div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sleep</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--embed-thumbnail </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> bestvideo+bestaudio </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">--write-auto-sub --convert-subs</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">ass --sub-lang </span><span class="token string" style="color:#e3116c">"zh-Hans,en"</span><span class="token plain"> --embed-sub </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"P%(playlist_index)02d｜%(title)s.%(ext)s"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">视频链接</span><span class="token punctuation" style="color:#393A34">]</span><br></div></code></pre></div></div></div></div></details>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="查看支持的网站列表">查看支持的网站列表<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E6%9F%A5%E7%9C%8B%E6%94%AF%E6%8C%81%E7%9A%84%E7%BD%91%E7%AB%99%E5%88%97%E8%A1%A8" class="hash-link" aria-label="查看支持的网站列表的直接链接" title="查看支持的网站列表的直接链接" translate="no">​</a></h2>
<p>如果想要知道 yt-dlp 工具支不支持你想下载的网站的视频可以使用下面参数看下。该参数会列出所有支持的网站列表：</p>
<div class="language-log codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-log codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">--list-extractors</span><br></div></code></pre></div></div>
<p>比如我想看看支不支持 bilibili：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp --list-extractors </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> bilibili</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">bangumi.bilibili.com</span><br></div></code></pre></div></div>
<p>这里显示支持。那我使用 <code>-F</code> 参数看下尚硅谷的c语言课程试试：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">$ yt-dlp </span><span class="token parameter variable" style="color:#36acaa">-F</span><span class="token plain"> https://www.bilibili.com/video/BV1qJ411z7Hf</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ID EXT RESOLUTION │  FILESIZE  TBR PROTO │ VCODEC            VBR ACODEC      ABR</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">─────────────────────────────────────────────────────────────────────────────────</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">0</span><span class="token plain">  m4a audio only │ ~ </span><span class="token number" style="color:#36acaa">4</span><span class="token plain">.85MiB  67k https │ audio only            mp4a.40.2   67k</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">1</span><span class="token plain">  m4a audio only │ ~ </span><span class="token number" style="color:#36acaa">9</span><span class="token plain">.59MiB 132k https │ audio only            mp4a.40.2  132k</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">2</span><span class="token plain">  m4a audio only │ ~23.04MiB 319k https │ audio only            mp4a.40.2  319k</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">30</span><span class="token plain"> mp4 1200x720   │ ~11.78MiB 163k https │ hev1.1.6.L120.90 163k video only</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">31</span><span class="token plain"> mp4 1280x768   │ ~15.40MiB 213k https │ avc1.640028      213k video only</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">32</span><span class="token plain"> mp4 1280x768   │ ~11.96MiB 165k https │ hev1.1.6.L120.90 165k video only</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">.</span><br></div></code></pre></div></div>
<p>那现在我下载课程还不轻而易举？</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="什么是-WebM-格式">什么是 WebM 格式<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#%E4%BB%80%E4%B9%88%E6%98%AF-WebM-%E6%A0%BC%E5%BC%8F" class="hash-link" aria-label="什么是 WebM 格式的直接链接" title="什么是 WebM 格式的直接链接" translate="no">​</a></h2>
<p>WebM由Google提出，是一个开放、免费的媒体文件格式。</p>
<p>WebM 影片格式其实是以 Matroska（即 MKV）容器格式为基础开发的新容器格式，里面包括了VP8影片轨和 Ogg Vorbis 音轨，其中Google将其拥有的VP8视频编码技术以类似BSD授权开源，Ogg Vorbis 本来就是开放格式。</p>
<p>WebM标准的网络视频更加偏向于开源并且是基于HTML5标准的。相比较而言，我发现同样是 1080p 的视频 WebM 要比 MP4 体积更小，更方便于网络传输，但两者的画面感我看不出有什么差异。</p>
<p>虽然 WebM 有很多好处，但是 MP4 是现在主流的流媒体标准。有些流媒体播放器还不支持 WebM 视频格式，如英特尔对 WebM 的流媒体就存在兼容性问题。</p>
<h2 class="anchor anchorTargetStickyNavbar_FAAG" id="QA">Q&amp;A<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#QA" class="hash-link" aria-label="Q&amp;A的直接链接" title="Q&amp;A的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_FAAG" id="JavaScript-运行时错误">JavaScript 运行时错误？<a href="https://ituknown.github.io/blog/yt-dlp-%E5%B7%A5%E5%85%B7%E5%B8%B8%E7%94%A8%E6%96%B9%E5%BC%8F/#JavaScript-%E8%BF%90%E8%A1%8C%E6%97%B6%E9%94%99%E8%AF%AF" class="hash-link" aria-label="JavaScript 运行时错误？的直接链接" title="JavaScript 运行时错误？的直接链接" translate="no">​</a></h3>
<p>在下载 YouTube 视频时大概率会遇到下面错误提示或警告：</p>
<div class="language-text codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-text codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">WARNING: [youtube] No supported JavaScript runtime could be found. Only deno is enabled by default; to use another runtime add  --js-runtimes RUNTIME[:PATH]  to your command/config. YouTube extraction without a JS runtime has been deprecated, and some formats may be missing. See  https://github.com/yt-dlp/yt-dlp/wiki/EJS  for details on installing one</span><br></div></code></pre></div></div>
<p>这个警告是 yt-dlp 提示你需要外部 JavaScript 运行时（runtime）来解决 YouTube 的反爬机制。解决方式也很简单，安装一个 JavaScript 运行环境即可（选一个你最熟悉的即可）：</p>
<ul>
<li class="">Deno (推荐)：轻量且是 yt-dlp 的默认首选。</li>
<li class="">Node.js</li>
<li class="">Bun</li>
</ul>
<p>之后使用只需要加上 <code>--js-runtimes</code> 参数即可：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp --js-runtimes deno</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp --js-runtimes </span><span class="token function" style="color:#d73a49">node</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">yt-dlp --js-runtimes bun</span><br></div></code></pre></div></div>
<p>另外，将配置写入文件，这样以后每次使用 yt-dlp 都会自动应用，无需再手动输入参数。根据你的操作系统选择对应的命令：</p>
<p>Linux/macOS 用户：</p>
<div class="language-bash codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-bash codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">mkdir</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> ~/.config/yt-dlp</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"--js-runtimes node"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> ~/.config/yt-dlp/config</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"--remote-components ejs:github"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> ~/.config/yt-dlp/config</span><br></div></code></pre></div></div>
<p>Windows 用户：</p>
<div class="language-powershell codeBlockContainer_Crht theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_P6P5"><pre tabindex="0" class="prism-code language-powershell codeBlock_R6qh thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_HvnT"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">echo</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">--</span><span class="token plain">js-runtimes node &gt; </span><span class="token operator" style="color:#393A34">%</span><span class="token plain">APPDATA%\yt-dlp\config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">txt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">echo</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">--</span><span class="token plain">remote-components ejs:github &gt;&gt; </span><span class="token operator" style="color:#393A34">%</span><span class="token plain">APPDATA%\yt-dlp\config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">txt</span><br></div></code></pre></div></div>
<p>简单解释一下这两个参数的作用：</p>
<ul>
<li class=""><code>--js-runtimes node</code>：指定使用 Node.js 作为 JavaScript 运行时（也可以修改为 deno）。</li>
<li class=""><code>--remote-components ejs:github</code>：允许 yt-dlp 在需要时，自动从 GitHub 下载最新的方案解决脚本异常</li>
</ul>]]></content:encoded>
            <category>软硬件</category>
        </item>
    </channel>
</rss>