<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>曹一山的个人博客</title>
  
  <subtitle>记录个人学习心路历程</subtitle>
  <link href="https://blog.plcent.com/atom.xml" rel="self"/>
  
  <link href="https://blog.plcent.com/"/>
  <updated>2026-03-08T04:44:49.549Z</updated>
  <id>https://blog.plcent.com/</id>
  
  <author>
    <name>Nolly</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>openclaw 报错 disconnected(4008)： connect failed</title>
    <link href="https://blog.plcent.com/openclaw-disconnected-4008-connect-failed/"/>
    <id>https://blog.plcent.com/openclaw-disconnected-4008-connect-failed/</id>
    <published>2026-03-08T02:47:40.000Z</published>
    <updated>2026-03-08T04:44:49.549Z</updated>
    
    <content type="html"><![CDATA[<p>解决openclaw 2026.3.2版本<code>disconnected(4008)： connect failed</code>报错问题。</p><span id="more"></span><p>在国产操作系统上部署openclaw过程中，遇到web ui打开openclaw时，UI界面报错<code>disconnected(4008)： connect failed</code></p><p><img src="/openclaw-disconnected-4008-connect-failed/1772938384250.png" alt="1772938384250" loading="lazy"></p><h2 id="问题原因"><a href="#问题原因" class="headerlink" title="问题原因"></a>问题原因</h2><p>找到问题点，根据页面错误提示，在openclaw源代码中全局搜索<code>4008</code>关键字。在源代码<code>/ui/src/ui/gateway.ts</code>中定义了该错误码。</p><p><img src="/openclaw-disconnected-4008-connect-failed/1772942353333.png" alt="1772942353333" loading="lazy"></p><p>在该问题<code>GatewayBrowserClient</code>方法中，<code>.catch</code>方法中捕获并抛出该异常。通过下面方法在关键位置增加console输出，进行调试。</p><p><img src="/openclaw-disconnected-4008-connect-failed/1772942406227.png" alt="1772942406227" loading="lazy"></p><p>发现异常时，错误堆栈中，调用了<code>/src/shared/device-auth.ts</code>中<code>normalizeDeviceAuthScope</code>方法，该方法输出内容为一个数组，该数组使用<code>[...out].toSorted()</code>进行排序后输出。<code>toSorted()</code>方法在当前浏览器中不存在，导致的报错。</p><p><img src="/openclaw-disconnected-4008-connect-failed/1772942671518.png" alt="1772942671518" loading="lazy"></p><h2 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h2><h3 id="1-更换最新版本的chrome浏览器直接解决"><a href="#1-更换最新版本的chrome浏览器直接解决" class="headerlink" title="1. 更换最新版本的chrome浏览器直接解决"></a>1. 更换最新版本的chrome浏览器直接解决</h3><p>经过测试，<code>toSorted()</code>方法在<code>100</code>以后的版本均支持，所以直接换用谷歌浏览器即可。</p><h3 id="2-重新编译openclaw，修改代码解决"><a href="#2-重新编译openclaw，修改代码解决" class="headerlink" title="2. 重新编译openclaw，修改代码解决"></a>2. 重新编译openclaw，修改代码解决</h3><p>既然知道问题点，修改数据排序方法，使用当前浏览器支持的方法即可。我直接使用了<code>sort()</code>替代。该方法老版本浏览器页支持。</p><blockquote><p>需要说明的是，<code>toSorted</code>方法不修改原数组，<code>sort</code>方法排序后会更新原数组。这个是副作用。</p></blockquote><p><img src="/openclaw-disconnected-4008-connect-failed/1772943064472.png" alt="1772943064472" loading="lazy"></p><ol><li><p>重新写编译打包<code>pnpm ui:build</code></p></li><li><p>会在项目更目录下生成一个<code>dist</code>目录，该目录下会生成一个<code>control-ui</code>的包。</p></li><li><p>复制该包，到你全局的openclaw包中，替换源包中的<code>control-ui</code>模块即可。</p></li></ol><p>由于<code>npm</code>全局目录的不同，默认情况下，你的<code>openclaw</code>包可能在以下目录：</p><ul><li><code>/usr/lib/node_modules/openclaw</code> 使用root权限安装</li><li><code>~/npm-global/lib/node_modules/openclaw</code> 当前用户安装</li></ul><ol start="3"><li><p>替换<code>openclaw/dist/control-ui</code>这个目录，为你打包出来的目录。</p></li><li><p>重启<code>openclaw</code>即可。<code>openclaw gateway restart</code></p></li></ol><p><img src="/openclaw-disconnected-4008-connect-failed/1772943281153.png" alt="1772943281153" loading="lazy"></p><h2 id="其他补充信息"><a href="#其他补充信息" class="headerlink" title="其他补充信息"></a>其他补充信息</h2><p>在移动信创云电脑等环境中，启动<code>openclaw</code>时，会报下面的告警信息：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Warning: no IPv4 address available on ens3</span><br></pre></td></tr></table></figure><p><img src="/openclaw-disconnected-4008-connect-failed/1772945058470.png" alt="1772945058470" loading="lazy"></p><p>这并不是没有<code>IPV4</code>导致的，该处告警，<code>openclaw</code>在检查所有网卡的所有<code>IPv4</code>地址，只是提醒在<code>ens3</code>网卡中，没有<code>IPV4</code>地址而已。</p><p>本地启动的服务，通常启动在<code>localhost</code>、<code>127.0.0.1</code>上，这类服务走的时本地回环地址，也就是<code>lo</code>网卡，根本走不到物理网卡上，所以不可能可物理网卡有关。</p><p><code>openclaw</code>的服务启动时，他会检查所有的网卡，同时在对应的IP上启动服务，比如<a href="https://docs.openclaw.ai/zh-CN/cli/gateway#%E9%80%89%E9%A1%B9"><code>gateway.bind</code></a>选项，支持<code>loopback|lan|tailnet|auto|custom</code>选项值，<code>loopback</code>就是本地回环地址，只能本地访问，<code>lan</code>就是启动在<code>0.0.0.0</code>上，绑定所有网卡，可以链接到本机的都可以访问到。可以暴露到公网。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;解决openclaw 2026.3.2版本&lt;code&gt;disconnected(4008)： connect failed&lt;/code&gt;报错问题。&lt;/p&gt;</summary>
    
    
    
    <category term="openclaw" scheme="https://blog.plcent.com/categories/openclaw/"/>
    
    
    <category term="openclaw" scheme="https://blog.plcent.com/tags/openclaw/"/>
    
  </entry>
  
  <entry>
    <title>国产操作系统麒麟、uos 无GPU系统，Openclaw 3.2+版本安装</title>
    <link href="https://blog.plcent.com/openclaw-install-on-kylin-uos/"/>
    <id>https://blog.plcent.com/openclaw-install-on-kylin-uos/</id>
    <published>2026-03-08T02:44:19.000Z</published>
    <updated>2026-03-08T04:33:21.302Z</updated>
    
    <content type="html"><![CDATA[<p>国产操作系统麒麟、uos下，虚拟机、云电脑等 无GPU场景下，基于<code>npm</code>的<code>Openclaw 3.2+</code>版本安装教程。</p><p>本教程移除了复杂的不必要的步骤。</p><span id="more"></span><h2 id="安装nodejs、npm"><a href="#安装nodejs、npm" class="headerlink" title="安装nodejs、npm"></a>安装nodejs、npm</h2><p>借助Nodejs版本管理工具nvm来安装，方便后期切换Nodejs版本</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载并安装nvm:</span></span><br><span class="line">curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">当前命令行中执行或者重庆命令行终，使nvm变成终端命令</span></span><br><span class="line">\. &quot;$HOME/.nvm/nvm.sh&quot;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">下载并安装 Node.js:</span></span><br><span class="line">nvm install 24</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看 Node.js 版本:</span></span><br><span class="line">node -v # Should print &quot;v24.14.0&quot;.</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看 npm 版本:</span></span><br><span class="line">npm -v # Should print &quot;11.9.0&quot;.</span><br></pre></td></tr></table></figure><p>来源于官方教程，地址：<a href="https://nodejs.org/en/download">https://nodejs.org/en/download</a></p><blockquote><p>原理说明：nvm时一个nodejs的包管理器，可以让你的电脑中，同时存在多个nodejs版本，后续升级如果当前nodejs版本不可以，可以通过nvm切换nodejs版本，而不需要卸载重装。</p><p>如</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装22版本nodejs</span></span><br><span class="line">nvm install 22</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看当前电脑安装了哪些版本</span></span><br><span class="line">nvm list</span><br><span class="line">24.1.0</span><br><span class="line">22.1.0</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">根据list显示的版本号，切换一个版本</span></span><br><span class="line">nvm use 22.1.0</span><br><span class="line"></span><br></pre></td></tr></table></figure></blockquote><p><code>nvm</code>安装逻辑时把<code>nvm</code>源码下载到当前用户的<code>~/.nvm</code>目录下，并把<code>~/.nvm/nvm.sh</code>变成终端命令。所以可以在命令行中使用。</p><h2 id="安装pnpm"><a href="#安装pnpm" class="headerlink" title="安装pnpm"></a>安装pnpm</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g pnpm</span><br></pre></td></tr></table></figure><blockquote><p>在该教程中，用不到，防止你后续需要。</p></blockquote><h2 id="修改安装源为国内淘宝镜像源"><a href="#修改安装源为国内淘宝镜像源" class="headerlink" title="修改安装源为国内淘宝镜像源"></a>修改安装源为国内淘宝镜像源</h2><p>该步骤必须要加，要不安装过程慢的要死。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">npm 设置淘宝代理</span></span><br><span class="line">npm config set registry https://registry.npmmirror.com</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">pnpm 设置淘宝代理</span></span><br><span class="line">pnpm config set registry https://registry.npmmirror.com</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">npm检查设置结果</span></span><br><span class="line">npm config get registry</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">pnpm检查设置结果</span></span><br><span class="line">pnpm config get registry</span><br></pre></td></tr></table></figure><p>pnpm 写入的配置文件为：<code>~/.config/pnpm/rc</code><br>npm    写入的配置文件为：<code>~/.npmrc</code></p><h2 id="安装git"><a href="#安装git" class="headerlink" title="安装git"></a>安装git</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install -y -qq git</span><br></pre></td></tr></table></figure><h2 id="安装openclaw"><a href="#安装openclaw" class="headerlink" title="安装openclaw"></a>安装openclaw</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g openclaw@latest --ignore-scripts</span><br></pre></td></tr></table></figure><p><code>--ignore-scripts</code> 表示忽略安装后的脚本，可以避免使用<code>node-llama-cpp</code>编译。这个参数必须加，和官方教程不同。</p><p>如果你电脑有<code>GPU</code>，可以不加该参数。</p><h2 id="进入openclaw-引导交互开始配置"><a href="#进入openclaw-引导交互开始配置" class="headerlink" title="进入openclaw 引导交互开始配置"></a>进入openclaw 引导交互开始配置</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">openclaw onboard --install-daemon</span><br></pre></td></tr></table></figure><blockquote><p>后续按照其他教程使用openclaw即可</p></blockquote><h1 id="问题处理"><a href="#问题处理" class="headerlink" title="问题处理"></a>问题处理</h1><h2 id="disconnected-4008-connect-failed"><a href="#disconnected-4008-connect-failed" class="headerlink" title="disconnected (4008): connect failed"></a>disconnected (4008): connect failed</h2><p>解决办法：使用谷歌浏览器，详细原理参见本博客文章：<a href="/openclaw-disconnected-4008-connect-failed/">openclaw 报错 disconnected(4008)： connect failed</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;国产操作系统麒麟、uos下，虚拟机、云电脑等 无GPU场景下，基于&lt;code&gt;npm&lt;/code&gt;的&lt;code&gt;Openclaw 3.2+&lt;/code&gt;版本安装教程。&lt;/p&gt;
&lt;p&gt;本教程移除了复杂的不必要的步骤。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>Linux下硬件时间系统时间等概念</title>
    <link href="https://blog.plcent.com/linux-systime-time-discuss/"/>
    <id>https://blog.plcent.com/linux-systime-time-discuss/</id>
    <published>2025-12-15T03:02:44.000Z</published>
    <updated>2025-12-15T04:55:44.619Z</updated>
    
    <content type="html"><![CDATA[<p>理解操作系统的硬件时间（RTC）、系统时间（UTC）、本地时间概念。操作系统如何配置实现无网络环境下时间准确。</p><span id="more"></span><p>在操作系统中，我们可以通过<a href="https://www.linuxcool.com/timedatectl"><code>timedatectl</code></a>命令来查看系统时间设置情况。</p><p><img src="/linux-systime-time-discuss/1765768134093.png" alt="1765768134093" loading="lazy"></p><p>上述的输出内容，共展示了以下信息：</p><ul><li><p>Local time：本地时间，<code>CST</code> 是中国标准时间（China Standard Time）的缩写。</p></li><li><p>Universal time：世界协调时（UTC），与本地时间相差 8 小时，符合东八区（+0800）的偏移。</p></li><li><p>RTC time：实时时钟（Real-Time Clock）时间，，与本地时间相差 8 小时。</p></li><li><p>Time zone：时区为 <code>Asia/Shanghai (CST, +0800)</code>，明确系统设置的时区是上海时区，偏移量为<code>+0800</code>。</p></li><li><p>System clock synchronized：系统时钟已同步，显示 <code>yes</code>，表明系统时钟正在与 <code>NTP</code> 服务器同步。如果内网环境，时间无法完成同步时，该处显示<code>no</code></p></li><li><p>NTP service：NTP 服务状态为 <code>active</code>，说明 NTP 服务正在运行。</p></li><li><p>RTC in local TZ：实时时钟是否已经使用了本地时区，<code>yes</code>表示是，<code>no</code>表示否。</p></li></ul><blockquote><p>其中使人困惑的应该是<code>RTC in local TZ</code>，该部分后面内容进行说明。</p></blockquote><h1 id="时钟概念"><a href="#时钟概念" class="headerlink" title="时钟概念"></a>时钟概念</h1><h2 id="硬件时间-实时时钟（RTC）"><a href="#硬件时间-实时时钟（RTC）" class="headerlink" title="硬件时间&#x2F;实时时钟（RTC）"></a>硬件时间&#x2F;实时时钟（RTC）</h2><p>硬件时钟是计算机主板上的一个实时时钟（RTC，Real-Time Clock）芯片，它独立于操作系统运行，即使计算机断电，也能依靠主板上的纽扣电池维持计时。</p><p><strong>工作原理</strong>：RTC 芯片内部有一个晶体振荡器，通过晶体的压电效应产生稳定的周期性振荡信号。这个振荡信号经过分频电路处理，转化为秒脉冲信号，进而实现对时间的计数，能够精确记录年、月、日、时、分、秒等时间信息。</p><p><strong>数据来源</strong>：硬件时钟的数据来源主要是其自身的计时电路和晶体振荡器产生的稳定振荡信号。在计算机开机时，操作系统会读取硬件时钟的时间，并以此为基础来设置系统时钟的初始值。同时，用户也可以手动设置硬件时钟的时间，例如在 BIOS 设置界面中进行操作。</p><blockquote><p>大部分操作系统会在启动时，读取硬件时间来更新系统时间。</p></blockquote><h2 id="系统时间（UTC）"><a href="#系统时间（UTC）" class="headerlink" title="系统时间（UTC）"></a>系统时间（UTC）</h2><p>系统时钟是操作系统内核维护的时间，它通常在操作系统启动时从RTC设置，然后由系统时钟进行跟踪。</p><p><strong>工作原理</strong>：系统时钟基于硬件时钟（RTC）获取初始时间值，然后通过操作系统内核中的时钟中断机制来不断更新时间。时钟中断是由计算机的定时器芯片（如可编程中断定时器 PIT）产生的周期性中断信号，内核接收到这个中断信号后，就会增加系统时钟的计数值，从而实现时间的流逝。例如，每秒钟可能会产生 100 次时钟中断（具体频率取决于系统设置），每次中断系统时钟就会相应增加一定的时间量（如 10 毫秒）。</p><p><strong>数据来源</strong>：系统时钟的初始数据来源于硬件时钟。在计算机启动过程中，BIOS 会将硬件时钟的时间传递给操作系统，操作系统以此为基础开始运行系统时钟。之后，系统时钟通过时钟中断机制不断更新，同时，系统也可以通过网络时间协议（NTP，Network Time Protocol）与外部时间服务器进行同步，获取更准确的时间数据来校准系统时钟。例如，操作系统会定期向 NTP 服务器发送请求，获取服务器上的准确时间，并根据两者的时间差来调整系统时钟，以保证系统时间的准确性。</p><blockquote><p>NTP的概念下文补充</p></blockquote><h2 id="本地时间（Local-time"><a href="#本地时间（Local-time" class="headerlink" title="本地时间（Local time)"></a>本地时间（Local time)</h2><p>本地时间是系统时间经过时区转换后的时间。时区是根据地理位置确定的，全球分为24个时区，每个时区大约代表15度的经度。例如，北京时间是UTC+8，而伦敦时间是UTC+0。</p><p>在操作系统中，时区可以手动设置(<code>tzselect</code>)，在上述的命令输出中，对应<code>Time zone</code>的概念。</p><h1 id="RTC时钟的工作方式"><a href="#RTC时钟的工作方式" class="headerlink" title="RTC时钟的工作方式"></a>RTC时钟的工作方式</h1><p>在上述的命令输出中，有一个概念是<code>RTC in local TZ</code></p><p>当<code>RTC in local TZ</code>配置为<code>yes</code>时，<strong>意味着 RTC 芯片记录的时间是本地时区时间，而非 UTC 时间。<strong>这就意味着</strong>当前硬件时间，已经包含了时区，RTC时间等于本地时间，UTC时间需要加上时区重新计算</strong>。</p><p>当<code>RTC in local TZ</code>配置为<code>no</code>时，<strong>意味着 RTC 芯片记录的时间是 UTC 时间。<strong>这就意味着</strong>RTC时间等于UTC时间，当前本地时间计算时，需要在TRC时间上再加上时区，得到系统时间。</strong></p><p>示例，<code>RTC in local TZ = yes</code>：</p><p><img src="/linux-systime-time-discuss/1765769598897.png" alt="1765769598897" loading="lazy"></p><blockquote><p>当前配置下系统给出了一些告警提示信息。</p></blockquote><p>示例，<code>RTC in local TZ = no</code>：</p><p><img src="/linux-systime-time-discuss/1765769632564.png" alt="1765769632564" loading="lazy"></p><h2 id="RTC-in-local-TZ-yes可能带来的问题"><a href="#RTC-in-local-TZ-yes可能带来的问题" class="headerlink" title="RTC in local TZ &#x3D; yes可能带来的问题"></a>RTC in local TZ &#x3D; yes可能带来的问题</h2><p>在上述的命令输出中，给出了一段告警信息</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Warning: The system is configured to read the RTC time in the local time zone.</span><br><span class="line">         This mode cannot be fully supported. It will create various problems</span><br><span class="line">         with time zone changes and daylight saving time adjustments. The RTC</span><br><span class="line">         time is never updated, it relies on external facilities to maintain it.</span><br><span class="line">         If at all possible, use RTC in UTC by calling</span><br><span class="line">         &#x27;timedatectl set-local-rtc 0&#x27;.</span><br></pre></td></tr></table></figure><p>中文：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">告警：系统配置为读取本地时区的RTC时间。</span><br><span class="line">无法完全支持此模式。它将在时区更改和夏令时调整方面产生各种问题。RTC时间从不更新，它依赖于外部设施来维护它。如果可能的话，通过调用&quot;timedatectl set-local-rtc 0&quot;在UTC中使用RTC。</span><br></pre></td></tr></table></figure><p>问题点在于<code>时区更改和夏令时调整方面产生问题</code>，因为系统时间直接采用的RTC时间进行展示，系统时间完全依赖硬件时间。无法根据相应的时区调整修改时间。</p><blockquote><p>通过系统UI调整时区，系统实际上是基于当前计算出来的UTC时间＋时区计算的，重启后，当前时间会重新从RTC读取并展示。</p></blockquote><h2 id="如何修正"><a href="#如何修正" class="headerlink" title="如何修正"></a>如何修正</h2><p>按照系统警告提示，在终端执行<code>timedatectl set-local-rtc 0</code>，修改后重启桌面即可。</p><p>如果你的机器不通公网，内外没有BTP服务对时，可以这样修改。</p><p>修改后系统时间为<code>RTC时间+时区</code></p><h1 id="NTP服务"><a href="#NTP服务" class="headerlink" title="NTP服务"></a>NTP服务</h1><p>NTP 即网络时间协议（Network Time Protocol），它是用于在计算机网络中同步时钟的标准互联网协议 。</p><p>NTP 服务器：包括权威时间服务器（如国际原子时标准的服务器）和本地 NTP 服务器。本地 NTP 服务器可以从权威时间服务器获取时间，并为本地网络中的设备提供时间同步服务，可提高时间同步的效率和可靠性，减少对外部网络的依赖。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;理解操作系统的硬件时间（RTC）、系统时间（UTC）、本地时间概念。操作系统如何配置实现无网络环境下时间准确。&lt;/p&gt;</summary>
    
    
    
    <category term="linux" scheme="https://blog.plcent.com/categories/linux/"/>
    
    
    <category term="linux" scheme="https://blog.plcent.com/tags/linux/"/>
    
    <category term="kylin" scheme="https://blog.plcent.com/tags/kylin/"/>
    
  </entry>
  
  <entry>
    <title>hexo 通过自定义git远程仓库实现一键部署到站点</title>
    <link href="https://blog.plcent.com/hexo-deployer-git/"/>
    <id>https://blog.plcent.com/hexo-deployer-git/</id>
    <published>2025-10-21T06:11:31.000Z</published>
    <updated>2025-10-21T09:32:30.574Z</updated>
    
    <content type="html"><![CDATA[<p>通过在服务器上自建git远程仓库，通过<code>hexo-deployer-git</code>实现自动推送到git仓库，利用仓库更新钩子函数实现站点自动更新。</p><span id="more"></span><h1 id="创建远程仓库"><a href="#创建远程仓库" class="headerlink" title="创建远程仓库"></a>创建远程仓库</h1><ol><li><p>登录阿里云服务器</p></li><li><p>创建git用户</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建一个专门用于git推送的服务器用户</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">useradd git</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">切换到该用户</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">su - git</span></span><br></pre></td></tr></table></figure></li><li><p>创建存储目录，并设置权限，否则后续命令执行可能会遇到权限问题</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir /data</span><br><span class="line">chown -R git:git /data</span><br></pre></td></tr></table></figure></li><li><p>创建git仓库</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建保存git仓库的目录</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">mkdir</span> /data/git-reps/my-blog.git</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cd</span> /data/git-reps/my-blog.git</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建git裸仓库</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git init --bare</span></span><br></pre></td></tr></table></figure><blockquote><p>注意：必须使用<code>--bare</code>参数来创建裸仓库，才能接收代码推送</p></blockquote></li></ol><h1 id="配置sudo免密"><a href="#配置sudo免密" class="headerlink" title="配置sudo免密"></a>配置sudo免密</h1><h2 id="本地文件创建密钥"><a href="#本地文件创建密钥" class="headerlink" title="本地文件创建密钥"></a>本地文件创建密钥</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">ssh-keygen -t rsa -C <span class="string">&quot;备注信息&quot;</span> -f ~/.ssh/myblog</span></span><br></pre></td></tr></table></figure><p>在<code>~/.ssh</code>目录会生成两个文件<code>myblog</code>、<code>myblog.pub</code></p><h2 id="本地配置ssh-config"><a href="#本地配置ssh-config" class="headerlink" title="本地配置ssh config"></a>本地配置ssh config</h2><p>本地存在多个ssh密钥需要管理，在本地新建<code>config</code>文件来管理多个ssh密钥</p><ol><li><p>新建<code>~/.ssh/config</code>文件</p></li><li><p>配置ssh使用的公钥</p><p>其中，<code>Host</code>可以自定义，<code>HostName</code>为真实的服务器地址信息，可以是IP，也可以是可以正常解析的域名</p></li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Host blog.plcent.com</span><br><span class="line">HostName blog.plcent.com</span><br><span class="line">PreferredAuthentications publickey</span><br><span class="line">IdentityFile ~/.ssh/myblog</span><br></pre></td></tr></table></figure><h2 id="配置服务器ssh免密"><a href="#配置服务器ssh免密" class="headerlink" title="配置服务器ssh免密"></a>配置服务器ssh免密</h2><ol><li>获取本地生成的公钥文件<code>myblog.pub</code>的内容</li><li>使用<code>git</code>用户登录服务器（或者使用其他用户登录后切换到git用户）</li><li>复制公钥内容到服务器<code>~/.ssh/authorized_keys</code></li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">确认所在的目录正确</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">pwd</span></span></span><br><span class="line">/home/git</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建.ssh目录</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">mkdir</span> .ssh</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">写入myblog.pub公钥文件内容</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">vi authorized_keys</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><blockquote><p>你也可以使用<code>ssh-copy-id</code>类复制命令来执行这个过程</p></blockquote><h2 id="测试ssh"><a href="#测试ssh" class="headerlink" title="测试ssh"></a>测试ssh</h2><p>本地目录测试配置是否正确</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">ssh -T git@blog.plcent.com</span></span><br></pre></td></tr></table></figure><p><code>git@blog.plcent.com</code>中，<code>git</code>是服务器新建的用户名， <code>blog.plcent.com</code>是本地<code>~/.ssh/config</code>配置文件中，<code>Host</code> 所写的ssh服务器信息，该信息可以自定义编写。</p><p><img src="/hexo-deployer-git/1761028448460.png" alt="1761028448460" loading="lazy"></p><h1 id="配置git推送"><a href="#配置git推送" class="headerlink" title="配置git推送"></a>配置git推送</h1><h2 id="安装hexo-deployer-git"><a href="#安装hexo-deployer-git" class="headerlink" title="安装hexo-deployer-git"></a>安装hexo-deployer-git</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-git --save</span><br></pre></td></tr></table></figure><h2 id="编辑-config-yml"><a href="#编辑-config-yml" class="headerlink" title="编辑 _config.yml"></a>编辑 _config.yml</h2><ol><li><p>打开<code>_config.yml</code>配置文件</p></li><li><p>写入下面信息</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line">  <span class="attr">repo:</span> <span class="string">git@blog.plcent.com:/data/git-reps/my-blog.git</span></span><br><span class="line">  <span class="attr">branch:</span> <span class="string">master</span></span><br><span class="line">  <span class="attr">message:</span></span><br><span class="line">  <span class="attr">token:</span></span><br></pre></td></tr></table></figure></li><li><p>推送当前代码到自定义git仓库</p></li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">npx hexo deploy</span></span><br></pre></td></tr></table></figure><p><code>hexo-deployer-git</code>根据配置文件所配置的远程<code>git</code>仓库信息，在项目根目录下生成<code>.deploy_git</code>目录，并生成站点内容，并<strong>强制推送到</strong>存储库来工作。 如果不存在.deploy_git<code>，则将</code>git init&#96;初始化存储库。 否则，将使用当前存储库（及其提交历史记录）。</p><p>相当于：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone git@blog.plcent.com:/data/git-reps/my-blog.git .deploy_git</span><br></pre></td></tr></table></figure><p>你也可以手动执行下面目录，生成仓库目录并保留提交历史。</p><h2 id="配置git仓库钩子"><a href="#配置git仓库钩子" class="headerlink" title="配置git仓库钩子"></a>配置git仓库钩子</h2><ol><li><p><strong>进入远程仓库的 hooks 目录</strong></p><p>远程仓库（裸仓库）的钩子脚本存放在 <code>hooks</code> 目录下，先通过 SSH 登录服务器，进入该目录。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cd</span> /data/git-reps/my-blog.git/hooks</span></span><br></pre></td></tr></table></figure></li><li><h4 id="创建-post-receive-钩子脚本"><a href="#创建-post-receive-钩子脚本" class="headerlink" title="创建 post-receive 钩子脚本"></a>创建 post-receive 钩子脚本</h4><p>在 <code>hooks</code> 目录下创建 <code>post-receive</code> 文件（无后缀），并写入执行逻辑：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 远程仓库地址（裸仓库）</span></span><br><span class="line">REPO_DIR=/data/git-reps/my-blog.git</span><br><span class="line"></span><br><span class="line"><span class="comment"># 目标部署目录</span></span><br><span class="line">DEPLOY_DIR=/app/blog</span><br><span class="line"></span><br><span class="line"><span class="comment"># 日志文件</span></span><br><span class="line">LOG_FILE=~/.log/git-deploy.log</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查并创建日志目录（如果不存在）</span></span><br><span class="line">LOG_DIR=$(<span class="built_in">dirname</span> <span class="string">&quot;<span class="variable">$LOG_FILE</span>&quot;</span>)  <span class="comment"># 提取目录部分（即 ~/.log）</span></span><br><span class="line"><span class="keyword">if</span> [ ! -d <span class="string">&quot;<span class="variable">$LOG_DIR</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">  <span class="built_in">mkdir</span> -p <span class="string">&quot;<span class="variable">$LOG_DIR</span>&quot;</span>  <span class="comment"># -p 确保父目录不存在时也能创建，且不报错</span></span><br><span class="line">  <span class="built_in">echo</span> <span class="string">&quot;[<span class="subst">$(date +&#x27;%Y-%m-%d %H:%M:%S&#x27;)</span>] 日志目录 <span class="variable">$LOG_DIR</span> 不存在，已自动创建&quot;</span> &gt;&gt; <span class="string">&quot;<span class="variable">$LOG_FILE</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行以下命令，添加例外（当前用户执行即可，无需 root）</span></span><br><span class="line">git config --global --add safe.directory <span class="variable">$REPO_DIR</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;部署开始于 <span class="subst">$(date)</span>&quot;</span> &gt;&gt; <span class="variable">$LOG_FILE</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果不存在git仓库目录，克隆git仓库</span></span><br><span class="line"><span class="keyword">if</span> [ ! -d <span class="variable">$DEPLOY_DIR</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">mkdir</span> -R <span class="variable">$DEPLOY_DIR</span></span><br><span class="line">    git <span class="built_in">clone</span> <span class="variable">$REPO_DIR</span> <span class="variable">$DEPLOY_DIR</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$DEPLOY_DIR</span> 不存在，重新拉取仓库&quot;</span> &gt;&gt; <span class="variable">$LOG_FILE</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">git checkout master</span><br><span class="line"><span class="comment"># 拉取最新代码</span></span><br><span class="line"><span class="comment"># 注意此处，指定路径</span></span><br><span class="line">git --work-tree=<span class="variable">$GIT_DIR</span> --git-dir=<span class="variable">$GIT_DIR</span>/.git pull &gt;&gt; <span class="variable">$LOG_FILE</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ $? eq 0 ]; <span class="keyword">then</span></span><br><span class="line">   <span class="built_in">echo</span> <span class="string">&quot;[<span class="subst">$(date +&#x27;%Y-%m-%d %H:%M:%S&#x27;)</span>] 拉取最新代码 success&quot;</span> &gt;&gt; <span class="variable">$LOG_FILE</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">   <span class="built_in">echo</span> <span class="string">&quot;[<span class="subst">$(date +&#x27;%Y-%m-%d %H:%M:%S&#x27;)</span>] 拉取最新代码 fail $?&quot;</span> &gt;&gt; <span class="variable">$LOG_FILE</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;部署完成 <span class="subst">$(date)</span>&quot;</span> &gt;&gt; <span class="variable">$LOG_FILE</span></span><br></pre></td></tr></table></figure></li><li><p>为脚本增加运行权限</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">chmod</span> +x post-receive</span></span><br></pre></td></tr></table></figure></li><li><p>测试</p><p>在服务器手动执行该脚本测试是否正常运行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cd</span> /data/git-reps/my-blog.git</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">./post-receive</span></span><br></pre></td></tr></table></figure></li></ol><h1 id="推送站点部署更新"><a href="#推送站点部署更新" class="headerlink" title="推送站点部署更新"></a>推送站点部署更新</h1><p>在本地执行推送hexo部署命令，即可将代码推送到服务器的git仓库，推送时即会触发钩子响应执行部署脚本。</p>   <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">hexo clean &amp;&amp; hexo generate &amp;&amp; hexo deploy</span></span><br></pre></td></tr></table></figure><blockquote><p><code>.deploy_git</code>目录部署推送的内容来自与public目录</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;通过在服务器上自建git远程仓库，通过&lt;code&gt;hexo-deployer-git&lt;/code&gt;实现自动推送到git仓库，利用仓库更新钩子函数实现站点自动更新。&lt;/p&gt;</summary>
    
    
    
    <category term="hexo" scheme="https://blog.plcent.com/categories/hexo/"/>
    
    
    <category term="hexo" scheme="https://blog.plcent.com/tags/hexo/"/>
    
  </entry>
  
  <entry>
    <title>SEO优化-sitemap站点地图</title>
    <link href="https://blog.plcent.com/seo-sitemap/"/>
    <id>https://blog.plcent.com/seo-sitemap/</id>
    <published>2025-10-20T16:32:46.000Z</published>
    <updated>2025-10-20T17:13:42.410Z</updated>
    
    <content type="html"><![CDATA[<p>详细介绍<code>Sitemap</code>的语法规则和搜索引擎搜录方法。</p><span id="more"></span><h1 id="什么是Sitemap"><a href="#什么是Sitemap" class="headerlink" title="什么是Sitemap"></a>什么是Sitemap</h1><p>Sitemap（即站点地图）就是您网站上各网页的列表。创建并提交Sitemap有助于搜索引擎发现并了解您网站上的所有网页。您还可以使用Sitemap提供有关您网站的其他信息，如上次更新日期、Sitemap文件的更新频率等，供搜索引擎Spider参考。</p><h1 id="支持的文件格式"><a href="#支持的文件格式" class="headerlink" title="支持的文件格式"></a>支持的文件格式</h1><p>搜索引擎支持的文件格式一般有：</p><ul><li><p>txt</p><p>此文本文件需要遵循以下指南：</p><ul><li><p>文本文件每行都必须有一个网址。网址中不能有换行</p></li><li><p>不应包含网址列表以外的任何信息</p></li><li><p>您必须书写完整的网址，包括 http</p></li><li><p>每个文本文件最多可包含 50,000 个网址，并且应小于10MB（10,485,760字节）。如果网站所包含的网址超过 50,000 个，则可将列表分割成多个文本文件，然后分别添加每个文件</p></li><li><p>文本文件需使用 UTF-8 编码或GBK编码。</p></li></ul></li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">http://www.example.com/repaste/101562698_5230191316.html</span><br><span class="line">http://www.example.com/repaste/101586283_5230215075.html</span><br><span class="line">http://www.example.com/repaste/101639435_5230310576.html  </span><br></pre></td></tr></table></figure><ul><li><p>xml</p><p>单个xml数据格式如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span><br><span class="line">&lt;!-- XML文件需以utf-8编码--&gt;</span><br><span class="line">&lt;urlset&gt;</span><br><span class="line">&lt;!--必填标签--&gt;</span><br><span class="line">    &lt;url&gt;</span><br><span class="line">        &lt;!--必填标签,这是具体某一个链接的定义入口，每一条数据都要用&lt;url&gt;和&lt;/url&gt;包含在里面，这是必须的 --&gt;</span><br><span class="line">        &lt;loc&gt;http://www.yoursite.com/yoursite.html&lt;/loc&gt;</span><br><span class="line">        &lt;!--必填,URL链接地址,长度不得超过256字节--&gt;</span><br><span class="line">        &lt;lastmod&gt;2009-12-14&lt;/lastmod&gt;</span><br><span class="line">        &lt;!--可以不提交该标签,用来指定该链接的最后更新时间--&gt;</span><br><span class="line">        &lt;changefreq&gt;daily&lt;/changefreq&gt;</span><br><span class="line">        &lt;!--可以不提交该标签,用这个标签告诉此链接可能会出现的更新频率 --&gt;</span><br><span class="line">        &lt;priority&gt;0.8&lt;/priority&gt;</span><br><span class="line">        &lt;!--可以不提交该标签,用来指定此链接相对于其他链接的优先权比值，此值定于0.0-1.0之间--&gt;</span><br><span class="line">    &lt;/url&gt;</span><br><span class="line">    &lt;url&gt;</span><br><span class="line">        &lt;loc&gt;http://www.yoursite.com/yoursite2.html&lt;/loc&gt;</span><br><span class="line">        &lt;lastmod&gt;2010-05-01&lt;/lastmod&gt;</span><br><span class="line">        &lt;changefreq&gt;daily&lt;/changefreq&gt;</span><br><span class="line">        &lt;priority&gt;0.8&lt;/priority&gt;</span><br><span class="line">    &lt;/url&gt;</span><br><span class="line">&lt;/urlset&gt;</span><br></pre></td></tr></table></figure><p>若有多条url，按照上述格式重复<url></url>之间的片断，列明所有url地址，打包到一个xml文件</p></li></ul><h1 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h1><ul><li><p>一个Sitemap文件包含的网址不得超过 5 万个，且文件大小不得超过 10 MB。如果您的Sitemap超过了这些限值，请将其拆分为几个小的Sitemap。这些限制条件有助于确保您的网络服务器不会因提供大文件而超载。</p></li><li><p>一个站点支持提交的sitemap链接个数必须小于5万个，多于5万个后会不再处理，并显示“链接数超”的提示。</p></li></ul><h1 id="自动生成工具"><a href="#自动生成工具" class="headerlink" title="自动生成工具"></a>自动生成工具</h1><p>在 Hexo 博客中生成 Sitemap 可以帮助搜索引擎更高效地抓取和索引您的网站内容。以下是设置和生成 Sitemap 的步骤。</p><ol><li>安装插件：</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-sitemap --save</span><br></pre></td></tr></table></figure><ol start="2"><li>修改配置文件</li></ol><p>打开 Hexo 的主配置文件 <em>_config.yml</em>。</p><p>添加以下内容：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">sitemap:</span></span><br><span class="line"><span class="attr">path:</span> <span class="string">sitemap.xml</span></span><br></pre></td></tr></table></figure><p>确保配置文件中的 <em>url</em> 和 <em>root</em> 设置正确，因为 Sitemap 会根据这些生成完整链接。</p><ol start="3"><li>生成 Sitemap</li></ol><p>执行以下命令生成站点：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo clean &amp;&amp; hexo generate</span><br></pre></td></tr></table></figure><p>在 <em>public</em> 文件夹中，您将看到生成的 <em>sitemap.xml</em> 和（如果安装了百度插件）<em>baidusitemap.xml</em> 文件。</p><h1 id="提交到搜索引擎"><a href="#提交到搜索引擎" class="headerlink" title="提交到搜索引擎"></a>提交到搜索引擎</h1><p><strong>Google</strong>: 登录 <a href="https://search.google.com/search-console">Google Search Console</a>，添加您的网站并提交 <em>sitemap.xml</em>。<strong>百度</strong>: 登录 <a href="https://ziyuan.baidu.com/">百度站长平台</a>，验证网站后提交 <em>sitemap.xml</em>。</p><p>以百度为例，百度提供<code>快速抓取</code>、<code>普通收录</code>功能，普通用户使用<code>普通收录</code>功能即可，主动向搜索引擎提交数据。</p><p><img src="/seo-sitemap/1760979776638.png" alt="1760979776638" loading="lazy"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;详细介绍&lt;code&gt;Sitemap&lt;/code&gt;的语法规则和搜索引擎搜录方法。&lt;/p&gt;</summary>
    
    
    
    <category term="seo" scheme="https://blog.plcent.com/categories/seo/"/>
    
    
    <category term="seo" scheme="https://blog.plcent.com/tags/seo/"/>
    
  </entry>
  
  <entry>
    <title>SEO优化-robots</title>
    <link href="https://blog.plcent.com/seo-robots/"/>
    <id>https://blog.plcent.com/seo-robots/</id>
    <published>2025-10-20T14:56:00.000Z</published>
    <updated>2025-10-20T16:43:31.283Z</updated>
    
    <content type="html"><![CDATA[<p>本文详细介绍了<code>robots.txt</code>的作用、语法、配置规则，同时针对搜索引擎爬虫的另外两种更为细粒度的规范<code>Robots Meta</code>、<code>X-Robots-Tag</code>进行说明。</p><span id="more"></span><h1 id="什么是robots文件"><a href="#什么是robots文件" class="headerlink" title="什么是robots文件"></a>什么是robots文件</h1><p>Robots是站点与spider沟通的重要渠道，站点通过robots文件声明本网站中不想被搜索引擎抓取的部分或者指定搜索引擎只抓取特定的部分。</p><p>搜索引擎使用spider程序自动访问互联网上的网页并获取网页信息。spider在访问一个网站时，会首先会检查该网站的根域下是否有一个叫做 robots.txt的纯文本文件，这个文件用于指定spider在您网站上的抓取范围。您可以在您的网站中创建一个robots.txt，在文件中声明 该网站中不想被搜索引擎抓取的部分或者指定搜索引擎只抓取特定的部分。</p><p>请注意，仅当您的网站包含不希望被搜索引擎收录的内容时，才需要使用robots.txt文件。如果您希望搜索引擎抓取网站上所有内容，请勿建立robots.txt文件。</p><blockquote><p>robots协议并不是一个规范，而只是约定俗成的，所以并不能保证网站的隐私。</p><p>并非所有的搜索引擎都严格遵循robots.txt协议。一些爬虫可能会忽视robots.txt文件中的指令，从而访问并索引您希望隐藏的页面。</p></blockquote><h1 id="robots-txt文件放在哪里"><a href="#robots-txt文件放在哪里" class="headerlink" title="robots.txt文件放在哪里"></a>robots.txt文件放在哪里</h1><p>robots.txt文件应该放置在网站根目录下。举例来说，当spider访问一个网站时，首先会检查该网站中是否存在<code>http://yourhost.com/robots.txt</code>这个文件，如果 Spider找到这个文件，它就会根据这个文件的内容，来确定它访问权限的范围。</p><h1 id="robots-txt语法"><a href="#robots-txt语法" class="headerlink" title="robots.txt语法"></a>robots.txt语法</h1><p>robots文件包含一条或更多的记录，这些记录通过空行分开（以CR,CR&#x2F;NL, or NL作为结束符），每一条记录的格式如下所示：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;指令&gt;:&lt;可选空格&gt;&lt;指令值&gt;&lt;可选空格&gt;</span><br></pre></td></tr></table></figure><p>在该文件中可以使用#进行注解，具体使用方法和UNIX中的惯例一样。该文件中的记录通常以一行或多行User-agent开始，后面加上若干指令行。</p><p>在robots.txt文件中，有几种主要指令可以使用：</p><ul><li><p><strong>User-agent</strong>：指定特定的搜索引擎爬虫。</p></li><li><p><strong>Allow</strong>：允许爬虫访问某个页面或目录。一个网站的所有URL默认是Allow的，所以Allow通常与Disallow搭配使用，实现允许访问一部分网页同时禁止访问其它所有URL的功能。</p><p>例如</p><p><code>Allow:/hibaidu</code>允许robot访问&#x2F;hibaidu.htm、&#x2F;hibaiducom.html、&#x2F;hibaidu&#x2F;com.html。</p></li><li><p><strong>Disallow</strong>：阻止爬虫访问某个页面或目录。这个值可以是一条完整的路径，也可以是路径的非空前缀，以Disallow项的值开头的URL不会被 robot访问。</p><p>例如</p><p><code>Disallow:/help</code>禁止robot访问&#x2F;help.html、&#x2F;helpabc.html、&#x2F;help&#x2F;index.html；</p><p><code>Disallow:/help/</code>则允许robot访问&#x2F;help.html、&#x2F;helpabc.html，不能访问&#x2F;help&#x2F;index.html；</p><p><code>Disallow:</code>说明允许robot访问该网站的所有url</p><p>在”&#x2F;robots.txt”文件中，至少要有一条Disallow记录。如果”&#x2F;robots.txt”不存在或者为空文件，则对于所有的搜索引擎robot，该网站都是开放的。</p></li><li><p><strong>Crawl-delay</strong>：设置爬虫访问的延迟。</p></li><li><p><strong>Sitemap</strong>：提供网站地图的链接，帮助爬虫更好地抓取网站。</p></li></ul><p>其中，<strong>Allow</strong>、<strong>Disallow</strong>支持通配符、<code>$</code>来模糊匹配url。</p><pre><code>- **\***：匹配0或多个任意字符- **$**：匹配行结束符。</code></pre><h2 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h2><p>Disallow: &#x2F;<em>?</em> 禁止访问网站中所有包含问号 (?) 的网址</p><p>Disallow: &#x2F;.jpg$ 禁止抓取网页所有的.<a href="https://baike.baidu.com/item/jpg%E6%A0%BC%E5%BC%8F/88929?fromModule=lemma_inlink">jpg格式</a>的图片</p><p>Allow: .htm$ 仅允许访问以”.htm”为后缀的URL。</p><p>以本站robots为例。</p><p>运行所有爬虫访问，但不允许访问以下目录</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">User-agent: *</span><br><span class="line">DisAllow: /css/</span><br><span class="line">DisAllow: /js/</span><br><span class="line">DisAllow: /img/</span><br><span class="line">Sitemap: https://blog.plcent.com/baidusitemap.xml</span><br><span class="line">Sitemap: https://blog.plcent.com/sitemap.xml</span><br></pre></td></tr></table></figure><h2 id="站点地图"><a href="#站点地图" class="headerlink" title="站点地图"></a>站点地图</h2><p>针对robots中的配置项<code>sitemap</code>，通过文章进行说明，参见：<a href="/seo-sitemap/"  target="_blank">SEO优化-sitemap站点地图</a></p><h2 id="robots生成器"><a href="#robots生成器" class="headerlink" title="robots生成器"></a>robots生成器</h2><p>可以使用站长工具来生成robots</p><p><a href="https://robots.bmcx.com/">robots.txt生成器 - robots.txt写法 - robots协议</a></p><p><a href="https://tool.chinaz.com/robots/">robots文件生成 - 站长工具</a></p><h2 id="如何测试robots-txt是否正确"><a href="#如何测试robots-txt是否正确" class="headerlink" title="如何测试robots.txt是否正确"></a>如何测试robots.txt是否正确</h2><p>各大搜搜引擎都会提供检查工具，例如百度站长工具：<a href="https://ziyuan.baidu.com/robots/intro">Robots_robots文件检测工具_站长工具_网站支持_百度搜索资源平台</a>中，提供了<code>robots.txt</code>测试工具，点击<code>检测</code>即可查看结果。</p><p><img src="/seo-robots/1760977403352.png" alt="1760977403352" loading="lazy"></p><h2 id="配置生效设置"><a href="#配置生效设置" class="headerlink" title="配置生效设置"></a>配置生效设置</h2><p>在百度站长工具中，检测自己的站点的配置结果：<a href="https://ziyuan.baidu.com/robots/index">https://ziyuan.baidu.com/robots/index</a></p><p><img src="/seo-robots/1760977665685.png" alt="1760977665685" loading="lazy"></p><h1 id="Robots-Meta"><a href="#Robots-Meta" class="headerlink" title="Robots Meta"></a>Robots Meta</h1><p>Robots.txt文件主要是限制整个站点或者目录的搜索引擎访问情况，而在html中的Robots Meta标签则主要是针对一个个具体的页面。</p><p>MDN中 html-meta中详细说明了该标签的用法：<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/name/robots"><meta name="robots"> - HTML | MDN</a></p><h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;robots&quot;</span> <span class="attr">content</span>=<span class="string">&quot;&lt;value&gt;&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure><p><code>content</code>必须定义该属性，其值设置协作搜索引擎机器人的索引和抓取行为。 接受以下一个或多个关键字作为逗号分隔的列表：<code>content</code></p><ul><li><strong>index</strong>：允许机器人为页面编制索引。这是默认行为。 被所有主要爬虫使用</li><li><strong>noindex</strong>：请求机器人不为页面编制索引。 被所有主要爬虫使用</li><li><strong>follow</strong>：允许机器人点击页面上的链接。这是默认行为。 被所有主要爬虫使用</li><li><strong>nofollow</strong>：请求机器人不要点击页面上的链接。 被所有主要爬虫使用</li><li><strong>all</strong> 相当于<code>index, follow</code></li><li><strong>none</strong>：<code>noindex, nofollow</code></li><li><strong>noarchive</strong>：请求搜索引擎不缓存页面内容</li><li><strong>nosnippet</strong>：防止在搜索引擎结果中显示页面的任何描述</li><li><strong>noimageindex</strong>：请求此页面不显示为索引图像的引用页面</li><li><strong>nocache</strong>：<code>noarchive</code>的同义词</li></ul><h2 id="示例-1"><a href="#示例-1" class="headerlink" title="示例"></a>示例</h2><p>不允许爬虫点击网页上的链接，不允许爬虫为网页建立索引</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;robots&quot;</span> <span class="attr">content</span>=<span class="string">&quot;nofollow, noindex&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure><h1 id="X-Robots-Tag"><a href="#X-Robots-Tag" class="headerlink" title="X-Robots-Tag"></a>X-Robots-Tag</h1><p><strong>X-Robots-Tag</strong> <a href="https://developer.mozilla.org/en-US/docs/Glossary/Response_header">响应头</a>定义了<a href="https://developer.mozilla.org/en-US/docs/Glossary/Crawler">爬虫</a>应如何为 URL 编制索引。 虽然它不是任何规范的一部分，但它是与搜索机器人、网络爬虫和类似用户代理通信的事实上的标准方法。 </p><p>该响应头和<code>robots.txt</code>、<code>Robots Meta</code>的区别是，<code>X-Robots-Tag</code>HTTP 标头对于非 HTML 文档（如图像、PDF 或其他媒体）非常有用。</p><p>MDN中 X-Robots-Tag 中详细说明了该响应头的用法：<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag">X-Robots-Tag 标头 - HTTP |MDN</a></p><h2 id="语法-1"><a href="#语法-1" class="headerlink" title="语法"></a>语法</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">X-Robots-Tag: &lt;indexing-rule&gt;</span><br><span class="line">X-Robots-Tag: &lt;indexing-rule&gt;, …, &lt;indexing-ruleN&gt;</span><br></pre></td></tr></table></figure><p>可选指定后续规则应应用于的用户代理：<code>&lt;bot-name&gt;:</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">X-Robots-Tag: &lt;indexing-rule&gt;, &lt;bot-name&gt;: &lt;indexing-rule&gt;</span><br><span class="line">X-Robots-Tag: &lt;bot-name&gt;: &lt;indexing-rule&gt;, …, &lt;indexing-ruleN&gt;</span><br></pre></td></tr></table></figure><p><code>indexing-rule</code> 可以使用以下任何索引规则：</p><ul><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#all"><code>all</code></a></p><p>在搜索结果中编入索引或投放没有限制。 此规则是默认值，如果显式列出，则无效。</p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#noindex"><code>noindex</code></a></p><p>请勿在搜索结果中显示此页面、媒体或资源。 如果省略，则页面、媒体或资源可能会被编入索引并显示在搜索结果中。</p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#nofollow"><code>nofollow</code></a></p><p>请勿点击此页面上的链接。 如果省略，搜索引擎可能会使用页面上的链接来发现这些链接页面。</p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#none"><code>none</code></a></p><p>相当于 .<code>noindex, nofollow</code></p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#nosnippet"><code>nosnippet</code></a></p><p>请勿在此页面的搜索结果中显示文本片段或视频预览。 静态图像缩略图（如果可用）可能仍然可见。 如果省略，搜索引擎可能会根据页面上找到的信息生成文本片段和视频预览。 要排除内容的某些部分不显示在搜索结果代码段中，请使用 <a href="https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr"><code>data-nosnippet</code> HTML 属性</a>。</p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#indexifembedded"><code>indexifembedded</code></a></p><p>如果页面的内容通过 iframe 或类似的 HTML 元素嵌入到另一个页面中，则允许搜索引擎对页面内容进行索引，该规则， 只有当它伴随着<code>noindex</code>值存在时才有效果。<code>indexifembedded noindex</code></p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#max-snippet_number"><code>max-snippet: &lt;number&gt;</code></a></p><p>最多使用字符数作为此搜索结果的文本片段。 如果未指定有效值，则忽略。</p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#max-image-preview_setting"><code>max-image-preview: &lt;setting&gt;</code></a></p><p>搜索结果中此页面的图片预览的图片尺寸大小。 如果省略，搜索引擎可能会显示默认尺寸的图像预览。 如果不希望搜索引擎使用较大的缩略图图像，请指定值<code>max-image-preview: standard</code><br>值包括：</p><ul><li><strong>none</strong>：不显示图像预览；</li><li><strong>standard</strong>：可能会显示默认图像预览；</li><li><strong>large</strong>：可能会显示更大的图像预览，直至视口的宽度。</li></ul></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#max-video-preview_number"><code>max-video-preview: &lt;number&gt;</code></a></p><p>在搜索结果中，最多使用秒数作为此页面上视频的视频片段。如果省略，搜索引擎可能会在搜索结果中显示视频片段，并由搜索引擎决定预览时长。如果未指定有效值，则忽略。<br>特殊值如下所示：</p><ul><li><strong>0</strong>：根据设置，最多只能使用静态图像；</li><li><strong>-1</strong>：没有视频长度限制</li></ul></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#notranslate"><code>notranslate</code></a></p><p>请勿在搜索结果中提供此页面的翻译。 如果省略，搜索引擎可能会将搜索结果标题和代码片段翻译成搜索查询的语言。</p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#noimageindex"><code>noimageindex</code></a></p><p>请勿将此页面上的图像编入索引。 如果省略，页面上的图像可能会被索引并显示在搜索结果中。</p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#unavailable_after_datetime"><code>unavailable_after: &lt;date/time&gt; </code></a></p><p>请求在指定的<code>&lt;date/time&gt;</code>之后不在搜索结果中显示此页面。 如果未指定有效值，则忽略。 必须以 <a href="https://datatracker.ietf.org/doc/html/rfc822">RFC 822</a>、<a href="https://datatracker.ietf.org/doc/html/rfc850">RFC 850</a> 或 ISO 8601 等格式指定日期。<br>默认情况下，内容没有到期日期。 如果省略，此页面可能会无限期地显示在搜索结果中。 爬虫预计会在指定日期和时间之后大幅降低网址的抓取速率。</p></li></ul><h2 id="示例-2"><a href="#示例-2" class="headerlink" title="示例"></a>示例</h2><p>以下标头添加了 ，要求抓取工具不要在搜索结果中显示此页面、媒体或资源：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 200 OK</span><br><span class="line">Date: Tue, 03 Dec 2024 17:08:49 GMT</span><br><span class="line">X-Robots-Tag: noindex</span><br></pre></td></tr></table></figure><h3 id="多个标头"><a href="#多个标头" class="headerlink" title="多个标头"></a>多个标头</h3><p>以下响应有两个标头，每个标头都指定了索引规则：<code>X-Robots-Tag</code></p><p>http复制</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 200 OK</span><br><span class="line">Date: Tue, 03 Dec 2024 17:08:49 GMT</span><br><span class="line">X-Robots-Tag: noimageindex</span><br><span class="line">X-Robots-Tag: unavailable_after: Wed, 03 Dec 2025 13:09:53 GMT</span><br></pre></td></tr></table></figure><h3 id="指定用户代理"><a href="#指定用户代理" class="headerlink" title="指定用户代理"></a>指定用户代理</h3><p>可以指定规则应应用于哪个用户代理。 以下示例包含两个标头，它们要求不要点击此页面上的链接，并且虚构的爬虫不要为该页面编制索引或点击其上的任何链接：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 200 OK</span><br><span class="line">Date: Tue, 03 Dec 2024 17:08:49 GMT</span><br><span class="line">X-Robots-Tag: BadBot: noindex, nofollow</span><br><span class="line">X-Robots-Tag: googlebot: nofollow</span><br></pre></td></tr></table></figure><p>在下面的响应中，定义了相同的索引规则，但在单个标头中。每个索引规则都适用于其后面指定的用户代理：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 200 OK</span><br><span class="line">Date: Tue, 03 Dec 2024 17:08:49 GMT</span><br><span class="line">X-Robots-Tag: BadBot: noindex, nofollow, googlebot: nofollow</span><br></pre></td></tr></table></figure><p>对于指定了多个爬虫和不同规则的情况，搜索引擎将使用否定规则的总和。例如：</p><p> <code>googlebot: noindex, nofollow</code>，<code>others: nofollow</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">X-Robots-Tag: nofollow</span><br><span class="line">X-Robots-Tag: googlebot: noindex</span><br></pre></td></tr></table></figure><h2 id="优先级"><a href="#优先级" class="headerlink" title="优先级"></a>优先级</h2><p>当<code>robots.txt</code>、<code>Robots Meta</code>、<code>X-Robots-Tag</code>定义的优先级冲突时，采用更为严格的限制规则为准。</p><p>参见：<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag#description">X-Robots-Tag 标头 - HTTP |MDN</a></p><h1 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h1><p>官方参考资料：</p><ul><li><p><a href="https://www.robotstxt.org/robotstxt.html">The Web Robots Pages</a></p></li><li><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/name/robots"><meta name="robots"> - HTML | MDN</a></p></li><li><p><a href="https://ziyuan.baidu.com/college/courseinfo?id=267&page=10">平台工具使用手册_robots_搜索学堂_百度搜索资源平台</a></p></li></ul><p>网络教程：</p><ul><li><a href="https://juejin.cn/post/7429610221247807522">90% 的人都用错了！robots.txt 正确用法全揭秘！你知道吗？实际上，90%的网站管理员在使用robots.tx - 掘金</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;本文详细介绍了&lt;code&gt;robots.txt&lt;/code&gt;的作用、语法、配置规则，同时针对搜索引擎爬虫的另外两种更为细粒度的规范&lt;code&gt;Robots Meta&lt;/code&gt;、&lt;code&gt;X-Robots-Tag&lt;/code&gt;进行说明。&lt;/p&gt;</summary>
    
    
    
    <category term="seo" scheme="https://blog.plcent.com/categories/seo/"/>
    
    
    <category term="seo" scheme="https://blog.plcent.com/tags/seo/"/>
    
  </entry>
  
  <entry>
    <title>twikoo评论系统阿里云服务器docker部署手册</title>
    <link href="https://blog.plcent.com/hexo-icarus-twikoo-deploy/"/>
    <id>https://blog.plcent.com/hexo-icarus-twikoo-deploy/</id>
    <published>2025-10-05T14:46:00.000Z</published>
    <updated>2025-10-08T03:40:24.068Z</updated>
    
    <content type="html"><![CDATA[<p>本文详细介绍了在阿里云云主机上，从<code>docker</code>&#x2F;<code>git</code>环境安装开始，编译<code>twikoo</code> <code>docker</code>镜像，通过<code>docker compose</code>启动<code>twikoo</code>服务，并通过<code>nginx</code>对外暴露服务的完整过程。</p><span id="more"></span><h1 id="阿里云服务器安装docker环境"><a href="#阿里云服务器安装docker环境" class="headerlink" title="阿里云服务器安装docker环境"></a>阿里云服务器安装docker环境</h1><p>参照阿里云官方教程：<a href="https://help.aliyun.com/zh/ecs/user-guide/install-and-use-docker?spm=a2c4g.11186623.help-menu-25365.d_0_12_3_6.2dea717cP81pvm&scm=20140722.H_51853._.OR_help-T_cn~zh-V_1">在Linux上安装Docker和Docker Compose_云服务器 ECS(ECS)-阿里云帮助中心</a></p><p>进行安装，使用命令行的方式进行安装。</p><h2 id="卸载旧版本的Docker"><a href="#卸载旧版本的Docker" class="headerlink" title="卸载旧版本的Docker"></a>卸载旧版本的Docker</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#删除Docker相关源</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">rm</span> -f /etc/yum.repos.d/docker*.repo</span><br><span class="line"><span class="comment">#卸载Docker和相关的软件包</span></span><br><span class="line"><span class="built_in">sudo</span> dnf -y remove \</span><br><span class="line">docker-ce \</span><br><span class="line">containerd.io \</span><br><span class="line">docker-ce-rootless-extras \</span><br><span class="line">docker-buildx-plugin \</span><br><span class="line">docker-ce-cli \</span><br><span class="line">docker-compose-plugin</span><br></pre></td></tr></table></figure><h2 id="安装Docker社区版本"><a href="#安装Docker社区版本" class="headerlink" title="安装Docker社区版本"></a>安装Docker社区版本</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#添加Docker软件包源</span></span><br><span class="line"><span class="built_in">sudo</span> wget -O /etc/yum.repos.d/docker-ce.repo http://mirrors.cloud.aliyuncs.com/docker-ce/linux/centos/docker-ce.repo</span><br><span class="line"><span class="built_in">sudo</span> sed -i <span class="string">&#x27;s|https://mirrors.aliyun.com|http://mirrors.cloud.aliyuncs.com|g&#x27;</span> /etc/yum.repos.d/docker-ce.repo</span><br><span class="line"><span class="comment">#Alibaba Cloud Linux3专用的dnf源兼容插件</span></span><br><span class="line"><span class="built_in">sudo</span> dnf -y install dnf-plugin-releasever-adapter --repo alinux3-plus</span><br><span class="line"><span class="comment">#安装Docker社区版本，容器运行时containerd.io，以及Docker构建和Compose插件</span></span><br><span class="line"><span class="built_in">sudo</span> dnf -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin</span><br></pre></td></tr></table></figure><blockquote><p>该步骤已经安装好docker-compose</p></blockquote><h2 id="启动Docker并设置开机自启"><a href="#启动Docker并设置开机自启" class="headerlink" title="启动Docker并设置开机自启"></a>启动Docker并设置开机自启</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#启动Docker</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl start docker</span><br><span class="line"><span class="comment">#设置Docker守护进程在系统启动时自动启动</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> docker</span><br></pre></td></tr></table></figure><h2 id="检查docker是否安装正常"><a href="#检查docker是否安装正常" class="headerlink" title="检查docker是否安装正常"></a>检查docker是否安装正常</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker -v</span><br></pre></td></tr></table></figure><p><img src="/hexo-icarus-twikoo-deploy/docker-v.png" alt="docker-v" loading="lazy"></p><h2 id="配置阿里云专属镜像源"><a href="#配置阿里云专属镜像源" class="headerlink" title="配置阿里云专属镜像源"></a>配置阿里云专属镜像源</h2><ol><li>登录<a href="https://cr.console.aliyun.com/?spm=a2c4g.11186623.0.0.6a6e4c309Z35vg">容器镜像服务控制台</a>，在左侧导航栏选择****镜像工具** &gt; *<em>镜像加速器*</em><strong>，在</strong>镜像加速器<strong>页面获取</strong>加速器地址**。</li><li>编辑Docker配置文件<code>/etc/docker/daemon.json</code>。若文件不存在，先创建。</li><li>重启docker服务</li></ol><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /etc/docker</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">tee</span> /etc/docker/daemon.json &lt;&lt;-<span class="string">&#x27;EOF&#x27;</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;registry-mirrors&quot;</span>: [<span class="string">&quot;&lt;加速器地址&gt;&quot;</span>]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br><span class="line"><span class="built_in">sudo</span> systemctl daemon-reload</span><br><span class="line"><span class="built_in">sudo</span> systemctl restart docker            </span><br></pre></td></tr></table></figure><h1 id="采用docker-compose的方式安装twikoo"><a href="#采用docker-compose的方式安装twikoo" class="headerlink" title="采用docker-compose的方式安装twikoo"></a>采用docker-compose的方式安装twikoo</h1><p>其实这一步才开始安装<code>twikoo</code>，上面的步骤是在阿里云主机中准备<code>docker</code>运行环境，每个环境不同，只需要依据环境进行准备即可。</p><p>参考<code>twikoo</code>官网文档进行安装：<a href="https://twikoo.js.org/backend.html#%E7%A7%81%E6%9C%89%E9%83%A8%E7%BD%B2-docker">云函数部署 | Twikoo 文档</a></p><h2 id="安装依赖环境"><a href="#安装依赖环境" class="headerlink" title="安装依赖环境"></a>安装依赖环境</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装git和nodejs环境</span></span><br><span class="line">yum install git</span><br></pre></td></tr></table></figure><blockquote><p>安装git是为了拉取代码</p><p>安装nodejs，此处其实使用不到，顺手安装后面</p></blockquote><h2 id="获取twikoo代码并编译镜像文件"><a href="#获取twikoo代码并编译镜像文件" class="headerlink" title="获取twikoo代码并编译镜像文件"></a>获取twikoo代码并编译镜像文件</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 拉取代码</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/twikoojs/twikoo.git</span><br><span class="line"><span class="built_in">cd</span> twikoo</span><br><span class="line"><span class="comment"># 编译docker 镜像</span></span><br><span class="line">docker build . -t  imaegoo/twikoo:latest</span><br></pre></td></tr></table></figure><p>查看编译好的镜像</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker images</span><br></pre></td></tr></table></figure><p><img src="/hexo-icarus-twikoo-deploy/1759687546996.png" alt="1759687546996" loading="lazy"></p><h2 id="编辑docker-compose-yml文件"><a href="#编辑docker-compose-yml文件" class="headerlink" title="编辑docker-compose.yml文件"></a>编辑docker-compose.yml文件</h2><p>在项目更目录下，存在一个<code>docker-compose.yml</code>配置文件，主要修改<code>volumes</code>为<code>./data:/app/data</code>，将容器内文件夹<code>/app/data</code>同步到当前文件夹<code>./data</code>下。做到评论数据持久化。</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">&#x27;3&#x27;</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">twikoo:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">imaegoo/twikoo</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">twikoo</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">8080</span><span class="string">:8080</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">TWIKOO_THROTTLE:</span> <span class="number">1000</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data:/app/data</span></span><br></pre></td></tr></table></figure><p>启动服务后，在当前文件夹下</p><h2 id="docker-compose启动服务"><a href="#docker-compose启动服务" class="headerlink" title="docker compose启动服务"></a>docker compose启动服务</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 进入到代码目录下</span></span><br><span class="line"><span class="built_in">cd</span> twikoo</span><br><span class="line"><span class="comment"># 后台启动服务</span></span><br><span class="line">docker compose up -d</span><br></pre></td></tr></table></figure><p><img src="/hexo-icarus-twikoo-deploy/1759687967324.png" alt="1759687967324" loading="lazy"></p><h2 id="测试服务是否完成启动"><a href="#测试服务是否完成启动" class="headerlink" title="测试服务是否完成启动"></a>测试服务是否完成启动</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 直接在命令行探测服务端口</span></span><br><span class="line">curl http://localhost:8080</span><br></pre></td></tr></table></figure><p>如果可以向下面这样正常输出说明服务启动正常</p><p><img src="/hexo-icarus-twikoo-deploy/1759688032175.png" alt="1759688032175" loading="lazy"></p><h1 id="将服务暴露公网"><a href="#将服务暴露公网" class="headerlink" title="将服务暴露公网"></a>将服务暴露公网</h1><p>截至目前，服务已经在服务器内部可以正常访问了，对外还不能提供服务。下一步需要将服务暴露在公网上，然后在配置前端部分。</p><h2 id="放开服务器端口"><a href="#放开服务器端口" class="headerlink" title="放开服务器端口"></a>放开服务器端口</h2><p>配置服务器安全组，放开必要的端口，可以放开下面几个端口</p><p><img src="/hexo-icarus-twikoo-deploy/1759689536452.png" alt="1759689536452" loading="lazy"></p><blockquote><p>放开上述端口后，使用公网IP（http:&#x2F;&#x2F;&lt;公网IP&gt;:8080），就可以访问启动的<code>twikoo</code>服务</p><p>如果要使用域名访问该服务，还需要通过nginx转发，同时为nginx配置一个公网暴露的端口，此处，在你测试完8080端口后，可以取消该端口暴露，使用其他如8081端口，通过域名访问（https:&#x2F;&#x2F;<host>.com:8081）</p></blockquote><h2 id="安装nginx"><a href="#安装nginx" class="headerlink" title="安装nginx"></a>安装nginx</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y nginx</span><br></pre></td></tr></table></figure><h2 id="禁用默认站点nginx"><a href="#禁用默认站点nginx" class="headerlink" title="禁用默认站点nginx"></a>禁用默认站点nginx</h2><p>可以参考阿里云官方帮助文档进行配置：<a href="https://help.aliyun.com/zh/ecs/user-guide/build-multiple-websites-on-a-linux-instance?spm=a2c4g.11186623.help-menu-25365.d_0_12_1_3.3665c1c8mXj736&scm=20140722.H_171730._.OR_help-T_cn~zh-V_1">Nginx服务配置多站点_云服务器 ECS(ECS)-阿里云帮助中心</a></p><p>通过yum安装的nginx 配置文件在<code>/etc/nginx</code>目录下，默认配置文件为<code>nginx.conf</code></p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /etc/nginx</span><br><span class="line"><span class="built_in">cat</span> nginx.conf</span><br></pre></td></tr></table></figure><p>注释掉该文件中默认放开的80服务，所有站点通过自己配置文件进行配置。</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># For more information on configuration, see:</span></span><br><span class="line"><span class="comment">#   * Official English Documentation: http://nginx.org/en/docs/</span></span><br><span class="line"><span class="comment">#   * Official Russian Documentation: http://nginx.org/ru/docs/</span></span><br><span class="line"></span><br><span class="line"><span class="attribute">user</span> nginx;</span><br><span class="line"><span class="attribute">worker_processes</span> auto;</span><br><span class="line"><span class="attribute">error_log</span> /var/log/nginx/<span class="literal">error</span>.log;</span><br><span class="line"><span class="attribute">pid</span> /run/nginx.pid;</span><br><span class="line"></span><br><span class="line"><span class="comment"># Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.</span></span><br><span class="line"><span class="attribute">include</span> /usr/share/nginx/modules/<span class="regexp">*.conf</span>;</span><br><span class="line"></span><br><span class="line"><span class="section">events</span> &#123;</span><br><span class="line">    <span class="attribute">worker_connections</span> <span class="number">1024</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="section">http</span> &#123;</span><br><span class="line">    <span class="attribute">log_format</span>  main  <span class="string">&#x27;<span class="variable">$remote_addr</span> - <span class="variable">$remote_user</span> [<span class="variable">$time_local</span>] &quot;<span class="variable">$request</span>&quot; &#x27;</span></span><br><span class="line">                      <span class="string">&#x27;<span class="variable">$status</span> <span class="variable">$body_bytes_sent</span> &quot;<span class="variable">$http_referer</span>&quot; &#x27;</span></span><br><span class="line">                      <span class="string">&#x27;&quot;<span class="variable">$http_user_agent</span>&quot; &quot;<span class="variable">$http_x_forwarded_for</span>&quot;&#x27;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">access_log</span>  /var/log/nginx/access.log  main;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">sendfile</span>            <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">tcp_nopush</span>          <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">tcp_nodelay</span>         <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">keepalive_timeout</span>   <span class="number">65</span>;</span><br><span class="line">    <span class="attribute">types_hash_max_size</span> <span class="number">4096</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">include</span>             /etc/nginx/mime.types;</span><br><span class="line">    <span class="attribute">default_type</span>        application/octet-stream;</span><br><span class="line"></span><br><span class="line">    <span class="comment"># Load modular configuration files from the /etc/nginx/conf.d directory.</span></span><br><span class="line">    <span class="comment"># See http://nginx.org/en/docs/ngx_core_module.html#include</span></span><br><span class="line">    <span class="comment"># for more information.</span></span><br><span class="line">    <span class="attribute">include</span> /etc/nginx/conf.d/<span class="regexp">*.conf</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">#    server &#123;</span></span><br><span class="line"><span class="comment">#        listen       80;</span></span><br><span class="line"><span class="comment">#        listen       [::]:80;</span></span><br><span class="line"><span class="comment">#        server_name  _;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#       return 301 https://$host$request_uri;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#       root         /usr/share/nginx/html;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#       Load configuration files for the default server block.</span></span><br><span class="line"><span class="comment">#       include /etc/nginx/default.d/*.conf;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#       error_page 404 /404.html;</span></span><br><span class="line"><span class="comment">#           location = /40x.html &#123;</span></span><br><span class="line"><span class="comment">#       &#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#        error_page 500 502 503 504 /50x.html;</span></span><br><span class="line"><span class="comment">#           location = /50x.html &#123;</span></span><br><span class="line"><span class="comment">#        &#125;</span></span><br><span class="line"><span class="comment">#    &#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Settings for a TLS enabled server.</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#    server &#123;</span></span><br><span class="line"><span class="comment">#        listen       443 ssl http2;</span></span><br><span class="line"><span class="comment">#        listen       [::]:443 ssl http2;</span></span><br><span class="line"><span class="comment">#        server_name  _;</span></span><br><span class="line"><span class="comment">#        root         /usr/share/nginx/html;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#        ssl_certificate &quot;/etc/pki/nginx/server.crt&quot;;</span></span><br><span class="line"><span class="comment">#        ssl_certificate_key &quot;/etc/pki/nginx/private/server.key&quot;;</span></span><br><span class="line"><span class="comment">#        ssl_session_cache shared:SSL:1m;</span></span><br><span class="line"><span class="comment">#        ssl_session_timeout  10m;</span></span><br><span class="line"><span class="comment">#        ssl_ciphers PROFILE=SYSTEM;</span></span><br><span class="line"><span class="comment">#        ssl_prefer_server_ciphers on;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#        # Load configuration files for the default server block.</span></span><br><span class="line"><span class="comment">#        include /etc/nginx/default.d/*.conf;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#        error_page 404 /404.html;</span></span><br><span class="line"><span class="comment">#            location = /40x.html &#123;</span></span><br><span class="line"><span class="comment">#        &#125;</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment">#        error_page 500 502 503 504 /50x.html;</span></span><br><span class="line"><span class="comment">#            location = /50x.html &#123;</span></span><br><span class="line"><span class="comment">#        &#125;</span></span><br><span class="line"><span class="comment">#    &#125;</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="新增站点nginx配置"><a href="#新增站点nginx配置" class="headerlink" title="新增站点nginx配置"></a>新增站点nginx配置</h2><p>新增配置文件<code>/etc/nginx/conf.d/blog.conf</code>。下面是https服务的配置信息。配置完成后可以通过：</p><ul><li>https:&#x2F;&#x2F;<host>.com:8081 访问twikoo服务</li><li>https:&#x2F;&#x2F;<host>.com 访问博客主站点</li></ul><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 自定义站点配置</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 代理twikoo评论服务</span></span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">        <span class="attribute">listen</span> <span class="number">8081</span> ssl;</span><br><span class="line">        <span class="attribute">listen</span> [::]:<span class="number">8081</span> ssl;</span><br><span class="line">        <span class="attribute">server_name</span> &lt;your host name&gt;;</span><br><span class="line"></span><br><span class="line">        <span class="attribute">ssl_certificate</span> <span class="string">&quot;/etc/nginx/ssl/ssl.pem&quot;</span>;</span><br><span class="line">        <span class="attribute">ssl_certificate_key</span> <span class="string">&quot;/etc/nginx/ssl/ssl.key&quot;</span>;</span><br><span class="line">        <span class="attribute">ssl_session_cache</span> shared:SSL:<span class="number">1m</span>;</span><br><span class="line">        <span class="attribute">ssl_session_timeout</span>  <span class="number">10m</span>;</span><br><span class="line">        <span class="attribute">ssl_ciphers</span> PROFILE=SYSTEM;</span><br><span class="line">        <span class="attribute">ssl_prefer_server_ciphers</span> <span class="literal">on</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="section">location</span> / &#123;</span><br><span class="line">                <span class="attribute">proxy_pass</span> http://127.0.0.1:8080;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span>       <span class="number">443</span> ssl;</span><br><span class="line">    <span class="attribute">listen</span>       [::]:<span class="number">443</span> ssl;</span><br><span class="line">    <span class="attribute">server_name</span>  &lt;your host name&gt;;</span><br><span class="line">    <span class="comment"># 配置博客内容根目录</span></span><br><span class="line">    <span class="attribute">root</span>         /usr/share/nginx/html/blog;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">ssl_certificate</span> <span class="string">&quot;/etc/nginx/ssl/ssl.pem&quot;</span>;</span><br><span class="line">    <span class="attribute">ssl_certificate_key</span> <span class="string">&quot;/etc/nginx/ssl/ssl.key&quot;</span>;</span><br><span class="line">    <span class="attribute">ssl_session_cache</span> shared:SSL:<span class="number">1m</span>;</span><br><span class="line">    <span class="attribute">ssl_session_timeout</span>  <span class="number">10m</span>;</span><br><span class="line">    <span class="attribute">ssl_ciphers</span> PROFILE=SYSTEM;</span><br><span class="line">    <span class="attribute">ssl_prefer_server_ciphers</span> <span class="literal">on</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">error_page</span> <span class="number">404</span> /<span class="number">404</span>.html;</span><br><span class="line">        <span class="section">location</span> = /40x.html &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">error_page</span> <span class="number">500</span> <span class="number">502</span> <span class="number">503</span> <span class="number">504</span> /50x.html;</span><br><span class="line">        <span class="section">location</span> = /50x.html &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>为何可以通过在<code>conf.d</code>目录中新增conf配置文件来配置站点，是因为在<code>nginx.conf</code>配置文件中存在<code>include /etc/nginx/conf.d/*.conf</code>引用其他配置文件的配置。</p></blockquote><blockquote><p>上述配置中，省略了获取ssl证书&#x2F;域名申请备案等步骤。</p></blockquote><h1 id="twikoo客户端配置"><a href="#twikoo客户端配置" class="headerlink" title="twikoo客户端配置"></a>twikoo客户端配置</h1><h2 id="配置icarus配置文件"><a href="#配置icarus配置文件" class="headerlink" title="配置icarus配置文件"></a>配置icarus配置文件</h2><p>配置<code>_config.icarus.yml</code>配置文件，修改信息如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">comment:</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">twikoo</span></span><br><span class="line">    <span class="comment"># 配置环境地址，私有化部署，配置服务器地址</span></span><br><span class="line">    <span class="attr">env_id:</span> <span class="string">https://blog.plcent.com:8099/</span></span><br></pre></td></tr></table></figure><p>自此配置完成，可以重启本地服务查看效果。</p><h2 id="首次使用设置管理员密码"><a href="#首次使用设置管理员密码" class="headerlink" title="首次使用设置管理员密码"></a>首次使用设置管理员密码</h2><p>首次使用<code>twikoo</code>时，请设置一个服务管理密码。在每个文章下面看到评论区，在评论区的右边发现有一个「<strong>蓝色小齿轮</strong>」，这就是管理面板。</p><p>第一次 点击小齿轮后会让你输入登录密码，请记住它，如果忘记了密码，请参考官网文档解决。</p><h1 id="补充信息"><a href="#补充信息" class="headerlink" title="补充信息"></a>补充信息</h1><h2 id="停止docker-compose服务"><a href="#停止docker-compose服务" class="headerlink" title="停止docker compose服务"></a>停止docker compose服务</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 进入到代码目录下</span></span><br><span class="line"><span class="built_in">cd</span> twikoo</span><br><span class="line"><span class="comment"># 停止服务</span></span><br><span class="line">docker compose down</span><br></pre></td></tr></table></figure><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><ul><li><a href="https://twikoo.js.org/">Twikoo | 一个简洁、安全、免费的静态网站评论系统</a></li><li><a href="https://www.peterjxl.com/Blog/Comment/#twikoo-%E7%9A%84%E5%AE%89%E8%A3%85">从零开始搭建博客系列-评论区 </a></li><li><a href="https://onedayxyy.cn/zhuanti/w3l4v">Twikoo使用 | One</a></li><li><a href="https://help.aliyun.com/zh/ssl-certificate/user-guide/install-ssl-certificates-on-nginx-servers-or-tengine-servers?spm=a2c4g.11186623.0.0.b52045ecnOMH4K">在 Linux（RHEL&#x2F;CentOS&#x2F;Ubuntu&#x2F;Debian）下的 Nginx或Tengine服务器中安装&#x2F;配置&#x2F;部署 SSL证书_数字证书管理服务（原SSL证书）(SSL Certificate)-阿里云帮助中心</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;本文详细介绍了在阿里云云主机上，从&lt;code&gt;docker&lt;/code&gt;&amp;#x2F;&lt;code&gt;git&lt;/code&gt;环境安装开始，编译&lt;code&gt;twikoo&lt;/code&gt; &lt;code&gt;docker&lt;/code&gt;镜像，通过&lt;code&gt;docker compose&lt;/code&gt;启动&lt;code&gt;twikoo&lt;/code&gt;服务，并通过&lt;code&gt;nginx&lt;/code&gt;对外暴露服务的完整过程。&lt;/p&gt;</summary>
    
    
    
    <category term="hexo" scheme="https://blog.plcent.com/categories/hexo/"/>
    
    <category term="icarus" scheme="https://blog.plcent.com/categories/hexo/icarus/"/>
    
    
    <category term="icarus" scheme="https://blog.plcent.com/tags/icarus/"/>
    
    <category term="twikoo" scheme="https://blog.plcent.com/tags/twikoo/"/>
    
  </entry>
  
  <entry>
    <title>stylus选择器 - selector()用法和使用场景</title>
    <link href="https://blog.plcent.com/stylus-docs-selector/"/>
    <id>https://blog.plcent.com/stylus-docs-selector/</id>
    <published>2025-10-05T11:33:53.000Z</published>
    <updated>2025-10-09T13:42:51.523Z</updated>
    
    <content type="html"><![CDATA[<p><code>stylus</code>选择器中的高阶用法用法<code>selector() bif</code>。常规用法，和<code>&amp;</code>选择器的对比，函数用法和mixins用法。</p><span id="more"></span><h1 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h1><p><code>stylus</code>内置的 <code>selector()</code> 函数，用于返回当前样式块的选择器字符串。所谓的<code>当前</code>指代的<code>是运行时</code>环境，方便进行动态样式生成或复用当前选择器。这为使用场景带来了很多有趣的可能性。</p><p> <code>selector()</code> 函数返回的是字符串，因此需要使用 <code>{}</code> 包裹才能作为选择器生效（Stylus 的插值语法）。</p><h2 id="无参调用"><a href="#无参调用" class="headerlink" title="无参调用"></a>无参调用</h2><p>用于获取当前样式块的选择器字符串，下面的例子中，<code>当前样式块</code>是<code>.foo .bar</code></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.foo</span></span><br><span class="line">    <span class="selector-class">.bar</span></span><br><span class="line">        &#123;<span class="built_in">selector</span>()&#125; <span class="comment">// selector() 返回 .foo .bar</span></span><br><span class="line">            <span class="attribute">color</span>: <span class="number">#FFF</span></span><br><span class="line">            <span class="attribute">content</span>: <span class="built_in">selector</span>() // 此处选择器所在的样式块包含上面一个<span class="built_in">selector</span>()生成的样式</span><br></pre></td></tr></table></figure><p>编译后CSS</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.foo</span> <span class="selector-class">.bar</span> <span class="selector-class">.foo</span> <span class="selector-class">.bar</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">&#x27;.foo .bar .foo .bar&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="有参调用（一个参数）"><a href="#有参调用（一个参数）" class="headerlink" title="有参调用（一个参数）"></a>有参调用（一个参数）</h2><p>这个 bif 还可以接受<strong>一个</strong>可选的字符串参数，在这种情况下它将返回编译后的选择器。请注意，如果当前作用域没有任何 <code>&amp;</code> 符号，则不会在其前面添加选择器。</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.foo</span></span><br><span class="line">    <span class="selector-class">.bar</span></span><br><span class="line">        &#123;<span class="built_in">selector</span>(<span class="string">&#x27;.para1&#x27;</span>)&#125; <span class="comment">// 等同于直接写 .para1</span></span><br><span class="line">            <span class="attribute">color</span>: <span class="number">#FFF</span></span><br><span class="line"><span class="selector-class">.foo</span></span><br><span class="line">    <span class="selector-class">.bar</span></span><br><span class="line">        &#123;<span class="built_in">selector</span>(<span class="string">&#x27;&amp;.para1&#x27;</span>)&#125; <span class="comment">// 在有&amp;的情况下，&amp;会被渲染成当前选择器环境 &amp;.para1 =&gt; .foo .bar.para1</span></span><br><span class="line">            <span class="attribute">color</span>: <span class="number">#FFF</span></span><br></pre></td></tr></table></figure><p>编译后CSS</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.foo</span> <span class="selector-class">.bar</span> <span class="selector-class">.para1</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.foo</span> <span class="selector-class">.bar</span> <span class="selector-class">.foo</span> <span class="selector-class">.bar</span><span class="selector-class">.para1</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="有参调用（多个参数）（不建议使用）"><a href="#有参调用（多个参数）（不建议使用）" class="headerlink" title="有参调用（多个参数）（不建议使用）"></a>有参调用（多个参数）（不建议使用）</h2><p>在传入多个参数时，将在当前样式块的选择器下，创建嵌套选择器结构</p><p><strong>当前上下文选择器分别与每个参数组合后，再将所有组合结果串联（无空格拼接）</strong>。</p><p>规则：<code>(当前选择器 + 空格 + sel1) + (当前选择器 + 空格 + sel2) + ...</code>（注意：是组合结果的直接拼接，而非后代 &#x2F; 兄弟关系）</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.foo</span></span><br><span class="line">    <span class="selector-class">.bar</span></span><br><span class="line">        <span class="comment">// .foo .bar .para1 + .foo .bar .para2</span></span><br><span class="line">        <span class="comment">// =&gt; .foo .bar .para1 .para2</span></span><br><span class="line">        &#123;<span class="built_in">selector</span>(<span class="string">&#x27;.para1&#x27;</span>, <span class="string">&#x27;.para2&#x27;</span>)&#125;</span><br><span class="line">            <span class="attribute">color</span>: <span class="number">#FFF</span></span><br><span class="line"><span class="selector-class">.foo</span></span><br><span class="line">    <span class="selector-class">.bar</span></span><br><span class="line">        <span class="comment">// .foo .bar.para1 + .foo .bar .para2</span></span><br><span class="line">        <span class="comment">// .foo .bar.para1.foo .bar .para2</span></span><br><span class="line">        <span class="comment">// 剔除错误css .foo .bar.para1&lt;.foo .bar&gt; .para2</span></span><br><span class="line">        <span class="comment">// =&gt; .foo .bar.para1 .para2</span></span><br><span class="line">        &#123;<span class="built_in">selector</span>(<span class="string">&#x27;&amp;.para1&#x27;</span>, <span class="string">&#x27;&amp; .para2&#x27;</span>)&#125;</span><br><span class="line">            <span class="attribute">color</span>: <span class="number">#FFF</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.foo</span></span><br><span class="line">    <span class="selector-class">.bar</span></span><br><span class="line">        <span class="comment">// .foo .bar .para1 + .foo .bar.para2</span></span><br><span class="line">        <span class="comment">// .foo .bar .para1.foo .bar.para2</span></span><br><span class="line">        <span class="comment">// 剔除错误css .foo .bar .para1&lt;.foo .bar&gt;.para2</span></span><br><span class="line">        <span class="comment">// =&gt; .foo .bar .para1.para2</span></span><br><span class="line">        &#123;<span class="built_in">selector</span>(<span class="string">&#x27;&amp; .para1&#x27;</span>, <span class="string">&#x27;&amp;.para2&#x27;</span>)&#125;</span><br><span class="line">            <span class="attribute">color</span>: <span class="number">#FFF</span></span><br></pre></td></tr></table></figure><p>编译后CSS</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.foo</span> <span class="selector-class">.bar</span> <span class="selector-class">.foo</span> <span class="selector-class">.bar</span> <span class="selector-class">.para1</span> <span class="selector-class">.para2</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.foo</span> <span class="selector-class">.bar</span> <span class="selector-class">.foo</span> <span class="selector-class">.bar</span><span class="selector-class">.para1</span> <span class="selector-class">.para2</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.foo</span> <span class="selector-class">.bar</span> <span class="selector-class">.foo</span> <span class="selector-class">.bar</span> <span class="selector-class">.para1</span><span class="selector-class">.para2</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在stylus中，stylus会尝试修正无效语法，Stylus 不会主动 “优化” 合法选择器，只有当 selector() 多参数拼接后出现 <strong>不符合 CSS 语法规范的片段</strong> 时，才会触发自动修正。Stylus 修正的底层思路是 <strong>“尽量保留开发者想表达的样式语义，同时剔除导致语法错误的冗余片段”</strong>。</p><p><strong>当</strong> <strong>selector()</strong> <strong>多参数机制产生语法错误时，通过 “保留目标类名、剔除重复上下文” 的逻辑，尽量让样式能正常生效，避免编译失败</strong>。但这种修正并非 “设计特性”，而是对 “不推荐用法（滥用 selector() 多参数）” 的容错。</p><blockquote><p>在上面的例子中，你可能发现了， <code>selector()</code> 在处理多个参数的过程中，出现了复杂的处理逻辑，最终编译后的css类明难以理解。</p><p>你不用去搞清楚其中的代码逻辑。</p><p>只是想说明，尽量不要使用<code>selector()</code> 多参数，优先用原生嵌套语法，让代码更易维护。</p></blockquote><h1 id="和-语法的对比"><a href="#和-语法的对比" class="headerlink" title="和&amp;语法的对比"></a>和&amp;语法的对比</h1><p>核心差异：<code>&amp;</code> 是 “拼接符号”，<code>selector()</code> 是 “选择器字符串”</p><ul><li><strong>&amp; 的本质</strong>：是一个 “选择器拼接标记”，用于将父选择器与子规则直接拼接，他只是一个静态替换。</li><li><strong>selector() 的本质</strong>：是一个 “函数”，返回当前上下文的完整选择器字符串，它可以实现&amp;的所有功能外，还可以基于上下文，动态生成“选择器字符串”，借助<code>{}</code>语法，生成选择器。</li></ul><h1 id="selector-使用场景"><a href="#selector-使用场景" class="headerlink" title="selector()使用场景"></a><code>selector()</code>使用场景</h1><p>那，何时用 <code>selector()</code> 而不是 <code>&amp;</code>？</p><h2 id="需要对选择器进行-“字符串级操作”-时"><a href="#需要对选择器进行-“字符串级操作”-时" class="headerlink" title="需要对选择器进行 “字符串级操作” 时"></a>需要对选择器进行 “字符串级操作” 时</h2><p><code>&amp;</code> 只能用于直接拼接选择器（如 <code>&amp;:hover</code> 变成 <code>.parent:hover</code>），但无法对选择器进行拆分、拼接变量或复杂逻辑处理。而 <code>selector()</code> 返回字符串，支持所有字符串操作。</p><p>基于当前类<code>.component</code>生成一个新类名<code>.theme-component</code></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">prefix = <span class="string">&quot;.theme-&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.component</span></span><br><span class="line">  &#123;prefix + <span class="built_in">replace</span>(<span class="string">&quot;\.&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="built_in">selector</span>())&#125;</span><br><span class="line">    <span class="attribute">color</span>: red</span><br></pre></td></tr></table></figure><p>编译后CSS</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.component</span> <span class="selector-class">.theme-component</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#f00</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="需要在函数中-“动态生成选择器”-时"><a href="#需要在函数中-“动态生成选择器”-时" class="headerlink" title="需要在函数中 “动态生成选择器” 时"></a>需要在函数中 “动态生成选择器” 时</h2><p>定义函数，在函数中根据调用环境，“动态生成选择器”</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义函数：为相同元素的兄弟节点添加间距</span></span><br><span class="line"><span class="function"><span class="title">sibling-gap</span><span class="params">(gap)</span></span></span><br><span class="line">  &#123;<span class="built_in">selector</span>() + <span class="string">&quot; + &quot;</span> + <span class="built_in">selector</span>()&#125;  <span class="comment">// 生成 &quot;A + A&quot; 选择器</span></span><br><span class="line">    <span class="attribute">margin-left</span>: gap</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用函数</span></span><br><span class="line"><span class="selector-class">.btn</span></span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100px</span></span><br><span class="line">  <span class="built_in">sibling-gap</span>(<span class="number">10px</span>)  <span class="comment">// 自动适配 .btn 选择器</span></span><br></pre></td></tr></table></figure><p>编译后CSS</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.btn</span> &#123;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.btn</span> <span class="selector-class">.btn</span> + <span class="selector-class">.btn</span> &#123;</span><br><span class="line">  <span class="attribute">margin-left</span>: <span class="number">10px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="mixins混入用法"><a href="#mixins混入用法" class="headerlink" title="mixins混入用法"></a>mixins混入用法</h2><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">prefix = <span class="string">&quot;theme-&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">prefix-class</span><span class="params">()</span></span></span><br><span class="line">    namespace = <span class="built_in">replace</span>(<span class="string">&quot;\.&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="built_in">selector</span>())</span><br><span class="line">    <span class="attr">--prefix-class</span>: prefix + namespace</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.component</span></span><br><span class="line">  <span class="built_in">prefix-class</span>()</span><br></pre></td></tr></table></figure><p>编译后CSS</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.component</span> &#123;</span><br><span class="line">  <span class="attr">--prefix-class</span>: <span class="string">&#x27;theme-component&#x27;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://stylus.nodejs.cn/docs/selectors.html#selector-bif">选择器 | Stylus 中文网</a></p><p><a href="https://stylus.github.io/nib/">nib - Stylus 的 CSS3 扩展</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;code&gt;stylus&lt;/code&gt;选择器中的高阶用法用法&lt;code&gt;selector() bif&lt;/code&gt;。常规用法，和&lt;code&gt;&amp;amp;&lt;/code&gt;选择器的对比，函数用法和mixins用法。&lt;/p&gt;</summary>
    
    
    
    <category term="stylus" scheme="https://blog.plcent.com/categories/stylus/"/>
    
    
    <category term="stylus" scheme="https://blog.plcent.com/tags/stylus/"/>
    
  </entry>
  
  <entry>
    <title>hexo-theme-icarus源码解析：stylus</title>
    <link href="https://blog.plcent.com/hexo-icarus-dependencies-stylus/"/>
    <id>https://blog.plcent.com/hexo-icarus-dependencies-stylus/</id>
    <published>2025-10-05T11:28:33.000Z</published>
    <updated>2025-10-05T13:43:55.363Z</updated>
    
    <content type="html"><![CDATA[<p>hexo默认依赖中，依赖<a href="https://www.npmjs.com/package/hexo-renderer-stylus"><code>hexo-renderer-stylus</code></a>，在icarus主题中，依赖<a href="https://www.npmjs.com/package/bulma-stylus"><code>bulma-stylus</code></a>。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;hexo默认依赖中，依赖&lt;a href=&quot;https://www.npmjs.com/package/hexo-renderer-stylus&quot;&gt;&lt;code&gt;hexo-renderer-stylus&lt;/code&gt;&lt;/a&gt;，在icarus主题中，依赖&lt;a href=&quot;http</summary>
      
    
    
    
    <category term="hexo" scheme="https://blog.plcent.com/categories/hexo/"/>
    
    <category term="icarus" scheme="https://blog.plcent.com/categories/hexo/icarus/"/>
    
    <category term="stylus" scheme="https://blog.plcent.com/categories/stylus/"/>
    
    
    <category term="icarus" scheme="https://blog.plcent.com/tags/icarus/"/>
    
    <category term="stylus" scheme="https://blog.plcent.com/tags/stylus/"/>
    
  </entry>
  
  <entry>
    <title>hexo-theme-icarus配置指南</title>
    <link href="https://blog.plcent.com/icarus-init-and-config/"/>
    <id>https://blog.plcent.com/icarus-init-and-config/</id>
    <published>2025-10-03T13:11:47.000Z</published>
    <updated>2025-10-21T10:08:57.228Z</updated>
    
    <content type="html"><![CDATA[<p>记录本站使用<code>icarus</code>主题的配置，以及自定义实现功能的实现方式，目前在原有主题基础上做了下属功能：</p><ul><li>代码高亮增加语言展示功能</li><li>修正<code>typora</code>编辑文章图片展示异常问题</li></ul><span id="more"></span><h1 id="引入主题icarus"><a href="#引入主题icarus" class="headerlink" title="引入主题icarus"></a>引入主题icarus</h1><p>引入<code>hexo-theme-icarus</code>到<code>theme/icarus</code>目录</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/ppoffice/hexo-theme-icarus.git themes/icarus -b master --depth 1</span><br></pre></td></tr></table></figure><blockquote><p>参考：<a href="https://ppoffice.github.io/hexo-theme-icarus/uncategorized/icarus%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B/#install-source">Icarus快速上手</a></p></blockquote><h2 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h2><p>将<code>theme/icarus/packages.json</code>的<code>devDependencies</code>和<code>dependencies</code>依赖，复制到项目根目录下的<code>packages.json</code>中，重新触发依赖安装</p><blockquote><p>请勿删除<code>theme/icarus/packages.json</code>文件，源代码中有使用该文件</p></blockquote><h1 id="代码高亮增加语言展示功能"><a href="#代码高亮增加语言展示功能" class="headerlink" title="代码高亮增加语言展示功能"></a>代码高亮增加语言展示功能</h1><h2 id="增加配置项"><a href="#增加配置项" class="headerlink" title="增加配置项"></a>增加配置项</h2><p><code>_config.icarus.yml</code>文件增加自定义配置<code>article.highlight.lang</code>，支持配置<code>true</code>&#x2F;<code>false</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 文章配置</span></span><br><span class="line"><span class="attr">article:</span></span><br><span class="line">    <span class="attr">highlight:</span></span><br><span class="line">        <span class="comment"># 自定义配置：是否展示代码块语言信息 true/false</span></span><br><span class="line">        <span class="attr">lang:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>具体实现代码<a href="https://gitee.com/caoruiy/blog.plcent.com/blob/master/_config.icarus.yml#L152">参见</a></p><h2 id="扩充全局变量定义"><a href="#扩充全局变量定义" class="headerlink" title="扩充全局变量定义"></a>扩充全局变量定义</h2><p>在icarus中，通过定义<code>IcarusThemeSettings</code>JS代码实现，通过变量<code>embeddedConfig</code>注入到全局<code>&lt;script&gt;</code>标签中，来实现全局变量<code>IcarusThemeSettings</code>的定义。你可以在控制台输入<code>IcarusThemeSettings</code>来查看变量具体的值。<br>修改后的代码如下，具体<a href="https://gitee.com/caoruiy/blog.plcent.com/blob/master/themes/icarus/layout/common/scripts.jsx#L33">参见</a></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 代码块语言信息</span></span><br><span class="line"><span class="keyword">let</span> lang = <span class="literal">true</span>;</span><br><span class="line"><span class="keyword">if</span> (article &amp;&amp; article.<span class="property">highlight</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> article.<span class="property">highlight</span>.<span class="property">clipboard</span> !== <span class="string">&#x27;undefined&#x27;</span>) &#123;</span><br><span class="line">        clipboard = !!article.<span class="property">highlight</span>.<span class="property">clipboard</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> article.<span class="property">highlight</span>.<span class="property">lang</span> !== <span class="string">&#x27;undefined&#x27;</span>) &#123;</span><br><span class="line">        lang = !!article.<span class="property">highlight</span>.<span class="property">lang</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> article.<span class="property">highlight</span>.<span class="property">fold</span> === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line">        fold = article.<span class="property">highlight</span>.<span class="property">fold</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> embeddedConfig = <span class="string">`var IcarusThemeSettings = &#123;</span></span><br><span class="line"><span class="string">    article: &#123;</span></span><br><span class="line"><span class="string">        highlight: &#123;</span></span><br><span class="line"><span class="string">            clipboard: <span class="subst">$&#123;clipboard&#125;</span>,</span></span><br><span class="line"><span class="string">            fold: &#x27;<span class="subst">$&#123;fold&#125;</span>&#x27;,</span></span><br><span class="line"><span class="string">            lang: <span class="subst">$&#123;lang&#125;</span></span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">&#125;;`</span>;</span><br></pre></td></tr></table></figure><p>在<code>themes\icarus\source\js\main.js</code>中通过注入全局的变量的方式，将<code>IcarusThemeSettings</code>注入到该文件内。具体实现<a href="https://gitee.com/caoruiy/blog.plcent.com/blob/master/themes/icarus/source/js/main.js#L158">参见</a></p><h2 id="实现逻辑功能"><a href="#实现逻辑功能" class="headerlink" title="实现逻辑功能"></a>实现逻辑功能</h2><p>在<code>themes\icarus\source\js\main.js</code>文件中，增加下面的代码，识别语言信息并添加展示按钮。具体实现代码<a href="https://gitee.com/caoruiy/blog.plcent.com/blob/master/themes/icarus/source/js/main.js#L92">参见</a></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 读取配置信息</span></span><br><span class="line"><span class="keyword">const</span> lang = config.<span class="property">article</span>.<span class="property">highlight</span>.<span class="property">lang</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 展示语言信息</span></span><br><span class="line"><span class="keyword">if</span> (lang) &#123;</span><br><span class="line">    $(<span class="string">&#x27;figure.highlight&#x27;</span>).<span class="title function_">each</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">        <span class="comment">// 获取代码块语言信息</span></span><br><span class="line">        <span class="keyword">const</span> classList = $(<span class="variable language_">this</span>).<span class="title function_">attr</span>(<span class="string">&#x27;class&#x27;</span>).<span class="title function_">split</span>(<span class="regexp">/\s+/</span>);</span><br><span class="line">        <span class="comment">// class名称列表格式： highlight &lt;语言&gt; &lt;其他添加的class&gt;</span></span><br><span class="line">        <span class="keyword">const</span> langName = classList &amp;&amp; classList[<span class="number">1</span>] || <span class="string">&quot;&quot;</span></span><br><span class="line">        <span class="keyword">if</span> (langName) &#123;</span><br><span class="line">            <span class="keyword">const</span> id = <span class="string">&#x27;code-&#x27;</span> + <span class="title class_">Date</span>.<span class="title function_">now</span>() + (<span class="title class_">Math</span>.<span class="title function_">random</span>() * <span class="number">1000</span> | <span class="number">0</span>);</span><br><span class="line">            <span class="keyword">const</span> lang = <span class="string">&#x27;&lt;a href=&quot;javascript:;&quot; class=&quot;copy&quot; title=&quot;语言&quot; data-clipboard-target=&quot;#&#x27;</span> + id + <span class="string">&#x27; .code&quot;&gt;&#x27;</span> + langName + <span class="string">&#x27;&lt;/i&gt;&lt;/a&gt;&#x27;</span>;</span><br><span class="line">            $(<span class="variable language_">this</span>).<span class="title function_">attr</span>(<span class="string">&#x27;id&#x27;</span>, id);</span><br><span class="line">            $(<span class="variable language_">this</span>).<span class="title function_">find</span>(<span class="string">&#x27;figcaption div.level-right&#x27;</span>).<span class="title function_">append</span>(lang);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="修改CSS样式"><a href="#修改CSS样式" class="headerlink" title="修改CSS样式"></a>修改CSS样式</h2><p>修改<code>themes\icarus\include\style\codeblock.styl</code>，修改鼠标指示器为默认样式，具有代码<a href="https://gitee.com/caoruiy/blog.plcent.com/blob/master/themes/icarus/include/style/codeblock.styl#L17">参见</a></p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.lang</span></span><br><span class="line">    <span class="attribute">cursor</span>: default</span><br></pre></td></tr></table></figure><h1 id="修正typora编辑文章图片展示异常问题"><a href="#修正typora编辑文章图片展示异常问题" class="headerlink" title="修正typora编辑文章图片展示异常问题"></a>修正<code>typora</code>编辑文章图片展示异常问题</h1><p><code>hexo</code>默认使用<code>hexo-renderer-marked</code>处理md中的图片，按照官方文档说明，图片需要<code>[图片名称](filename.png)</code>的格式，不能包含路径。</p><blockquote><p><a href="https://hexo.io/zh-cn/docs/asset-folders#%E4%BD%BF%E7%94%A8-Markdown-%E5%B5%8C%E5%85%A5%E5%9B%BE%E7%89%87">资源文件夹 | Hexo</a></p><p>原文：</p><p>启用<code>post_asset_folder: true</code>，资源图片将会被自动解析为其对应文章的路径。 例如： <code>image.jpg</code> 位置为 <code>/2020/01/02/foo/image.jpg</code> ，这表示它是 <code>/2020/01/02/foo/</code> 文章的一张资源图片， <code>![](image.jpg)</code> 将会被解析为 <code>&lt;img src=&quot;/2020/01/02/foo/image.jpg&quot;&gt;</code> 。</p></blockquote><p>在使用<code>typora</code>编写博客时，设置将图片复制到同名资源目录。</p><p><img src="/icarus-init-and-config/1759823861216.png" alt="1759823861216" loading="lazy"></p><p>这样，<code>typora</code>在你粘贴图片时，生成的图片路径时一个包含资源目录的相对路径。</p><p>例如：<code>![1759823861216](icarus-init-and-config-page/1759823861216.png)</code></p><p>为了保证<code>hexo</code>可以正常渲染，需要将路径修改成<code>![1759823861216](1759823861216.png)</code>，这样会导致在<code>typora</code>中展示异常。</p><p>有没有可以兼顾的方法？</p><h2 id="自定义图片处理过滤器"><a href="#自定义图片处理过滤器" class="headerlink" title="自定义图片处理过滤器"></a>自定义图片处理过滤器</h2><ol><li><p>在项目更目录，新增<code>scripts</code>目录</p></li><li><p>添加自定义处理过滤器<code>fix-image-path.js</code></p><p>该脚本的作用就是把应用的图片的md格式，匹配出包含引用资源的路径，人为去掉相关路径。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> log = <span class="built_in">require</span>(<span class="string">&#x27;hexo-log&#x27;</span>).<span class="title function_">default</span>();</span><br><span class="line">hexo.<span class="property">extend</span>.<span class="property">filter</span>.<span class="title function_">register</span>(<span class="string">&#x27;before_post_render&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">const</span> &#123; config &#125; = <span class="variable language_">this</span>;</span><br><span class="line">    <span class="keyword">if</span>(!config.<span class="property">post_asset_folder</span>)&#123;</span><br><span class="line">        log.<span class="title function_">debug</span>(<span class="string">&quot;[fix-image-path] 未启用post_asset_folder, markdown 图片目录处理程序暂不执行&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> data</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 匹配图片语法 ![alt](文件夹名/文件名)</span></span><br><span class="line">    <span class="keyword">const</span> regex = <span class="regexp">/!\[(.*?)\]\(([^)]+)\/([^)]+)\)/g</span>;</span><br><span class="line">    <span class="comment">// 替换为 ![alt](文件名)</span></span><br><span class="line">    data.<span class="property">content</span> = data.<span class="property">content</span>.<span class="title function_">replace</span>(regex, <span class="keyword">function</span>(<span class="params">matched, mName, mDir, mFileName, offset, string, groups</span>)&#123;</span><br><span class="line">        <span class="comment">// data.slug中保存的时当前文章文件的名称，也是附件保存的文件夹名称</span></span><br><span class="line">        <span class="comment">// 通过该判断限制匹配图片范围，文章中依然可以引入其他目录资源文件</span></span><br><span class="line">        <span class="keyword">if</span>(mDir == data.<span class="property">slug</span>)&#123;</span><br><span class="line">            log.<span class="title function_">info</span>(<span class="string">&#x27;[fix-image-path] 识别到带目录的图片地址&#x27;</span>, matched, <span class="string">&#x27;-&gt;&#x27;</span>, <span class="string">`![<span class="subst">$&#123;mName&#125;</span>](<span class="subst">$&#123;mFileName&#125;</span>)`</span>)</span><br><span class="line">            <span class="keyword">return</span> <span class="string">`![<span class="subst">$&#123;mName&#125;</span>](<span class="subst">$&#123;mFileName&#125;</span>)`</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> matched</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> data;</span><br><span class="line">  &#125;);</span><br></pre></td></tr></table></figure></li><li><p>效果如下</p><p><img src="/icarus-init-and-config/1759827056605.png" alt="1759827056605" loading="lazy"></p></li></ol><blockquote><p>网上有很多其他的教程，例如引入<code>hexo-asset-img</code>插件，下面这些，都可以参照。</p><p><a href="https://moeci.com/posts/hexo-typora/">Hexo + Typora + 开发Hexo插件 解决图片路径不一致 | yiyun’s Blog</a></p><p><a href="https://www.cnblogs.com/guide2it/p/11111715.html">Hexo+NexT（六）：手把手教你编写一个Hexo过滤器插件 - Guide2IT - 博客园</a></p></blockquote><h1 id="代办事项"><a href="#代办事项" class="headerlink" title="代办事项"></a>代办事项</h1><ul><li><input disabled="" type="checkbox"> 修改CDN，优化CDN响应慢的问题</li><li><input disabled="" type="checkbox"> 实现黑白主题切换</li><li><input disabled="" type="checkbox"> 实现国际化</li></ul><h1 id="资源站列表"><a href="#资源站列表" class="headerlink" title="资源站列表"></a>资源站列表</h1><ul><li><a href="https://fontawesome.com/icons/packs/brands">fontawesome字体</a></li><li><a href="https://www.cnblogs.com/yyhh/p/11058985.html">开发hexo主题教程</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;记录本站使用&lt;code&gt;icarus&lt;/code&gt;主题的配置，以及自定义实现功能的实现方式，目前在原有主题基础上做了下属功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;代码高亮增加语言展示功能&lt;/li&gt;
&lt;li&gt;修正&lt;code&gt;typora&lt;/code&gt;编辑文章图片展示异常问题&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="hexo" scheme="https://blog.plcent.com/categories/hexo/"/>
    
    <category term="icarus" scheme="https://blog.plcent.com/categories/hexo/icarus/"/>
    
    
    <category term="icarus" scheme="https://blog.plcent.com/tags/icarus/"/>
    
  </entry>
  
  <entry>
    <title>windows事件日志</title>
    <link href="https://blog.plcent.com/windows-event-log/"/>
    <id>https://blog.plcent.com/windows-event-log/</id>
    <published>2023-11-07T06:36:34.000Z</published>
    <updated>2025-10-22T03:32:36.459Z</updated>
    
    <content type="html"><![CDATA[<span id="more"></span><h1 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h1><ul><li><p><a href="https://learn.microsoft.com/zh-cn/windows/win32/wes/windows-event-log?redirectedfrom=MSDN">官方-Windows 事件日志</a></p></li><li><p><a href="https://learn.microsoft.com/zh-cn/training/modules/manage-monitor-event-logs/2-describe-windows-server-event-logs">https://learn.microsoft.com/zh-cn/training/modules/manage-monitor-event-logs/2-describe-windows-server-event-logs</a></p></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;span id=&quot;more&quot;&gt;&lt;/span&gt;

&lt;h1 id=&quot;参考文档&quot;&gt;&lt;a href=&quot;#参考文档&quot; class=&quot;headerlink&quot; title=&quot;参考文档&quot;&gt;&lt;/a&gt;参考文档&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://learn.micro</summary>
      
    
    
    
    <category term="windows" scheme="https://blog.plcent.com/categories/windows/"/>
    
    <category term="运维" scheme="https://blog.plcent.com/categories/windows/%E8%BF%90%E7%BB%B4/"/>
    
    <category term="事件日志" scheme="https://blog.plcent.com/categories/windows/%E8%BF%90%E7%BB%B4/%E4%BA%8B%E4%BB%B6%E6%97%A5%E5%BF%97/"/>
    
    
    <category term="windows" scheme="https://blog.plcent.com/tags/windows/"/>
    
    <category term="事件日志" scheme="https://blog.plcent.com/tags/%E4%BA%8B%E4%BB%B6%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>使用AJAX的方式发送FORM表单数据</title>
    <link href="https://blog.plcent.com/use-ajax-send-form-data/"/>
    <id>https://blog.plcent.com/use-ajax-send-form-data/</id>
    <published>2023-05-11T08:44:32.000Z</published>
    <updated>2025-10-22T03:36:23.959Z</updated>
    
    <content type="html"><![CDATA[<p>详细介绍前端使用 AJAX 发送 FORM 表单数据的问题与解决方案，核心围绕中文乱码及 <code>axios</code> 设置请求头失效展开。</p><p>介绍 form 标签<code>enctype</code>属性及<code>multipart/form-data</code>的 MIME 规范，给出自定义 AJAX 方法：手动组织 FormData、设置带编码和分隔符的请求头、拼接请求体并以二进制发送。</p><span id="more"></span><h2 id="问题缘由"><a href="#问题缘由" class="headerlink" title="问题缘由"></a>问题缘由</h2><p>在前端（vue，axios）提交表单数据到后端（springboot）时，表单字段如果存在中文，后端接收到数据会解析为乱码。这篇文章<a href="https://blog.csdn.net/weixin_42161320/article/details/129283121">https://blog.csdn.net/weixin_42161320&#x2F;article&#x2F;details&#x2F;129283121</a>给出的原因是，后端接收到数据时默认的编码格式为iso_8859_1。</p><p>问题的缘由为前后端编码的问题所致，后端设置编码可以修正该问题。通过postman调用接口测试，前端指定参数编码也可以解决该问题。解决方式为在表单提交过程中，手动指定请求头<code>Content-Type</code>值为<code>multipart/form-data; charset=UTF-8</code>即可。</p><h2 id="axios无法设置表单请求头"><a href="#axios无法设置表单请求头" class="headerlink" title="axios无法设置表单请求头"></a>axios无法设置表单请求头</h2><p>尝试修改axois请求，在发送请求前，手动设置请求头。代码如下，实际测试时发现，该方式并不会生效。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> formData = <span class="keyword">new</span> <span class="title class_">FormData</span>();</span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&#x27;id&#x27;</span>, <span class="string">&#x27;123&#x27;</span>) <span class="comment">// id</span></span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&#x27;file&#x27;</span>, file, <span class="string">&#x27;test.jpg&#x27;</span>) <span class="comment">// 文件</span></span><br><span class="line">axios.<span class="title function_">post</span>(url, formData, &#123;</span><br><span class="line">    <span class="attr">headers</span>: &#123;</span><br><span class="line">        <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&quot;multipart/form-data; charset=UTF-8&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>在axios<code>0.xx.xx</code>版本，<code>0.27.2</code>、<code>0.26.0</code>，设置的请求头会被忽略。在<code>1.xx.xx</code>版本，<code>Content-Type</code>会被修改为<code>false</code>。经过查询资料，在原生浏览器实现中，form表单提交时，由于form-data存在特殊的格式，当不设置<code>Content-Type</code>或者设置<code>Content-Type</code>为<code>false</code>时，浏览器默认会设置这个请求头。<strong>在浏览器默认设置的请求头中，并不会设置chartset编码。</strong></p><h2 id="form标签规范"><a href="#form标签规范" class="headerlink" title="form标签规范"></a>form标签规范</h2><p>HTML的<code>form</code>标签用来提交表单数据，文件上传通常以表单的形式提交。</p><p>在<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/form#%E5%85%B3%E4%BA%8E%E6%8F%90%E4%BA%A4%E8%A1%A8%E5%8D%95%E7%9A%84%E5%B1%9E%E6%80%A7">form</a>属性中，<code>enctype</code> 属性用来设置表单的数据类型，当 <code>method</code> 属性值为 <code>post</code> 时，将表单的内容提交给服务器的 。可能的取值有： </p><ul><li><code>application/x-www-form-urlencoded</code>：未指定属性时的默认值。</li><li><code>multipart/form-data</code>：当表单包含 <code>type=file</code> 的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a> 元素时使用此值。</li><li><code>text/plain</code>：出现于 HTML5，用于调试。这个值可被 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/button"><code>&lt;button&gt;</code></a>、<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/submit"><code>&lt;input type=&quot;submit&quot;&gt;</code></a> 或 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/image"><code>&lt;input type=&quot;image&quot;&gt;</code></a> 元素上的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/button#formenctype"><code>formenctype</code></a> 属性覆盖。</li></ul><p>当请求方式不为<code>post</code>时，该属性<code>enctype</code>无效。</p><h2 id="MIME规范：multipart-form-data"><a href="#MIME规范：multipart-form-data" class="headerlink" title="MIME规范：multipart&#x2F;form-data"></a>MIME规范：multipart&#x2F;form-data</h2><p>作为重要的MIME类型，MDN对<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types#multipartform-data">multipart&#x2F;form-data</a>编码规范进行了说明， 作为多部分文档格式，它由边界线（一个由<code>&#39;--&#39;</code>开始的字符串）划分出的不同部分组成。每一部分有自己的实体，以及自己的 HTTP 请求头。 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition"><code>Content-Disposition</code></a>和 <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Type"><code>Content-Type</code></a> 用于文件上传领域。</p><p>请求头以及提交的请求头格式，形如：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"># 请求头</span><br><span class="line">Content-Type: multipart/form-data; boundary=aBoundaryString</span><br><span class="line">(该请求头和其他表单提交请求头，如Content-Length，组成一个整体)</span><br><span class="line"></span><br><span class="line"># 请求体</span><br><span class="line">--aBoundaryString</span><br><span class="line">Content-Disposition: form-data; name=&quot;myFile&quot;; filename=&quot;img.jpg&quot;</span><br><span class="line">Content-Type: image/jpeg</span><br><span class="line"></span><br><span class="line">(data)</span><br><span class="line">--aBoundaryString</span><br><span class="line">Content-Disposition: form-data; name=&quot;myField&quot;</span><br><span class="line"></span><br><span class="line">(data)</span><br><span class="line">--aBoundaryString</span><br><span class="line">(其余更多的表单字段)</span><br><span class="line">--aBoundaryString--</span><br></pre></td></tr></table></figure><p>上述格式中给出了一个表单中，包含一个文件和一个其他字段的格式，每个字段之间通过<code>--aBoundaryString</code>进行分割，字段说明信息和字段值之间存在一个空行，文件字段比普通字段，多出<code>filename</code>和<code>Content-Type</code>信息。</p><p>如果有更多的字段，追加在下方即可。</p><p>所以，在上例ajax给出的表单请求，发送请求长这样：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"># 请求头</span><br><span class="line">Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7SWpm1kGf6oJFKnK</span><br><span class="line"></span><br><span class="line"># 请求体</span><br><span class="line">----WebKitFormBoundary7SWpm1kGf6oJFKnK</span><br><span class="line">Content-Disposition: form-data; name=&quot;id&quot;</span><br><span class="line"></span><br><span class="line">123</span><br><span class="line">----WebKitFormBoundary7SWpm1kGf6oJFKnK</span><br><span class="line">Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;test.jpg&quot;</span><br><span class="line">Content-Type: image/jpeg</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">----WebKitFormBoundary7SWpm1kGf6oJFKnK--</span><br></pre></td></tr></table></figure><h2 id="通过ajax的方式发送form-data"><a href="#通过ajax的方式发送form-data" class="headerlink" title="通过ajax的方式发送form-data"></a>通过ajax的方式发送form-data</h2><p>既然浏览器默认的方式无法指定请求头<code>Content-Type</code>值为<code>multipart/form-data; charset=UTF-8</code>，在了解浏览器表单提交数据的格式后，可以通过ajax的方式进行模拟。</p><p>在MDN文档<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#%E6%8F%90%E4%BA%A4%E8%A1%A8%E5%8D%95%E5%92%8C%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6">使用 XMLHttpRequest</a>中，给出了<code>一个小框架</code>，用于模拟表单提交的示例， 在使用 JavaScript 做表单提交的工作时，你需要完全模拟浏览器表单提交的行为。 </p><p>在简化这个示例过程中，将表单提交的过程简化为一下几个步骤：</p><ol><li>组织formData对象</li><li>手动设置请求头<code>Content-Type</code>值为<code>multipart/form-data; charset=UTF-8; boundary=分隔符</code></li><li>手动拼接请求体格式</li><li>将请求体作为二级制数据，使用xhr发送请求</li></ol><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ajax形式模拟表单数据提交</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">String</span>&#125; url 请求URL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">FormData</span>&#125; formData 表单数据</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">let</span> httpXhr = <span class="keyword">async</span> <span class="keyword">function</span> (<span class="params">url, formData</span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> xhr = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">  xhr.<span class="title function_">open</span>(<span class="string">&quot;POST&quot;</span>, url, <span class="literal">true</span>);</span><br><span class="line">  <span class="comment">// 固定分隔符</span></span><br><span class="line">  <span class="keyword">var</span> sBoundary = <span class="string">&quot;--WebKitFormBoundary7SWpm1kGf6oJFKnK&quot;</span>;</span><br><span class="line">  <span class="comment">// 设置请求头</span></span><br><span class="line">  xhr.<span class="title function_">setRequestHeader</span>(</span><br><span class="line">    <span class="string">&quot;Content-Type&quot;</span>,</span><br><span class="line">    <span class="string">`multipart/form-data; charset=utf-8; boundary=<span class="subst">$&#123;sBoundary&#125;</span>`</span></span><br><span class="line">  );</span><br><span class="line">  <span class="comment">// 表单数据的数组形式</span></span><br><span class="line">  <span class="keyword">var</span> reqData = [];</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 提交form-data格式</span></span><br><span class="line">  <span class="comment">// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types#multipartform-data</span></span><br><span class="line">  <span class="comment">// Content-Type: multipart/form-data; boundary=aBoundaryString</span></span><br><span class="line">  <span class="comment">// (other headers associated with the multipart document as a whole)</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// --aBoundaryString</span></span><br><span class="line">  <span class="comment">// Content-Disposition: form-data; name=&quot;myFile&quot;; filename=&quot;img.jpg&quot;</span></span><br><span class="line">  <span class="comment">// Content-Type: image/jpeg</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// (data)</span></span><br><span class="line">  <span class="comment">// --aBoundaryString</span></span><br><span class="line">  <span class="comment">// Content-Disposition: form-data; name=&quot;myField&quot;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// (data)</span></span><br><span class="line">  <span class="comment">// --aBoundaryString</span></span><br><span class="line">  <span class="comment">// (more subparts)</span></span><br><span class="line">  <span class="comment">// --aBoundaryString--</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">var</span> i <span class="keyword">of</span> formData) &#123;</span><br><span class="line">    <span class="comment">// 如果是文件</span></span><br><span class="line">    <span class="keyword">if</span> (i[<span class="number">1</span>] <span class="keyword">instanceof</span> <span class="title class_">File</span>) &#123;</span><br><span class="line">      <span class="comment">// 异步转同步</span></span><br><span class="line">      <span class="keyword">await</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">var</span> reader = <span class="keyword">new</span> <span class="title class_">FileReader</span>();</span><br><span class="line">        <span class="comment">// reader.readAsDataURL(i[1].slice());</span></span><br><span class="line">        reader.<span class="title function_">readAsBinaryString</span>(i[<span class="number">1</span>]);</span><br><span class="line">        reader.<span class="title function_">addEventListener</span>(<span class="string">&quot;loadend&quot;</span>, <span class="keyword">function</span> (<span class="params">e</span>) &#123;</span><br><span class="line">          reqData.<span class="title function_">push</span>(</span><br><span class="line">            <span class="string">`--<span class="subst">$&#123;sBoundary&#125;</span>\r\nContent-Disposition: form-data; name=&quot;<span class="subst">$&#123;i[<span class="number">0</span>]&#125;</span>&quot;; filename=&quot;<span class="subst">$&#123;i[<span class="number">1</span>].name&#125;</span>&quot;\r\nContent-Type: <span class="subst">$&#123;i[<span class="number">1</span>].type&#125;</span>\r\n\r\n<span class="subst">$&#123;reader.result&#125;</span>\r\n`</span></span><br><span class="line">          );</span><br><span class="line">          <span class="title function_">resolve</span>();</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125;);</span><br><span class="line">      <span class="comment">// 如果是普通字段</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      reqData.<span class="title function_">push</span>(</span><br><span class="line">        <span class="string">`--<span class="subst">$&#123;sBoundary&#125;</span>\r\nContent-Disposition: form-data; name=&quot;<span class="subst">$&#123;i[<span class="number">0</span>]&#125;</span>&quot;\r\n\r\n<span class="subst">$&#123;i[<span class="number">1</span>]&#125;</span>\r\n`</span></span><br><span class="line">      );</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 增加一个结尾</span></span><br><span class="line">  reqData.<span class="title function_">push</span>(<span class="string">`--<span class="subst">$&#123;sBoundary&#125;</span>--`</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 处理接口响应相关信息</span></span><br><span class="line">  xhr.<span class="property">onload</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;接口响应&quot;</span>, xhr.<span class="property">response</span>);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  xhr.<span class="title function_">send</span>(<span class="keyword">new</span> <span class="title class_">Blob</span>(reqData));</span><br><span class="line">  <span class="keyword">return</span> xhr</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>使用该示例也较为简单</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> formData = <span class="keyword">new</span> <span class="title class_">FormData</span>();</span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&#x27;id&#x27;</span>, <span class="string">&#x27;123&#x27;</span>) <span class="comment">// id</span></span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&#x27;file&#x27;</span>, file, <span class="string">&#x27;test.jpg&#x27;</span>) <span class="comment">// 文件</span></span><br><span class="line"><span class="title function_">httpXhr</span>(url, formData)</span><br></pre></td></tr></table></figure><h2 id="限制"><a href="#限制" class="headerlink" title="限制"></a>限制</h2><ul><li>该框架使用 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader"><code>FileReader</code></a> API 进行文件的上传。这是一个较新的 API 并且还未在 IE9 及以下版本的浏览器中实现。因此，使用 AJAX 上传仍是一项<strong>实验性的技术</strong>。如果你不需要上传 二进制文件，该框架在大多数浏览器中运行良好。 </li><li>发送二进制内容的最佳途径是通过 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer"><code>ArrayBuffers</code></a> 或 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Blob"><code>Blobs</code></a> 结合 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/send"><code>send()</code></a> 方法甚至 <code>FileReader</code> API 的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsArrayBuffer"><code>readAsArrayBuffer()</code></a> 方法。但是，自从该脚本的目的变成处理 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">可字符串化</a> 的原始数据以来，我们使用 <code>sendAsBinary()</code> 方法结合 <code>FileReader</code> API 的 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsBinaryString"><code>readAsBinaryString()</code></a> 方法。同样地，上述脚本仅当你处理小文件时行之有效。如果不打算上传二进制内容，就考虑使用 <code>FormData</code> API 来替代。 </li><li>非标准的 <code>sendAsBinary</code> 方法从 Gecko 31 开始将会废弃并且会很快被移除。标准方法 <code>send(Blob data)</code> 将会取而代之。</li></ul><h2 id="FormData-对象的使用"><a href="#FormData-对象的使用" class="headerlink" title="FormData 对象的使用"></a>FormData 对象的使用</h2><p> FormData 对象用以将数据编译成键值对，以便用<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code></a>来发送数据。其主要用于发送表单数据，但亦可用于发送带键数据 (keyed data)，而独立于表单使用。如果表单<code>enctype</code>属性设为 multipart&#x2F;form-data，则会使用表单的<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLFormElement/submit"><code>submit()</code></a>方法来发送数据，从而，发送数据具有同样形式。 </p><p> 你可以自己创建一个<code>FormData</code>对象，然后调用它的<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/append"><code>append()</code></a>方法来添加字段，像这样： </p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> formData = <span class="keyword">new</span> <span class="title class_">FormData</span>();</span><br><span class="line"></span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&quot;username&quot;</span>, <span class="string">&quot;Groucho&quot;</span>);</span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&quot;accountnum&quot;</span>, <span class="number">123456</span>); <span class="comment">//数字 123456 会被立即转换成字符串 &quot;123456&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// HTML 文件类型 input，由用户选择</span></span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&quot;userfile&quot;</span>, fileInputElement.<span class="property">files</span>[<span class="number">0</span>]);</span><br><span class="line"></span><br><span class="line"><span class="comment">// JavaScript file-like 对象</span></span><br><span class="line"><span class="keyword">var</span> content = <span class="string">&#x27;&lt;a id=&quot;a&quot;&gt;&lt;b id=&quot;b&quot;&gt;hey!&lt;/b&gt;&lt;/a&gt;&#x27;</span>; <span class="comment">// 新文件的正文</span></span><br><span class="line"><span class="keyword">var</span> blob = <span class="keyword">new</span> <span class="title class_">Blob</span>([content], &#123; <span class="attr">type</span>: <span class="string">&quot;text/xml&quot;</span>&#125;);</span><br><span class="line"></span><br><span class="line">formData.<span class="title function_">append</span>(<span class="string">&quot;webmasterfile&quot;</span>, blob);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> request = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">request.<span class="title function_">open</span>(<span class="string">&quot;POST&quot;</span>, <span class="string">&quot;http://foo.com/submitform.php&quot;</span>);</span><br><span class="line">request.<span class="title function_">send</span>(formData);</span><br></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li>FormData 对象的使用：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/Using_FormData_Objects">https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/Using_FormData_Objects</a></li><li>使用 XMLHttpRequest：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest</a></li><li>MIME 类型：<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types">https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP&#x2F;MIME_types</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;详细介绍前端使用 AJAX 发送 FORM 表单数据的问题与解决方案，核心围绕中文乱码及 &lt;code&gt;axios&lt;/code&gt; 设置请求头失效展开。&lt;/p&gt;
&lt;p&gt;介绍 form 标签&lt;code&gt;enctype&lt;/code&gt;属性及&lt;code&gt;multipart/form-data&lt;/code&gt;的 MIME 规范，给出自定义 AJAX 方法：手动组织 FormData、设置带编码和分隔符的请求头、拼接请求体并以二进制发送。&lt;/p&gt;</summary>
    
    
    
    <category term="javascript" scheme="https://blog.plcent.com/categories/javascript/"/>
    
    
    <category term="javascript" scheme="https://blog.plcent.com/tags/javascript/"/>
    
    <category term="ajax" scheme="https://blog.plcent.com/tags/ajax/"/>
    
    <category term="form" scheme="https://blog.plcent.com/tags/form/"/>
    
    <category term="form-data" scheme="https://blog.plcent.com/tags/form-data/"/>
    
    <category term="mime" scheme="https://blog.plcent.com/tags/mime/"/>
    
  </entry>
  
  <entry>
    <title>docker compose</title>
    <link href="https://blog.plcent.com/learn-the-abc-of-docker-about-compose/"/>
    <id>https://blog.plcent.com/learn-the-abc-of-docker-about-compose/</id>
    <published>2023-04-19T07:37:30.000Z</published>
    <updated>2025-10-22T03:28:09.331Z</updated>
    
    <content type="html"><![CDATA[<p>docker compose 使用详解</p><span id="more"></span><h1 id="docker-compose"><a href="#docker-compose" class="headerlink" title="docker compose"></a>docker compose</h1><p>Docker帮助我们解决服务的打包安装的问题，随着而来的问题就是服务过多的带来如下问题，</p><ol><li>多次使用Dockerfile Build Image或者DockerHub拉取Image;</li><li>需要创建多个Container，多次编写启动命令；</li><li>Container互相依赖的如何进行管理和编排；</li></ol><p>当我们服务数量增多的时候，上面三个问题就会更加的被放大，如果这三个问题不解决，其实从虚拟机到容器化除了机器减少一些浪费以外，好像没有更多的变化。Docker有没有什么好的方法，可以让我们通过一个配置就搞定容器编排和运行呢?这个时候Docker Compose就站出来了。</p><p>Docker Compose可以做到以下几点：</p><ol><li>提供工具用于定义和运行多个docker容器应用；</li><li>使用yaml文件来配置应用服务(docker-compse.yml)；</li><li>可以通过一个简单的命令docker-compse up可以按照依赖关系启动所有服务；</li><li>可以通过一个简单的命令docker-compose down停止所有服务；</li><li>当一个服务需要的时候，可以很简单地通过–scale进行扩容；</li></ol><p>Docker Compose有以下特征:</p><ol><li>更高的可移植性，Docker Compose仅需一个docker-compse up可以完成按照依赖关系启动所有服务，然后使用docker-compose down轻松将其拆解。帮助我们更轻松地部署复杂的应用程序；</li><li>单个主机上的多个隔离环境，Compose可以使用项目名称将环境彼此隔离，这带可以在一台计算机上运行同一环境的多个副本，它可以防止不同的项目和服务相互干扰；</li></ol><h1 id="什么是Docker-Compose"><a href="#什么是Docker-Compose" class="headerlink" title="什么是Docker Compose"></a>什么是Docker Compose</h1><ol><li>Docker Compose是一个工具，用于定义和运行多容器应用程序的工具；</li><li>Docker Compose通过yml文件定义多容器的docker应用；</li><li>Docker Compose通过一条命令根据yml文件的定义去创建或管理多容器；</li></ol><p>Docker Compose 是用来做Docker 的多容器控制，是一个用来把 Docker 自动化的东西。有了 Docker Compose 你可以把所有繁复的 Docker 操作全都一条命令，自动化的完成。 </p><p><img src="/learn-the-abc-of-docker-about-compose/image.png" alt="image.png" loading="lazy"></p><h1 id="Docker-Compose-Yml文件介绍"><a href="#Docker-Compose-Yml文件介绍" class="headerlink" title="Docker Compose Yml文件介绍"></a>Docker Compose Yml文件介绍</h1>]]></content>
    
    
    <summary type="html">&lt;p&gt;docker compose 使用详解&lt;/p&gt;</summary>
    
    
    
    <category term="docker" scheme="https://blog.plcent.com/categories/docker/"/>
    
    
    <category term="docker" scheme="https://blog.plcent.com/tags/docker/"/>
    
  </entry>
  
  <entry>
    <title>docker网络互连</title>
    <link href="https://blog.plcent.com/learn-the-abc-of-docker-about-network/"/>
    <id>https://blog.plcent.com/learn-the-abc-of-docker-about-network/</id>
    <published>2022-07-15T02:21:26.000Z</published>
    <updated>2025-10-22T04:29:15.370Z</updated>
    
    <content type="html"><![CDATA[<p>文章围绕 Docker 网络互连展开，详细介绍了默认网络、容器互联方法及自定义网络配置。<br>文章先讲解默认的 docker0 网络，指出 Linux 主机默认存在该虚拟桥接网卡，启动容器会生成 veth-pair 虚拟网卡对，主机可 ping 通容器 IP 并访问容器服务。接着介绍容器互联的 –link 方式，说明其通过配置 &#x2F;etc&#x2F;hosts 实现单向域名访问，但灵活性差。<br>随后重点推荐自定义网络，说明可通过docker network create创建桥接网络，指定子网和网关，启动容器时用 –net 指定该网络，即可实现容器间双向域名访问，保证网络隔离。还提到用docker network connect可让容器加入多个网络，实现不同网络间连通，最后提及集群部署需结合分片、高可用和负载均衡。</p><span id="more"></span><h2 id="docker0网络"><a href="#docker0网络" class="headerlink" title="docker0网络"></a>docker0网络</h2><p>在未启动任何docker镜像时，查看本机的网卡，存在docker0</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"># 查看本机网络情况</span><br><span class="line">[root@VM-16-13-centos ~]# ip addr</span><br><span class="line">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000</span><br><span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br><span class="line">    inet 127.0.0.1/8 scope host lo</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 ::1/128 scope host</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP group default qlen 1000</span><br><span class="line">    link/ether 55:54:00:a7:16:17 brd ff:ff:ff:ff:ff:ff</span><br><span class="line">    inet 11.0.16.13/22 brd 10.0.19.255 scope global noprefixroute eth0</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 fe80::5054:ff:fea7:1617/64 scope link noprefixroute</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">3: docker0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue state UP group default</span><br><span class="line">    link/ether 02:42:dc:a8:a2:72 brd ff:ff:ff:ff:ff:ff</span><br><span class="line">    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 fe80::42:dcff:fea8:a272/64 scope link</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>启动两容器</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"># 启动一个nginx容器</span><br><span class="line">docker run -it --name ng1 nginx</span><br><span class="line"># 查看容器的IP地址</span><br><span class="line">docker inspect -f &#x27;&#123;&#123;range .NetworkSettings.Networks&#125;&#125;&#123;&#123;.IPAddress&#125;&#125;&#123;&#123;end&#125;&#125;&#x27; ng1</span><br><span class="line">172.17.0.2</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 启动一个tomcat容器</span><br><span class="line">docker run -it --name tomcat01 tomcat</span><br><span class="line"># 查看容器的IP地址</span><br><span class="line">docker inspect -f &#x27;&#123;&#123;range .NetworkSettings.Networks&#125;&#125;&#123;&#123;.IPAddress&#125;&#125;&#123;&#123;end&#125;&#125;&#x27; ng1</span><br><span class="line">172.17.0.3</span><br></pre></td></tr></table></figure><p>启动两个容器后，本机网卡多个两个内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"># 查看本机网络情况</span><br><span class="line">ip addr</span><br><span class="line">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000</span><br><span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br><span class="line">    inet 127.0.0.1/8 scope host lo</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 ::1/128 scope host</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP group default qlen 1000</span><br><span class="line">    link/ether 55:54:00:a7:16:17 brd ff:ff:ff:ff:ff:ff</span><br><span class="line">    inet 11.0.16.13/22 brd 10.0.19.255 scope global noprefixroute eth0</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 fe80::5054:ff:fea7:1617/64 scope link noprefixroute</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">3: docker0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue state UP group default</span><br><span class="line">    link/ether 02:42:dc:a8:a2:72 brd ff:ff:ff:ff:ff:ff</span><br><span class="line">    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 fe80::42:dcff:fea8:a272/64 scope link</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">99: veth5bc12fa@if98: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue master docker0 state UP group default</span><br><span class="line">    link/ether 56:27:a0:23:a0:f7 brd ff:ff:ff:ff:ff:ff link-netnsid 0</span><br><span class="line">    inet6 fe80::5427:a0ff:fe23:a0f7/64 scope link</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">101: veth7ede5f7@if100: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue master docker0 state UP group default</span><br><span class="line">    link/ether 22:3b:ed:fc:47:29 brd ff:ff:ff:ff:ff:ff link-netnsid 1</span><br><span class="line">    inet6 fe80::203b:edff:fefc:4729/64 scope link</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>从主机检查网络情况，可以直接ping通docker内部的网络</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">[root@VM-16-13-centos ~]# ping 172.17.0.2</span><br><span class="line">PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.</span><br><span class="line">64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.037 ms</span><br><span class="line">--- 172.17.0.2 ping statistics ---</span><br><span class="line">2 packets transmitted, 2 received, 0% packet loss, time 1053ms</span><br><span class="line">rtt min/avg/max/mdev = 0.037/0.038/0.039/0.001 ms</span><br><span class="line"></span><br><span class="line">[root@VM-16-13-centos ~]# ping 172.17.0.3</span><br><span class="line">PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.</span><br><span class="line">64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.045 ms</span><br><span class="line">--- 172.17.0.3 ping statistics ---</span><br><span class="line">4 packets transmitted, 4 received, 0% packet loss, time 3079ms</span><br><span class="line">rtt min/avg/max/mdev = 0.040/0.042/0.045/0.006 ms</span><br></pre></td></tr></table></figure><p>容器ng1中启动了默认的nginx站点，可以通过IP直接请求到</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">curl http://172.17.0.2</span><br><span class="line"></span><br><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;title&gt;Welcome to nginx!&lt;/title&gt;</span><br><span class="line">&lt;style&gt;</span><br><span class="line">html &#123; color-scheme: light dark; &#125;</span><br><span class="line">body &#123; width: 35em; margin: 0 auto;</span><br><span class="line">font-family: Tahoma, Verdana, Arial, sans-serif; &#125;</span><br><span class="line">&lt;/style&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</span><br><span class="line">&lt;p&gt;If you see this page, the nginx web server is successfully installed and</span><br><span class="line">working. Further configuration is required.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;For online documentation and support please refer to</span><br><span class="line">&lt;a href=&quot;http://nginx.org/&quot;&gt;nginx.org&lt;/a&gt;.&lt;br/&gt;</span><br><span class="line">Commercial support is available at</span><br><span class="line">&lt;a href=&quot;http://nginx.com/&quot;&gt;nginx.com&lt;/a&gt;.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><h2 id="docker是如何进行网络通信的"><a href="#docker是如何进行网络通信的" class="headerlink" title="docker是如何进行网络通信的?"></a>docker是如何进行网络通信的?</h2><p> <strong>每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡，使用了veth-pair技术！</strong> </p><p>查看本机网卡发现，每启动一个docker容器，则会生成一个新的网卡信息，网卡信息都是一对一对存在的。</p><p>启动容器均会生成新的网卡信息，删除容器，网卡也会移除，也就是每次启动，IP地址都会新建</p><p><img src="/./learn-the-abc-of-docker-about-network/1657876653166.png" alt="1657876653166" loading="lazy"></p><p>Docker容器网络就很好的利用了Linux虚拟网络技术，在本地主机和容器内分别创建一个虚拟接口，并 让他们彼此联通（这样一对接口叫veth pair）；<br>Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高（因为Linux是在内核中 进行数据的复制来实现虚拟接口之间的数据转发，无需通过外部的网络设备交换），对于本地系统和容 器系统来说，虚拟接口跟一个正常的以太网卡相比并没有区别，只是他的速度快很多。</p><h2 id="veth-pair"><a href="#veth-pair" class="headerlink" title="veth-pair"></a>veth-pair</h2><p><a href="https://zhuanlan.zhihu.com/p/293659939">Linux veth pair 详解</a></p><p>veth pair是成对出现的一种虚拟网络设备接口，一端连着网络协议栈，一端彼此相连。</p><p>Veth-pair 不是一个设备，而是一对设备，作为虚拟网线用于连接两个虚拟网络设备。veth pair 是根据<a href="https://so.csdn.net/so/search?q=%E6%95%B0%E6%8D%AE%E9%93%BE%E8%B7%AF%E5%B1%82&spm=1001.2101.3001.7020">数据链路层</a>的 MAC 地址对网络数据包进行转发的过程来实现的，本质是反转通讯数据的方向，需要发送的数据会被转换成需要收到的数据重新送入内核网络层进行处理，从而间接的完成数据的注入。 </p><h2 id="容器互联-–link"><a href="#容器互联-–link" class="headerlink" title="容器互联 –link"></a>容器互联 –link</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"># 启动新的容器 ng2 并将它和 ng1 的网络连通</span><br><span class="line">docker run -d -P -it --name ng2 --link ng1 nginx</span><br><span class="line"></span><br><span class="line"># 即可在容器 ng2 中，直接通过容器名连通容器 ng1</span><br><span class="line">docker exec -it ng2 curl http://ng1</span><br><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;title&gt;Welcome to nginx!&lt;/title&gt;</span><br><span class="line">&lt;style&gt;</span><br><span class="line">html &#123; color-scheme: light dark; &#125;</span><br><span class="line">body &#123; width: 35em; margin: 0 auto;</span><br><span class="line">font-family: Tahoma, Verdana, Arial, sans-serif; &#125;</span><br><span class="line">&lt;/style&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</span><br><span class="line">&lt;p&gt;If you see this page, the nginx web server is successfully installed and</span><br><span class="line">working. Further configuration is required.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;For online documentation and support please refer to</span><br><span class="line">&lt;a href=&quot;http://nginx.org/&quot;&gt;nginx.org&lt;/a&gt;.&lt;br/&gt;</span><br><span class="line">Commercial support is available at</span><br><span class="line">&lt;a href=&quot;http://nginx.com/&quot;&gt;nginx.com&lt;/a&gt;.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 但是反过来，却不可以，网络不通</span><br><span class="line">docker exec -it ng1 curl http://ng2</span><br></pre></td></tr></table></figure><p>其根本原因在于使用–link命令时，其实是在容器的&#x2F;etc&#x2F;hosts中配置了相关的域名映射关系。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"># 查看ng2容器的hosts配置</span><br><span class="line"># 发现新增了到ng1的域名配置信息</span><br><span class="line">docker exec -it ng2 cat /etc/hosts</span><br><span class="line"></span><br><span class="line">127.0.0.1       localhost</span><br><span class="line">::1     localhost ip6-localhost ip6-loopback</span><br><span class="line">fe00::0 ip6-localnet</span><br><span class="line">ff00::0 ip6-mcastprefix</span><br><span class="line">ff02::1 ip6-allnodes</span><br><span class="line">ff02::2 ip6-allrouters</span><br><span class="line"># 该配置信息，让ng2内部可以直接通过ng1请求172.17.0.2</span><br><span class="line">172.17.0.2      ng1 d35478a52fd4</span><br><span class="line">172.17.0.4      7e5024e74b30</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 查看ng1容器的hosts配置</span><br><span class="line"># ng1 中未配置 ng2 的信息，所以无法直接访问</span><br><span class="line">docker exec -it ng1 cat /etc/hosts</span><br><span class="line"></span><br><span class="line">127.0.0.1       localhost</span><br><span class="line">::1     localhost ip6-localhost ip6-loopback</span><br><span class="line">fe00::0 ip6-localnet</span><br><span class="line">ff00::0 ip6-mcastprefix</span><br><span class="line">ff02::1 ip6-allnodes</span><br><span class="line">ff02::2 ip6-allrouters</span><br><span class="line">172.17.0.2      d35478a52fd4</span><br><span class="line"></span><br></pre></td></tr></table></figure><blockquote><p>该种方式相对死板，不够灵活，所以 –link 方式已经不建议使用。更为灵活的方式是自定义docker网络</p></blockquote><h2 id="自定义网络docker-network-create"><a href="#自定义网络docker-network-create" class="headerlink" title="自定义网络docker network create"></a>自定义网络docker network create</h2><p>docker0存在不能通过域名的方式访问、可以通过–link连通但是不够灵活。</p><p>docker提供的网络模式</p><ul><li>bridge 桥接模式（默认）</li><li>none 不配置网络</li><li>host 主机模式</li><li>container：容器网络连通（用的少，局限大）</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"># 你可以自定义一个桥接网络, 默认情况下,会根据docker0的IP自动生成</span><br><span class="line">docker network create -d bridge my-network</span><br><span class="line"></span><br><span class="line">docker network inspect my-network</span><br><span class="line">[</span><br><span class="line">    &#123;</span><br><span class="line">        &quot;Name&quot;: &quot;my-network&quot;,</span><br><span class="line">        &quot;Id&quot;: &quot;89a89f04f757b184d3544373940008b02b7215587fb0d591c87b6f4e5030dd4e&quot;,</span><br><span class="line">        &quot;Created&quot;: &quot;2022-07-15T18:19:46.645909571+08:00&quot;,</span><br><span class="line">        &quot;Scope&quot;: &quot;local&quot;,</span><br><span class="line">        &quot;Driver&quot;: &quot;bridge&quot;,</span><br><span class="line">        &quot;EnableIPv6&quot;: false,</span><br><span class="line">        &quot;IPAM&quot;: &#123;</span><br><span class="line">            &quot;Driver&quot;: &quot;default&quot;,</span><br><span class="line">            &quot;Options&quot;: &#123;&#125;,</span><br><span class="line">            &quot;Config&quot;: [</span><br><span class="line">                &#123;</span><br><span class="line">                    &quot;Subnet&quot;: &quot;172.18.0.0/16&quot;,</span><br><span class="line">                    &quot;Gateway&quot;: &quot;172.18.0.1&quot;</span><br><span class="line">                &#125;</span><br><span class="line">            ]</span><br><span class="line">        &#125;,</span><br><span class="line">        &quot;Internal&quot;: false,</span><br><span class="line">        &quot;Attachable&quot;: false,</span><br><span class="line">        &quot;Ingress&quot;: false,</span><br><span class="line">        &quot;ConfigFrom&quot;: &#123;</span><br><span class="line">            &quot;Network&quot;: &quot;&quot;</span><br><span class="line">        &#125;,</span><br><span class="line">        &quot;ConfigOnly&quot;: false,</span><br><span class="line">        &quot;Containers&quot;: &#123;&#125;,</span><br><span class="line">        &quot;Options&quot;: &#123;&#125;,</span><br><span class="line">        &quot;Labels&quot;: &#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 当然可以自己指定子网IP和网关。指定子网IP需要指定网关IP，默认都是x.x.0.1</span><br><span class="line">docker network create -d bridge --subnet=192.168.0.0/16 --getway 192.168.0.1 my-network2</span><br></pre></td></tr></table></figure><h2 id="使用自定义网络-–net"><a href="#使用自定义网络-–net" class="headerlink" title="使用自定义网络 –net"></a>使用自定义网络 –net</h2><p>启动容器时，使用–net参数指定网络，如果不指定该参数，则默认使用docker0作为网络。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br></pre></td><td class="code"><pre><span class="line"># 启动my-ng1容器</span><br><span class="line">[root@VM-16-13-centos ~]# docker run -d -it --name my-ng1 --net my-network nginx</span><br><span class="line">WARNING: IPv4 forwarding is disabled. Networking will not work.</span><br><span class="line">fb9f6921bd53a4522e20b84d35447eaabe316cba9cd9c7cda6faa362b2047d64</span><br><span class="line"></span><br><span class="line"># 启动my-ng2容器</span><br><span class="line">[root@VM-16-13-centos ~]# docker run -d -it --name my-ng2 --net my-network nginx</span><br><span class="line">WARNING: IPv4 forwarding is disabled. Networking will not work.</span><br><span class="line">71ffcb0a619d81cd36c3283419da543bd23a721d4e84801b877891a5be1d614a</span><br><span class="line"></span><br><span class="line"># 查看新建网络的情况，发现新建的两个容器已经挂载在新建的网络上</span><br><span class="line">[root@VM-16-13-centos ~]# docker network inspect my-network</span><br><span class="line">[</span><br><span class="line">    &#123;</span><br><span class="line">        &quot;Name&quot;: &quot;my-network&quot;,</span><br><span class="line">        &quot;Id&quot;: &quot;89a89f04f757b184d3544373940008b02b7215587fb0d591c87b6f4e5030dd4e&quot;,</span><br><span class="line">        &quot;Created&quot;: &quot;2022-07-15T18:19:46.645909571+08:00&quot;,</span><br><span class="line">        &quot;Scope&quot;: &quot;local&quot;,</span><br><span class="line">        &quot;Driver&quot;: &quot;bridge&quot;,</span><br><span class="line">        &quot;EnableIPv6&quot;: false,</span><br><span class="line">        &quot;IPAM&quot;: &#123;</span><br><span class="line">            &quot;Driver&quot;: &quot;default&quot;,</span><br><span class="line">            &quot;Options&quot;: &#123;&#125;,</span><br><span class="line">            &quot;Config&quot;: [</span><br><span class="line">                &#123;</span><br><span class="line">                    &quot;Subnet&quot;: &quot;172.18.0.0/16&quot;,</span><br><span class="line">                    &quot;Gateway&quot;: &quot;172.18.0.1&quot;</span><br><span class="line">                &#125;</span><br><span class="line">            ]</span><br><span class="line">        &#125;,</span><br><span class="line">        &quot;Internal&quot;: false,</span><br><span class="line">        &quot;Attachable&quot;: false,</span><br><span class="line">        &quot;Ingress&quot;: false,</span><br><span class="line">        &quot;ConfigFrom&quot;: &#123;</span><br><span class="line">            &quot;Network&quot;: &quot;&quot;</span><br><span class="line">        &#125;,</span><br><span class="line">        &quot;ConfigOnly&quot;: false,</span><br><span class="line">        &quot;Containers&quot;: &#123;</span><br><span class="line">            &quot;71ffcb0a619d81cd36c3283419da543bd23a721d4e84801b877891a5be1d614a&quot;: &#123;</span><br><span class="line">                &quot;Name&quot;: &quot;my-ng2&quot;,</span><br><span class="line">                &quot;EndpointID&quot;: &quot;5e3c6239a7bf550a97963466b74e8829f1523af6d6985b8b46e0da5b74f11332&quot;,</span><br><span class="line">                &quot;MacAddress&quot;: &quot;02:42:ac:12:00:03&quot;,</span><br><span class="line">                &quot;IPv4Address&quot;: &quot;172.18.0.3/16&quot;,</span><br><span class="line">                &quot;IPv6Address&quot;: &quot;&quot;</span><br><span class="line">            &#125;,</span><br><span class="line">            &quot;fb9f6921bd53a4522e20b84d35447eaabe316cba9cd9c7cda6faa362b2047d64&quot;: &#123;</span><br><span class="line">                &quot;Name&quot;: &quot;my-ng1&quot;,</span><br><span class="line">                &quot;EndpointID&quot;: &quot;f450e8f8f9ea96aaed2c55e0db93f1cd8962ea9998b3500ca4307f419a76aade&quot;,</span><br><span class="line">                &quot;MacAddress&quot;: &quot;02:42:ac:12:00:02&quot;,</span><br><span class="line">                &quot;IPv4Address&quot;: &quot;172.18.0.2/16&quot;,</span><br><span class="line">                &quot;IPv6Address&quot;: &quot;&quot;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        &quot;Options&quot;: &#123;&#125;,</span><br><span class="line">        &quot;Labels&quot;: &#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"># 直接在 my-ng1 容器中，使用容器名称，请求 my-ng2 容器</span><br><span class="line">[root@VM-16-13-centos ~]# docker exec -it my-ng1 curl http://my-ng2</span><br><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;title&gt;Welcome to nginx!&lt;/title&gt;</span><br><span class="line">&lt;style&gt;</span><br><span class="line">html &#123; color-scheme: light dark; &#125;</span><br><span class="line">body &#123; width: 35em; margin: 0 auto;</span><br><span class="line">font-family: Tahoma, Verdana, Arial, sans-serif; &#125;</span><br><span class="line">&lt;/style&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</span><br><span class="line">&lt;p&gt;If you see this page, the nginx web server is successfully installed and</span><br><span class="line">working. Further configuration is required.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;For online documentation and support please refer to</span><br><span class="line">&lt;a href=&quot;http://nginx.org/&quot;&gt;nginx.org&lt;/a&gt;.&lt;br/&gt;</span><br><span class="line">Commercial support is available at</span><br><span class="line">&lt;a href=&quot;http://nginx.com/&quot;&gt;nginx.com&lt;/a&gt;.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 直接在 my-ng2 容器中，使用容器名称，请求 my-ng1 容器</span><br><span class="line">[root@VM-16-13-centos ~]# docker exec -it my-ng2 curl http://my-ng1</span><br><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;title&gt;Welcome to nginx!&lt;/title&gt;</span><br><span class="line">&lt;style&gt;</span><br><span class="line">html &#123; color-scheme: light dark; &#125;</span><br><span class="line">body &#123; width: 35em; margin: 0 auto;</span><br><span class="line">font-family: Tahoma, Verdana, Arial, sans-serif; &#125;</span><br><span class="line">&lt;/style&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</span><br><span class="line">&lt;p&gt;If you see this page, the nginx web server is successfully installed and</span><br><span class="line">working. Further configuration is required.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;For online documentation and support please refer to</span><br><span class="line">&lt;a href=&quot;http://nginx.org/&quot;&gt;nginx.org&lt;/a&gt;.&lt;br/&gt;</span><br><span class="line">Commercial support is available at</span><br><span class="line">&lt;a href=&quot;http://nginx.com/&quot;&gt;nginx.com&lt;/a&gt;.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line">[root@VM-16-13-centos ~]#</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>可以发现，新建的自定义网络，修复了docker0的缺点，可以通过容器名进行互联。</p><p>这种方式是推荐使用的方式。</p><p>在构建不同的集群时，可以使用不同的网络，用来保证各个集群的网络隔离。</p><h2 id="网络连通docker-network-connect"><a href="#网络连通docker-network-connect" class="headerlink" title="网络连通docker network connect"></a>网络连通docker network connect</h2><p>在基于自定义网络的基础上，如果打通不同自定义网络之间的网络？</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 将之前创建的docker0网络下的容器 ng1 连接到网络 my-network 上</span><br><span class="line">[root@VM-16-13-centos ~]# docker network connect my-network ng1</span><br><span class="line"></span><br><span class="line"># 查看 ng1 的网络情况</span><br><span class="line">docker inspect ng1</span><br></pre></td></tr></table></figure><p><img src="/./learn-the-abc-of-docker-about-network/1657882812055.png" alt="1657882812055" loading="lazy"></p><p>可以发现 ng1 上被挂载了一个新的网络my-network。就是所谓的”一个容器两个IP地址”。</p><blockquote><p>所以不同网络之间的容器连通，其实是容器和网络进行连通，而不是两个网络进行连通</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"># 测试，直接在网络 docker0 中的 ng1 内连接网络 my-network 下的 my-ng1</span><br><span class="line">[root@VM-16-13-centos ~]# docker exec -it ng1 curl http://my-ng1</span><br><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;title&gt;Welcome to nginx!&lt;/title&gt;</span><br><span class="line">&lt;style&gt;</span><br><span class="line">html &#123; color-scheme: light dark; &#125;</span><br><span class="line">body &#123; width: 35em; margin: 0 auto;</span><br><span class="line">font-family: Tahoma, Verdana, Arial, sans-serif; &#125;</span><br><span class="line">&lt;/style&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</span><br><span class="line">&lt;p&gt;If you see this page, the nginx web server is successfully installed and</span><br><span class="line">working. Further configuration is required.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;For online documentation and support please refer to</span><br><span class="line">&lt;a href=&quot;http://nginx.org/&quot;&gt;nginx.org&lt;/a&gt;.&lt;br/&gt;</span><br><span class="line">Commercial support is available at</span><br><span class="line">&lt;a href=&quot;http://nginx.com/&quot;&gt;nginx.com&lt;/a&gt;.&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">&lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 测试，直接在网络 docker0 中的 ng2 内连接网络 my-network 下的 my-ng1</span><br><span class="line"># 由于ng2并没有打通，所以无法连接成功</span><br><span class="line">[root@VM-16-13-centos ~]# docker exec -it ng2 curl http://my-ng1</span><br></pre></td></tr></table></figure><h2 id="集群部署"><a href="#集群部署" class="headerlink" title="集群部署"></a>集群部署</h2><p>分片+高可用+负载均衡</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;文章围绕 Docker 网络互连展开，详细介绍了默认网络、容器互联方法及自定义网络配置。&lt;br&gt;文章先讲解默认的 docker0 网络，指出 Linux 主机默认存在该虚拟桥接网卡，启动容器会生成 veth-pair 虚拟网卡对，主机可 ping 通容器 IP 并访问容器服务。接着介绍容器互联的 –link 方式，说明其通过配置 &amp;#x2F;etc&amp;#x2F;hosts 实现单向域名访问，但灵活性差。&lt;br&gt;随后重点推荐自定义网络，说明可通过docker network create创建桥接网络，指定子网和网关，启动容器时用 –net 指定该网络，即可实现容器间双向域名访问，保证网络隔离。还提到用docker network connect可让容器加入多个网络，实现不同网络间连通，最后提及集群部署需结合分片、高可用和负载均衡。&lt;/p&gt;</summary>
    
    
    
    <category term="docker" scheme="https://blog.plcent.com/categories/docker/"/>
    
    
    <category term="docker" scheme="https://blog.plcent.com/tags/docker/"/>
    
  </entry>
  
  <entry>
    <title>docker入门学习笔记</title>
    <link href="https://blog.plcent.com/learn-the-abc-of-docker/"/>
    <id>https://blog.plcent.com/learn-the-abc-of-docker/</id>
    <published>2022-07-11T08:34:10.000Z</published>
    <updated>2025-10-22T03:31:12.463Z</updated>
    
    <content type="html"><![CDATA[<p>docker基础知识点概要总结</p><span id="more"></span><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>官方文档：<a href="https://docs.docker.com/engine/install/centos/">https://docs.docker.com/engine/install/centos/</a></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line"># 1. 卸载旧版本</span><br><span class="line">sudo yum remove docker \</span><br><span class="line">                  docker-client \</span><br><span class="line">                  docker-client-latest \</span><br><span class="line">                  docker-common \</span><br><span class="line">                  docker-latest \</span><br><span class="line">                  docker-latest-logrotate \</span><br><span class="line">                  docker-logrotate \</span><br><span class="line">                  docker-engine</span><br><span class="line"></span><br><span class="line"># 2. 安装前置工具/依赖</span><br><span class="line">sudo yum install -y yum-utils</span><br><span class="line"></span><br><span class="line"># 3. 设置镜像仓库</span><br><span class="line">sudo yum-config-manager \</span><br><span class="line">    --add-repo \</span><br><span class="line">    https://download.docker.com/linux/centos/docker-ce.repo</span><br><span class="line"></span><br><span class="line"># 3. 使用阿里云镜像</span><br><span class="line">sudo yum-config-manager \</span><br><span class="line">    --add-repo \</span><br><span class="line">    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</span><br><span class="line">    </span><br><span class="line"># 4. 安装最新版docker </span><br><span class="line"># docker-ce 社区版本，docker-ee 企业版，推荐社区版</span><br><span class="line">sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin</span><br><span class="line"></span><br><span class="line"># 4. 安装指定版本docker</span><br><span class="line"># 4.1 列出所有版本可用版本</span><br><span class="line">yum list docker-ce --showduplicates | sort -r</span><br><span class="line"></span><br><span class="line">docker-ce.x86_64                3:20.10.9-3.el8                 docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.8-3.el8                 docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.7-3.el8                 docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.6-3.el8                 docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.5-3.el8                 docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.4-3.el8                 docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.3-3.el8                 docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.2-3.el8                 docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.17-3.el8                docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.16-3.el8                docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.15-3.el8                docker-ce-stable</span><br><span class="line">docker-ce.x86_64                3:20.10.14-3.el8                docker-ce-stable</span><br><span class="line"></span><br><span class="line"># 4.2 安装指定版本</span><br><span class="line">sudo yum install docker-ce-&lt;VERSION_STRING&gt; docker-ce-cli-&lt;VERSION_STRING&gt; containerd.io docker-compose-plugin</span><br><span class="line"># 4.2 选择需要的版本，通过第二列，“：”之后和“-”之前的部分，是版本号（VERSION_STRING）</span><br><span class="line"># 例如安装第一个20.10.9版本</span><br><span class="line">sudo yum install docker-ce-20.10.9 docker-ce-cli-20.10.9 containerd.io docker-compose-plugin</span><br><span class="line"></span><br><span class="line"># 5. 启动docker</span><br><span class="line">sudo systemctl start docker</span><br><span class="line"></span><br><span class="line"># 6. 查看docker版本信息</span><br><span class="line">docker version</span><br><span class="line"></span><br><span class="line">Client: Docker Engine - Community</span><br><span class="line"> Version:           20.10.17</span><br><span class="line"> API version:       1.41</span><br><span class="line"> Go version:        go1.17.11</span><br><span class="line"> Git commit:        100c701</span><br><span class="line"> Built:             Mon Jun  6 23:03:11 2022</span><br><span class="line"> OS/Arch:           linux/amd64</span><br><span class="line"> Context:           default</span><br><span class="line"> Experimental:      true</span><br><span class="line"></span><br><span class="line">Server: Docker Engine - Community</span><br><span class="line"> Engine:</span><br><span class="line">  Version:          20.10.17</span><br><span class="line">  API version:      1.41 (minimum version 1.12)</span><br><span class="line">  Go version:       go1.17.11</span><br><span class="line">  Git commit:       a89b842</span><br><span class="line">  Built:            Mon Jun  6 23:01:29 2022</span><br><span class="line">  OS/Arch:          linux/amd64</span><br><span class="line">  Experimental:     false</span><br><span class="line"> containerd:</span><br><span class="line">  Version:          1.6.6</span><br><span class="line">  GitCommit:        10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1</span><br><span class="line"> runc:</span><br><span class="line">  Version:          1.1.2</span><br><span class="line">  GitCommit:        v1.1.2-0-ga916309</span><br><span class="line"> docker-init:</span><br><span class="line">  Version:          0.19.0</span><br><span class="line">  GitCommit:        de40ad0</span><br><span class="line">  </span><br><span class="line"># 7. 使用hello-world测试docker是否按照成功</span><br><span class="line">sudo docker run hello-world</span><br><span class="line"></span><br><span class="line">Unable to find image &#x27;hello-world:latest&#x27; locally</span><br><span class="line">latest: Pulling from library/hello-world</span><br><span class="line">2db29710123e: Pull complete</span><br><span class="line">Digest: sha256:13e367d31ae85359f42d637adf6da428f76d75dc9afeb3c21faea0d976f5c651</span><br><span class="line">Status: Downloaded newer image for hello-world:latest</span><br><span class="line"></span><br><span class="line">Hello from Docker!</span><br><span class="line">This message shows that your installation appears to be working correctly.</span><br><span class="line"></span><br><span class="line">To generate this message, Docker took the following steps:</span><br><span class="line"> 1. The Docker client contacted the Docker daemon.</span><br><span class="line"> 2. The Docker daemon pulled the &quot;hello-world&quot; image from the Docker Hub.</span><br><span class="line">    (amd64)</span><br><span class="line"> 3. The Docker daemon created a new container from that image which runs the</span><br><span class="line">    executable that produces the output you are currently reading.</span><br><span class="line"> 4. The Docker daemon streamed that output to the Docker client, which sent it</span><br><span class="line">    to your terminal.</span><br><span class="line"></span><br><span class="line">To try something more ambitious, you can run an Ubuntu container with:</span><br><span class="line"> $ docker run -it ubuntu bash</span><br><span class="line"></span><br><span class="line">Share images, automate workflows, and more with a free Docker ID:</span><br><span class="line"> https://hub.docker.com/</span><br><span class="line"></span><br><span class="line">For more examples and ideas, visit:</span><br><span class="line"> https://docs.docker.com/get-started/</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 查看docker下载的所有镜像</span><br><span class="line">docker images</span><br><span class="line"></span><br><span class="line">REPOSITORY    TAG       IMAGE ID       CREATED        SIZE</span><br><span class="line">hello-world   latest    feb5d9fea6a5   9 months ago   13.3kB</span><br></pre></td></tr></table></figure><h1 id="卸载"><a href="#卸载" class="headerlink" title="卸载"></a>卸载</h1><p><a href="https://docs.docker.com/engine/install/centos/#uninstall-docker-engine">https://docs.docker.com/engine/install/centos/#uninstall-docker-engine</a></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 卸载依赖</span><br><span class="line">sudo yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin</span><br><span class="line"></span><br><span class="line"># 删除目录</span><br><span class="line">sudo rm -rf /var/lib/docker</span><br><span class="line">sudo rm -rf /var/lib/containerd</span><br></pre></td></tr></table></figure><p><code>/var/lib/docker</code> 是docker的默认工作路径。</p><h1 id="docker-run-执行流程"><a href="#docker-run-执行流程" class="headerlink" title="docker run 执行流程"></a>docker run 执行流程</h1><p>执行<code>docker run</code>时，首先会在本地查找镜像是否存在，如果存在，则直接运行。如果不存在，则到远程docker hub上进行下载，如果下载成功，则运行，如果不存在，则报错。</p><h1 id="docker-原理"><a href="#docker-原理" class="headerlink" title="docker 原理"></a>docker 原理</h1><p> Docker 使用客户端-服务器架构。Docker*客户端与 Docker守护进程对话，后者负责构建、运行和分发 Docker 容器的繁重工作 。 Docker 守护程序 ( <code>dockerd</code>) 侦听 Docker API 请求并管理 Docker 对象，例如图像、容器、网络和卷。 </p><p>Docker 使用一种称为<em>容器</em><code>namespaces</code>的技术来提供隔离的工作空间。当您运行容器时，Docker 会为该容器创建一组 <em>命名空间。</em></p><p>这些命名空间提供了一层隔离。容器的每个方面都在单独的命名空间中运行，并且它的访问权限仅限于该命名空间。</p><p><img src="/./learn-the-abc-of-docker/architecture.svg" alt="docker" loading="lazy"></p><h1 id="docker信息命令"><a href="#docker信息命令" class="headerlink" title="docker信息命令"></a>docker信息命令</h1><h2 id="docker-verion"><a href="#docker-verion" class="headerlink" title="docker verion"></a>docker verion</h2><p>显示docker的基本信息</p><h2 id="docker-info"><a href="#docker-info" class="headerlink" title="docker info"></a>docker info</h2><p>显示docker的系统信息，包括镜像和容器数量等等</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">docker info</span><br><span class="line">Client:</span><br><span class="line"> Context:    default</span><br><span class="line"> Debug Mode: false</span><br><span class="line"> Plugins:</span><br><span class="line">  app: Docker App (Docker Inc., v0.9.1-beta3)</span><br><span class="line">  buildx: Docker Buildx (Docker Inc., v0.8.2-docker)</span><br><span class="line">  compose: Docker Compose (Docker Inc., v2.6.0)</span><br><span class="line">  scan: Docker Scan (Docker Inc., v0.17.0)</span><br><span class="line"></span><br><span class="line">Server:</span><br><span class="line"> Containers: 1</span><br><span class="line">  Running: 0</span><br><span class="line">  Paused: 0</span><br><span class="line">  Stopped: 1</span><br><span class="line"> Images: 1</span><br><span class="line"> Server Version: 20.10.17</span><br><span class="line"> Storage Driver: overlay2</span><br><span class="line">  Backing Filesystem: extfs</span><br><span class="line">  Supports d_type: true</span><br><span class="line">  Native Overlay Diff: true</span><br><span class="line">  userxattr: false</span><br><span class="line"> Logging Driver: json-file</span><br><span class="line"> Cgroup Driver: cgroupfs</span><br><span class="line"> Cgroup Version: 1</span><br><span class="line"> Plugins:</span><br><span class="line">  Volume: local</span><br><span class="line">  Network: bridge host ipvlan macvlan null overlay</span><br><span class="line">  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog</span><br><span class="line"> Swarm: inactive</span><br><span class="line"> Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc</span><br><span class="line"> Default Runtime: runc</span><br><span class="line"> Init Binary: docker-init</span><br><span class="line"> containerd version: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1</span><br><span class="line"> runc version: v1.1.2-0-ga916309</span><br><span class="line"> init version: de40ad0</span><br><span class="line"> Security Options:</span><br><span class="line">  seccomp</span><br><span class="line">   Profile: default</span><br><span class="line"> Kernel Version: 4.18.0-305.10.2.el8_4.x86_64</span><br><span class="line"> Operating System: CentOS Linux 8 (Core)</span><br><span class="line"> OSType: linux</span><br><span class="line"> Architecture: x86_64</span><br><span class="line"> CPUs: 2</span><br><span class="line"> Total Memory: 3.649GiB</span><br><span class="line"> Name: VM-16-13-centos</span><br><span class="line"> ID: KFBX:BDVF:ADQ4:AZAB:YA5L:TBQS:Z3I2:JOHA:ITTB:SQDC:E42M:M73J</span><br><span class="line"> Docker Root Dir: /var/lib/docker</span><br><span class="line"> Debug Mode: false</span><br><span class="line"> Registry: https://index.docker.io/v1/</span><br><span class="line"> Labels:</span><br><span class="line"> Experimental: false</span><br><span class="line"> Insecure Registries:</span><br><span class="line">  127.0.0.0/8</span><br><span class="line"> Live Restore Enabled: false</span><br></pre></td></tr></table></figure><h2 id="docker-命令-–help"><a href="#docker-命令-–help" class="headerlink" title="docker  命令 –help"></a>docker  命令 –help</h2><p>命令文档  <a href="https://docs.docker.com/reference/">https://docs.docker.com/reference/</a></p><h1 id="镜像命令"><a href="#镜像命令" class="headerlink" title="镜像命令"></a>镜像命令</h1><h2 id="docker-image"><a href="#docker-image" class="headerlink" title="docker image"></a>docker image</h2><p>镜像管理</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">docker images</span><br><span class="line"></span><br><span class="line">REPOSITORY    TAG       IMAGE ID       CREATED        SIZE</span><br><span class="line">hello-world   latest    feb5d9fea6a5   9 months ago   13.3kB</span><br><span class="line"></span><br><span class="line"># REPOSITORY 镜像的仓库源，容器名称</span><br><span class="line"># TAG镜像的标签</span><br><span class="line"># IMAGE ID镜像ID</span><br><span class="line"># CREATED镜像创建时间</span><br><span class="line"># SIZE镜像大小</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 可选性</span><br><span class="line">-a, --all显示所有镜像</span><br><span class="line">-q, --quiet仅显示镜像ID</span><br></pre></td></tr></table></figure><h2 id="docker-search"><a href="#docker-search" class="headerlink" title="docker search"></a>docker search</h2><p>搜索镜像</p><p>网页版镜像仓库地址: <a href="https://hub.docker.com/search">https://hub.docker.com/search</a></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"># 所有所有镜像</span><br><span class="line">docker search mysql</span><br><span class="line">NAMEDESCRIPTION                                     STARS     OFFICIAL   AUTOMATED</span><br><span class="line">mysqlMySQL is a widely used, open-source relation…   12851     [OK]</span><br><span class="line">mariadbMariaDB Server is a high performing open sou…   4926      [OK]</span><br><span class="line"></span><br><span class="line"># 可选项</span><br><span class="line">-f, --filter</span><br><span class="line">--format</span><br><span class="line">--limit</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 按条件搜索，STARS大于600 且 是官方仓库</span><br><span class="line"># 两种写法, 多条件使用多个--filter</span><br><span class="line">docker search mysql --filter=stars=600 --filter is-official=true</span><br><span class="line"></span><br><span class="line">NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED</span><br><span class="line">mysql     MySQL is a widely used, open-source relation…   12851     [OK]</span><br><span class="line">mariadb   MariaDB Server is a high performing open sou…   4926      [OK]</span><br><span class="line"></span><br><span class="line"># --filter支持三个条件</span><br><span class="line"># stars收藏数stars=number</span><br><span class="line"># is-automated自动化 is-automated=true/false</span><br><span class="line"># is-official官方 is-official=true/false</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="docker-pull"><a href="#docker-pull" class="headerlink" title="docker pull"></a>docker pull</h2><p>下载镜像</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"># docker pull 镜像名[:tag]</span><br><span class="line">docker pull mysql</span><br><span class="line">Using default tag: latest# 如果不写tag，默认是latest</span><br><span class="line">latest: Pulling from library/mysql# 分层下载，联合文件系统，docker image核心</span><br><span class="line">e54b73e95ef3: Pull complete</span><br><span class="line">bb429e544310: Pull complete</span><br><span class="line">c148b3f9047c: Pull complete</span><br><span class="line">a1dd213a3236: Pull complete</span><br><span class="line">297095d1476d: Pull complete</span><br><span class="line">87f3aa837301: Pull complete</span><br><span class="line">535019436481: Pull complete</span><br><span class="line">23722cff1cc3: Pull complete</span><br><span class="line">eb19883dc4c6: Pull complete</span><br><span class="line">6eaa2c236095: Pull complete</span><br><span class="line">Digest: sha256:444f037733d01fc3dfc691a9ab05e346629e8e4d3a6c75da864f21421fb38ced# 签名</span><br><span class="line">Status: Downloaded newer image for mysql:latest</span><br><span class="line">docker.io/library/mysql:latest#docker image 真实地址</span><br><span class="line"></span><br><span class="line"># 以下两个命令等价</span><br><span class="line">docker pull mysql</span><br><span class="line">docker pull docker.io/library/mysql:latest</span><br></pre></td></tr></table></figure><h2 id="docker-rmi"><a href="#docker-rmi" class="headerlink" title="docker rmi"></a>docker rmi</h2><p>删除镜像</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">docker rmi -f hello-world</span><br><span class="line"></span><br><span class="line">Untagged: hello-world:latest</span><br><span class="line">Untagged: hello-world@sha256:13e367d31ae85359f42d637adf6da428f76d75dc9afeb3c21faea0d976f5c651</span><br><span class="line">Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412</span><br><span class="line"></span><br><span class="line">docker rmi -f image_id[:tag]# 删除指定镜像</span><br><span class="line">docker rmi - f image_id image_id # 删除多个镜像</span><br></pre></td></tr></table></figure><h1 id="容器命令"><a href="#容器命令" class="headerlink" title="容器命令"></a>容器命令</h1><p>有镜像才能创建容器</p><h2 id="新建容器并启动-docker-run"><a href="#新建容器并启动-docker-run" class="headerlink" title="新建容器并启动 docker run"></a>新建容器并启动 docker run</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">docker run [参数] image</span><br><span class="line"></span><br><span class="line"># 参数说明</span><br><span class="line">--name=&quot;容器名称&quot;容器名字，启动容器的名称，便于区分</span><br><span class="line">-d后台运行</span><br><span class="line">-it使用交互方式运行,进入容器内容查看内容</span><br><span class="line">-p 指定容器端口 -p 8080:80</span><br><span class="line">-p ip:主机端口:容器端口</span><br><span class="line">-p 主机端口:容器端口(最常用)</span><br><span class="line">-p 容器端口</span><br><span class="line">-P随机指定端口</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"># cmd 下启动cenos</span><br><span class="line">docker run -it centos /bin/sh</span><br><span class="line">[root@5dda638536fa /]#</span><br><span class="line"></span><br><span class="line"># centos 下启动centos</span><br><span class="line">docker run -it centos /bin/bash</span><br><span class="line">[root@5dda638536fa /]#</span><br><span class="line"></span><br><span class="line"># exit停止容器并退出容器</span><br><span class="line">[root@5dda638536fa /]# exit</span><br><span class="line"># ctrl + P + Q 不停止容器 退出容器</span><br></pre></td></tr></table></figure><h2 id="docker-ps"><a href="#docker-ps" class="headerlink" title="docker ps"></a>docker ps</h2><p>列出运行的容器</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"># docker ps [可选参数]</span><br><span class="line"></span><br><span class="line"># 列出正在运行的容器</span><br><span class="line">docker ps</span><br><span class="line"></span><br><span class="line">CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                  NAMES</span><br><span class="line">113ffb59a550   nginx     &quot;/docker-entrypoint.…&quot;   6 minutes ago   Up 6 minutes   0.0.0.0:8080-&gt;80/tcp   nginx-01</span><br><span class="line"></span><br><span class="line"># CONTAINER ID 容器ID</span><br><span class="line"># IMAGE镜像名称</span><br><span class="line"># COMMAND启动命令</span><br><span class="line"># CREATED容器创建时间</span><br><span class="line"># STATUS运行状态</span><br><span class="line"># PORTS端口映射情况</span><br><span class="line"># NAMES容器名称</span><br><span class="line"></span><br><span class="line"># 列出所有容器，包括已经停止的</span><br><span class="line">docker ps -a</span><br><span class="line"></span><br><span class="line"># 根据名称模糊搜索</span><br><span class="line">docker ps -a --filter &quot;name=ng&quot;</span><br><span class="line"></span><br><span class="line"># 根据容器ID模糊搜索</span><br><span class="line">docker ps -a --filter &quot;id=cca&quot;</span><br><span class="line"></span><br><span class="line"># 可选参数</span><br><span class="line">-a全部</span><br><span class="line">-n num最近创建的几条</span><br><span class="line">-l最后创建的一条</span><br><span class="line">-q只显示ID</span><br><span class="line">-s显示size大小</span><br><span class="line">--no-trunc显示明细信息， don&#x27;t truncate output 不截断输出</span><br><span class="line">-f, --filter过滤条件 -f &quot;key=value&quot;</span><br><span class="line">id</span><br><span class="line">name</span><br><span class="line">label</span><br><span class="line">statusOne of created, restarting, running, removing, paused, exited, or dead</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="docker-rm"><a href="#docker-rm" class="headerlink" title="docker rm"></a>docker rm</h2><p>删除容器</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"># 删除指定容器</span><br><span class="line">docker rm bfb2710c293d</span><br><span class="line"></span><br><span class="line"># 删除所有不在运行的容器</span><br><span class="line">docker rm $(docker ps -aq -f &quot;status=exited&quot;)</span><br><span class="line"># 等价于</span><br><span class="line">docker ps -aq -f &quot;status=exited&quot; | xargs docker rm</span><br><span class="line"></span><br><span class="line"># 可选参数</span><br><span class="line">-f强制删除正在运行的容器</span><br></pre></td></tr></table></figure><h2 id="docker-start-restart"><a href="#docker-start-restart" class="headerlink" title="docker start&#x2F;restart"></a>docker start&#x2F;restart</h2><p>启动容器</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 启动容器</span><br><span class="line">docker start 84480543d8cd</span><br><span class="line"></span><br><span class="line"># 重启容器，重启时间间隔2秒</span><br><span class="line">docker restart -t 10 84480543d8cd</span><br></pre></td></tr></table></figure><h2 id="docker-stop-kill"><a href="#docker-stop-kill" class="headerlink" title="docker stop&#x2F;kill"></a>docker stop&#x2F;kill</h2><p>停止容器</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 优雅退出容器</span><br><span class="line">docker stop 84480543d8cd</span><br><span class="line"></span><br><span class="line"># 强制退出容器</span><br><span class="line">docker kill 84480543d8cd</span><br></pre></td></tr></table></figure><h1 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h1><h2 id="后台启动容器-docker-run"><a href="#后台启动容器-docker-run" class="headerlink" title="后台启动容器 docker run"></a>后台启动容器 docker run</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 使用-d指令后台启动</span><br><span class="line">docker run -d centos</span><br><span class="line"></span><br><span class="line"># 该命令存在问题，通过docker ps 发现容器被停止了</span><br><span class="line"># docker容器使用后台运行时，必须要有一个前台进程，如果没有就会自动停止，该方式就缺乏前台进程导致启动后自动停止</span><br><span class="line"></span><br><span class="line"># 使用-it保持容器后台运行</span><br><span class="line">docker run --name centos-03 -d  -it centos /bin/sh</span><br></pre></td></tr></table></figure><h2 id="查看日志-docker-logs"><a href="#查看日志-docker-logs" class="headerlink" title="查看日志 docker logs"></a>查看日志 docker logs</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"># 监听容器日志</span><br><span class="line">docker logs -tf 9164f68ea536</span><br><span class="line"></span><br><span class="line"># 输出指定时间之后的日志</span><br><span class="line">docker logs --since 2022-07-12T08:15:04.719814800Z 9164f68ea536</span><br><span class="line"></span><br><span class="line"># 可选参数</span><br><span class="line">-f监听日志输出</span><br><span class="line">-n, --tail输出最后N行日志</span><br><span class="line">-t, --timestamps显示时间戳，每一行日志前输出时间戳信息</span><br><span class="line">-since输出指定时间之后的日志</span><br><span class="line">-until输出指定时间之前的日志</span><br></pre></td></tr></table></figure><h2 id="查看容器进程-docker-top"><a href="#查看容器进程-docker-top" class="headerlink" title="查看容器进程 docker top"></a>查看容器进程 docker top</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker top 9164f68ea536</span><br><span class="line">UIDPIDPPIDCSTIMETTYTIMECMD</span><br><span class="line">root35293509008:15?00:00:00/bin/sh</span><br></pre></td></tr></table></figure><h2 id="查看容器元数据-docker-inspect"><a href="#查看容器元数据-docker-inspect" class="headerlink" title="查看容器元数据 docker inspect"></a>查看容器元数据 docker inspect</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 查看容器元数据</span><br><span class="line">docker inspect 9164f68ea536</span><br></pre></td></tr></table></figure><h2 id="进入容器-docker-exec-attach"><a href="#进入容器-docker-exec-attach" class="headerlink" title="进入容器 docker exec&#x2F;attach"></a>进入容器 docker exec&#x2F;attach</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"># 方式一</span><br><span class="line"># 新建一个命令行并进入</span><br><span class="line">docker exec -it 容器ID bashShell</span><br><span class="line"></span><br><span class="line">docker exec -it 9164f68ea536 /bin/bash</span><br><span class="line"></span><br><span class="line"># 方式二</span><br><span class="line"># 进入正在运行的命令行</span><br><span class="line">docker attach 容器ID</span><br><span class="line"></span><br><span class="line">docker attach 9164f68ea536</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="拷贝命令-docker-copy"><a href="#拷贝命令-docker-copy" class="headerlink" title="拷贝命令 docker copy"></a>拷贝命令 docker copy</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"># 复制容器文件到本地</span><br><span class="line">docker cp 容器:路径 本机路径</span><br><span class="line"></span><br><span class="line"># 复制本地文件到容器</span><br><span class="line">docker cp 本机路径 容器:路径</span><br><span class="line"></span><br><span class="line"># 在centos中新建一个文件</span><br><span class="line">docker exec -it -w ~ centos-01 touch /tmp/test.txt</span><br><span class="line"># 拷贝容器文件到当前目录</span><br><span class="line">docker cp centos-01:/tmp/test.txt ./</span><br><span class="line"></span><br><span class="line"># 本地新建文件并复制到容器</span><br><span class="line">echo &quot;test&quot; &gt;&gt; test2.txt; docker cp ./test2.txt centos-01:/tmp/</span><br><span class="line"># 查看容器内目录</span><br><span class="line">docker exec -it centos-01 ls /tmp</span><br><span class="line">test.txt  test2.txt</span><br></pre></td></tr></table></figure><h1 id="联合文件系统"><a href="#联合文件系统" class="headerlink" title="联合文件系统"></a>联合文件系统</h1><h1 id="commit-镜像"><a href="#commit-镜像" class="headerlink" title="commit 镜像"></a>commit 镜像</h1><p>将一个容器生成一个新的镜像</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">docker commit 可选参数 容器ID 镜像名称[:tag]</span><br><span class="line"></span><br><span class="line"># 将一个容器生成一个本地镜像</span><br><span class="line">docker commit -a caoruiy -m &quot;test helloworld&quot; c4af83c1f703 hello-world-cr:v1.0.0</span><br></pre></td></tr></table></figure><h1 id="容器数据卷"><a href="#容器数据卷" class="headerlink" title="容器数据卷"></a>容器数据卷</h1><p>使用容器时，希望容器之间有一个数据共享的技术，Docker中产生的数据，可以同步到本地。可以将容器内的数据，挂载到本地。</p><p>这是一个容器数据持久化和同步的操作，使得容器间可以数据共享。</p><h2 id="使用方式一-v"><a href="#使用方式一-v" class="headerlink" title="使用方式一 -v"></a>使用方式一 -v</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">docker run -it -v 主机目录:容器目录 镜像 交互命令</span><br><span class="line"></span><br><span class="line"># 挂载的形式启动容器</span><br><span class="line"># 修改容器内容的文件，在主机上修改文件，两边均会同步</span><br><span class="line"># 如果容器停止，在本地上修改文件内容，启动容器后，容器内也会进行同步</span><br><span class="line">docker run -it -v /c/Users/Lenovo/Desktop/centos:/home centos /bin/bash</span><br><span class="line"># 容器内部操作文件</span><br><span class="line">[root@6b77aeb1d6de home]# cd /home</span><br><span class="line">[root@6b77aeb1d6de home]# mkdir test</span><br><span class="line"></span><br><span class="line"># 退出容器</span><br><span class="line">ctrl + p + q</span><br><span class="line"></span><br><span class="line"># 列出本地目录内容</span><br><span class="line">ls /c/Users/Lenovo/Desktop/centos</span><br><span class="line">test</span><br></pre></td></tr></table></figure><h3 id="具名挂载和匿名挂载"><a href="#具名挂载和匿名挂载" class="headerlink" title="具名挂载和匿名挂载"></a>具名挂载和匿名挂载</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"># 匿名挂载，挂载容器内的目录时，不指定具体的本地地址，本地卷名称</span><br><span class="line">docker run -it -v 容器目录 镜像 交互命令</span><br><span class="line"></span><br><span class="line"># 匿名挂载一个卷</span><br><span class="line">docker run -d -it -v /home centos /bin/sh</span><br><span class="line"></span><br><span class="line"># 查看docker 卷</span><br><span class="line">docker volume ls</span><br><span class="line"></span><br><span class="line">DRIVER    VOLUME NAME</span><br><span class="line">local     12d96dec13ff04dcc58d060d00bb01fcc3128102476160a8d79c0fa815de14b9</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"># 具名挂载，挂载容器内的目录时，指定一个卷名称</span><br><span class="line"># 卷名称就是一个字符串,不是一个 / 或者 ./ 的路径地址</span><br><span class="line">docker run -it -v 卷名称:容器目录 镜像 交互命令</span><br><span class="line"></span><br><span class="line"># 具名挂载</span><br><span class="line">docker run -d -it -v juming-cento:/home centos /bin/sh</span><br><span class="line"></span><br><span class="line"># 查看docker 卷</span><br><span class="line">docker volume ls</span><br><span class="line"></span><br><span class="line">DRIVER    VOLUME NAME</span><br><span class="line">local     12d96dec13ff04dcc58d060d00bb01fcc3128102476160a8d79c0fa815de14b9</span><br><span class="line">local     juming-cento</span><br></pre></td></tr></table></figure><p>匿名挂载和具名挂载，具体的挂载目录到底在哪里？</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"># 查看docker元信息</span><br><span class="line">docker inspect 433938cde9c0</span><br><span class="line"></span><br><span class="line"># 具名挂载时挂载信息输出</span><br><span class="line">&quot;Mounts&quot;: [</span><br><span class="line">  &#123;</span><br><span class="line">      &quot;Type&quot;: &quot;volume&quot;, // 类型,挂载</span><br><span class="line">      &quot;Name&quot;: &quot;juming-cento&quot;, // 挂载名称</span><br><span class="line">      &quot;Source&quot;: &quot;/var/lib/docker/volumes/juming-cento/_data&quot;, // 具体的本机挂载地址</span><br><span class="line">      &quot;Destination&quot;: &quot;/home&quot;, // 容器内地址</span><br><span class="line">      &quot;Driver&quot;: &quot;local&quot;,</span><br><span class="line">      &quot;Mode&quot;: &quot;z&quot;,</span><br><span class="line">      &quot;RW&quot;: true,</span><br><span class="line">      &quot;Propagation&quot;: &quot;&quot;</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"># 匿名挂载时挂载信息输出</span><br><span class="line">&quot;Mounts&quot;: [</span><br><span class="line">    &#123;</span><br><span class="line">        &quot;Type&quot;: &quot;volume&quot;,</span><br><span class="line">        &quot;Name&quot;: &quot;12d96dec13ff04dcc58d060d00bb01fcc3128102476160a8d79c0fa815de14b9&quot;,</span><br><span class="line">        &quot;Source&quot;: &quot;/var/lib/docker/volumes/12d96dec13ff04dcc58d060d00bb01fcc3128102476160a8d79c0fa815de14b9/_data&quot;,</span><br><span class="line">        &quot;Destination&quot;: &quot;/home&quot;,</span><br><span class="line">        &quot;Driver&quot;: &quot;local&quot;,</span><br><span class="line">        &quot;Mode&quot;: &quot;&quot;,</span><br><span class="line">        &quot;RW&quot;: true,</span><br><span class="line">        &quot;Propagation&quot;: &quot;&quot;</span><br><span class="line">    &#125;</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"># 加载点都在 /var/lib/docker/volumes/xxx/_data目录下</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="使用方式二-DockerFile"><a href="#使用方式二-DockerFile" class="headerlink" title="使用方式二 DockerFile"></a>使用方式二 DockerFile</h2><p>DockerFile是用来构建docker镜像的一个构建文件。脚本。</p><p><a href="https://docs.docker.com/engine/reference/builder/">https://docs.docker.com/engine/reference/builder/</a></p><h1 id="数据卷容器"><a href="#数据卷容器" class="headerlink" title="数据卷容器"></a>数据卷容器</h1><p>为了实现多个容器之间的数据共享，最好的方式就是让多个容器挂载到一个目录地址作为数据卷。所谓的数据卷容器，就是作为存放数据的容器，其他容器加载到该容器上，实现数据共享。</p><p><code>--volumes-from</code> 参数，可以从引用的容器中，挂载所有自定义的卷，需要注意的是“自定义的卷”。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"># 首先启动一个容器，并挂载一个卷</span><br><span class="line">docker run -it -name c1 -v ~/centos01:/centos01 centos /bin/sh</span><br><span class="line"></span><br><span class="line"># 在容器c1 centos01卷内新建一个目录11</span><br><span class="line">sh-4.4# cd centos01/</span><br><span class="line">sh-4.4# ls</span><br><span class="line">sh-4.4# mkdir 11</span><br><span class="line">sh-4.4# ls</span><br><span class="line">11</span><br><span class="line"></span><br><span class="line"># 退出容器，在本地目录centos01中发现相同内容，挂载成功</span><br><span class="line">[root@VM-16-13-centos ~]# ls</span><br><span class="line">centos01  test2.txt  test.txt</span><br><span class="line">[root@VM-16-13-centos ~]# ls centos01/</span><br><span class="line">11</span><br><span class="line"></span><br><span class="line"># 新建容器c2，c1作为数据卷容器</span><br><span class="line">docker run -it --name c2 --volumes-from c1 centos /bin/sh</span><br><span class="line"></span><br><span class="line"># 查看容器内挂载数据</span><br><span class="line">sh-4.4# cd centos01/</span><br><span class="line">sh-4.4# ls</span><br><span class="line">11</span><br><span class="line"></span><br><span class="line"># 在容器c2中centos01卷下，新建文件夹22</span><br><span class="line">sh-4.4# mkdir 22</span><br><span class="line">sh-4.4# ls</span><br><span class="line">11  22</span><br><span class="line"></span><br><span class="line"># 退出容器，查看本地数据</span><br><span class="line">[root@VM-16-13-centos ~]# ls centos01/</span><br><span class="line">11  22</span><br><span class="line"></span><br><span class="line"># 进入容器c1 查看数据</span><br><span class="line">[root@VM-16-13-centos ~]# docker exec -it c1 /bin/sh</span><br><span class="line">sh-4.4# ls centos01/</span><br><span class="line">11  22</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="/./learn-the-abc-of-docker/1657758523904.png" alt="1657758523904" loading="lazy"></p><p>删除数据卷容器c1，数据也不会丢失。<strong>共享卷实际是一个备份的概念。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"># 查看本地容器，一共有c1 c2两个容器</span><br><span class="line">[root@VM-16-13-centos ~]# docker ps</span><br><span class="line">CONTAINER ID   IMAGE     COMMAND     CREATED         STATUS         PORTS     NAMES</span><br><span class="line">cfe02ba04ad7   centos    &quot;/bin/sh&quot;   5 minutes ago   Up 5 minutes             c2</span><br><span class="line">f7d563151f92   centos    &quot;/bin/sh&quot;   6 minutes ago   Up 6 minutes             c1</span><br><span class="line"></span><br><span class="line"># 强制删除数据卷容器c1</span><br><span class="line">[root@VM-16-13-centos ~]# docker rm -f c1</span><br><span class="line">c1</span><br><span class="line"></span><br><span class="line">[root@VM-16-13-centos ~]# docker ps</span><br><span class="line">CONTAINER ID   IMAGE     COMMAND     CREATED         STATUS         PORTS     NAMES</span><br><span class="line">cfe02ba04ad7   centos    &quot;/bin/sh&quot;   5 minutes ago   Up 5 minutes             c2</span><br><span class="line"></span><br><span class="line"># 查看本地目录数据依然存在</span><br><span class="line">[root@VM-16-13-centos ~]# ls centos01/</span><br><span class="line">11  22</span><br><span class="line"></span><br><span class="line"># 容器c2中的数据依然存在</span><br><span class="line">[root@VM-16-13-centos ~]# docker exec -it c2 /bin/sh</span><br><span class="line">sh-4.4# ls centos01/</span><br><span class="line">11  22</span><br><span class="line"></span><br><span class="line"># 在容器c2中创建新目录33</span><br><span class="line">sh-4.4# mkdir centos01/33</span><br><span class="line">sh-4.4# ls centos01/</span><br><span class="line">11  22  33</span><br><span class="line">sh-4.4# read escape sequence</span><br><span class="line"></span><br><span class="line"># 退出容器后，查看本地目录，数据依然同步</span><br><span class="line">[root@VM-16-13-centos ~]# ls centos01/</span><br><span class="line">11  22  33</span><br></pre></td></tr></table></figure><p>数据卷容器可以做多个容器之间的数据共享，<strong>数据卷的生命周期直到没有容器使用为止</strong>。所以删除任意一个容器不影响数据卷的信息共享。</p><h1 id="docker-build"><a href="#docker-build" class="headerlink" title="docker build"></a>docker build</h1><p>从Dockerfile构建镜像</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">docker build [可选项] 向下文目录</span><br><span class="line"></span><br><span class="line"># 可选项</span><br><span class="line">-f, --file #Dockerfile的名称，不指定是默认是当前文件夹的Dickerfile文件</span><br><span class="line">-t, --tag </span><br></pre></td></tr></table></figure><h1 id="dockerignore"><a href="#dockerignore" class="headerlink" title=".dockerignore"></a>.dockerignore</h1><p>排除部分构建文件，防止将大文件或者敏感文件添加到构建上下文中。</p><p>每行一个目录或者文件地址，支持形式有</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># comment注释信息</span><br><span class="line">temp?排除根目录名称以temp开头的,后接单个字符的目录或文件, 如: /tempa</span><br><span class="line">*/temp*排除以temp开头的子目录或文件，如: /a/tempFile.txt  /a/tempDir</span><br><span class="line">*/*/temp*排除以temp开头的两级子目录或文件，如: /a/b/tempFile.txt  /a/b/tempDir</span><br><span class="line">**/tmp*排除所有目录中的以temp开头的目录或文件</span><br><span class="line">!temp*!表示排除例外，表示剔除根目录下以temp开头的目录或文件。</span><br></pre></td></tr></table></figure><p>基本原则为<code>?</code>匹配单个字符；<code>*</code>匹配多个字符。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># 以下写法的含义表示保留除了根目录下的以以temp开头的目录或文件外的，所有层级下的以temp开头的目录或文件</span><br><span class="line">**/tmp*</span><br><span class="line">!temp*</span><br><span class="line"></span><br><span class="line"># 示例: 除了/tempa 其他文件均会被剔除</span><br><span class="line">/tempa</span><br><span class="line">/tempb/a</span><br><span class="line">/a/tempc</span><br><span class="line">/a/b/tempd</span><br></pre></td></tr></table></figure><h1 id="DockerFile"><a href="#DockerFile" class="headerlink" title="DockerFile"></a>DockerFile</h1><p>docker file是用来构建docker镜像的文件，是一个命令脚本文件。</p><p>构建镜像的步骤：</p><ol><li>编写dockerfile文件</li><li>使用docker build 构建一个镜像</li><li>使用docker run运行进行</li><li>使用docker push 发布镜像</li></ol><h2 id="dockerFile指令"><a href="#dockerFile指令" class="headerlink" title="dockerFile指令"></a>dockerFile指令</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">ARG# 定义变量，提供给FROM使用</span><br><span class="line">FROM # 基础镜像，镜像构建开始位置</span><br><span class="line">MAINTAINER# 负责人，姓名+邮箱</span><br><span class="line">RUN# 进行构建时需要执行的命令</span><br><span class="line">ADD# 复制文件，往镜像中添加内容</span><br><span class="line">WORKDIR# 设置镜像的工作目录</span><br><span class="line">VOLUME# 挂载目录</span><br><span class="line">EXPOST# 对外暴露的端口</span><br><span class="line">RUN#</span><br><span class="line">CMD# 指定容器启动时候要运行的命令，相当于为容器执行提供默认值。只有最后一个会生效，可以被替代</span><br><span class="line">ENTRYPOINT# 指定容器启动时候要运行的命令，不可替代，可以追加</span><br><span class="line">ONBUILD# </span><br><span class="line">COPY# 类似ADD，拷贝内容到镜像中</span><br><span class="line">ENV# 构建时设置环境变量</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="RUN"><a href="#RUN" class="headerlink" title="RUN"></a>RUN</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"># 该命令支持两种写法，shell和exec，</span><br><span class="line"># shell形式将改变默认的shell，linux下默认是/bin/sh -c，window下默认是cmd /S /C</span><br><span class="line"># exec形式，因为可以避免shell字符串修改</span><br><span class="line"># RUN &lt;command&gt;# shell形式</span><br><span class="line"># RUN [&quot;executable&quot;, &quot;param1&quot;, &quot;param2&quot;]# exec形式</span><br><span class="line"></span><br><span class="line"># 可以使用\符号进行命令换行书写</span><br><span class="line">RUN /bin/sh -c &#x27;cd /home; \</span><br><span class="line">ls -al&#x27;</span><br><span class="line"># 等价于</span><br><span class="line">RUM /bin/sh -c &#x27;cd /home; ls -al&#x27;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 如果需要使用其他shell, 请使用exec形式</span><br><span class="line"># exec形式被解析为 JSON 数组，这意味着您必须在单词周围使用双引号 (&quot;) 而不是单引号 (&#x27;)</span><br><span class="line">RUN [&quot;/bin/bash&quot;, &quot;-c&quot;, &quot;cd /home&quot;, &quot;ls -al&quot;]</span><br></pre></td></tr></table></figure><blockquote><p>exec形式被解析为 JSON 数组，这意味着您必须在单词周围使用双引号 (“) 而不是单引号 (‘)</p></blockquote><blockquote><p>exec模式，不是直接调用命令，所以不会引用shell脚本命令，如果你希望启动时使用shell，可以明确指定hell。就像这样：RUN [“&#x2F;bin&#x2F;bash”, “-c”, “cd &#x2F;home”, “ls -al”]</p></blockquote><p>基于centos制作自己的镜像</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mkdir my-centos</span><br><span class="line">cd my-centos</span><br><span class="line">vim Dockerfile</span><br></pre></td></tr></table></figure><p>编写Dockerfile文件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">FROM centos</span><br><span class="line">RUN sed -i &#x27;s/mirrorlist/#mirrorlist/g&#x27; /etc/yum.repos.d/CentOS-*</span><br><span class="line">RUN sed -i &#x27;s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g&#x27; /etc/yum.repos.d/CentOS-*</span><br><span class="line">RUN yum clear</span><br><span class="line">RUN yum makecache</span><br><span class="line">RUN yum -y install wget</span><br><span class="line">RUN echo &#x27;---------------------over--------------------&#x27;</span><br></pre></td></tr></table></figure><p>生成镜像</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docekr build -t my-centyos .</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># 运行镜像</span><br><span class="line">docker run -it --name mc1 my-centos /bin/sh</span><br><span class="line"># 容器内执行,已经包含wget命令</span><br><span class="line">[root@8d8302624841 /]# wget</span><br><span class="line">wget: missing URL</span><br><span class="line">Usage: wget [OPTION]... [URL]...</span><br><span class="line"></span><br><span class="line">Try `wget --help&#x27; for more options.</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="CMD-和-ENTRYPOINT的区别"><a href="#CMD-和-ENTRYPOINT的区别" class="headerlink" title="CMD 和 ENTRYPOINT的区别"></a>CMD 和 ENTRYPOINT的区别</h1><p>CMD是执行运行的默认命令，当镜像运行时不指定任何命令时，默认的CMD命令会被执行，该指令可以在运行时被替换。</p><h2 id="CMD制作镜像"><a href="#CMD制作镜像" class="headerlink" title="CMD制作镜像"></a>CMD制作镜像</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">FROM centos</span><br><span class="line">RUN echo &#x27;This is a test image&#x27;</span><br><span class="line">CMD ls -a</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"># 编译生成镜像</span><br><span class="line">docker build -t my-centos .</span><br><span class="line"></span><br><span class="line"># 运行时不指定默认命令，将执行  ls -a</span><br><span class="line">docker run -it my-centos</span><br><span class="line">.   .dockerenv  dev  home  lib64       media  opt   root  sbin  sys  usr</span><br><span class="line">..  bin         etc  lib   lost+found  mnt    proc  run   srv   tmp  var</span><br><span class="line"></span><br><span class="line"># 运行时指定默认命令，执行信息被新命令覆盖</span><br><span class="line">[root@VM-16-13-centos my-centos]# docker run -it my-centos ls -al</span><br><span class="line">total 56</span><br><span class="line">drwxr-xr-x   1 root root 4096 Jul 14 06:28 .</span><br><span class="line">drwxr-xr-x   1 root root 4096 Jul 14 06:28 ..</span><br><span class="line">-rwxr-xr-x   1 root root    0 Jul 14 06:28 .dockerenv</span><br><span class="line">lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -&gt; usr/bin</span><br><span class="line">drwxr-xr-x   5 root root  360 Jul 14 06:28 dev</span><br><span class="line">drwxr-xr-x   1 root root 4096 Jul 14 06:28 etc</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 home</span><br><span class="line">lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -&gt; usr/lib</span><br><span class="line">lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -&gt; usr/lib64</span><br><span class="line">drwx------   2 root root 4096 Sep 15  2021 lost+found</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 media</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 opt</span><br><span class="line">dr-xr-xr-x 129 root root    0 Jul 14 06:28 proc</span><br><span class="line">dr-xr-x---   2 root root 4096 Sep 15  2021 root</span><br><span class="line">drwxr-xr-x  11 root root 4096 Sep 15  2021 run</span><br><span class="line">lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -&gt; usr/sbin</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 srv</span><br><span class="line">dr-xr-xr-x  13 root root    0 Jul 14 06:28 sys</span><br><span class="line">drwxrwxrwt   7 root root 4096 Sep 15  2021 tmp</span><br><span class="line">drwxr-xr-x  12 root root 4096 Sep 15  2021 usr</span><br><span class="line">drwxr-xr-x  20 root root 4096 Sep 15  2021 var</span><br></pre></td></tr></table></figure><h2 id="ENTRYPOINT制作镜像"><a href="#ENTRYPOINT制作镜像" class="headerlink" title="ENTRYPOINT制作镜像"></a>ENTRYPOINT制作镜像</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">FROM centos</span><br><span class="line">RUN echo &#x27;This is a test image&#x27;</span><br><span class="line">ENTRYPOINT [&quot;ls&quot;, &quot;-a&quot;]</span><br></pre></td></tr></table></figure><p>值得注意的是，此处的ENTRYPOINT写法是采用exec形式（[命令，参数，参数]）（ENTRYPOINT [“ls”, “-a”]）只有该形式，在运行镜像时才能追加参数。</p><p>如果采用shell命令形式（ENTRYPOINT 字符串）（ENTRYPOINT ls -a），他将在<code>/bin/sh -c</code>中执行，并会忽略docker run时的命令参数</p><p>exec 形式不会调用shell命令，这就意味着，使用该命令时，你无法通过命令行外壳进入容器，如想使用shell处理，可以这么写<code>ENTRYPOINT [ &quot;sh&quot;, &quot;-c&quot;, &quot;ls -a&quot; ]</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"># 生成镜像</span><br><span class="line">docker build -t entrypoint-centos .</span><br><span class="line"></span><br><span class="line"># 运行,默认命令</span><br><span class="line">docker run -it --name ec1 entrypoint-centos</span><br><span class="line">.   .dockerenv  dev  home  lib64       media  opt   root  sbin  sys  usr</span><br><span class="line">..  bin         etc  lib   lost+found  mnt    proc  run   srv   tmp  var</span><br><span class="line"></span><br><span class="line"># 运行,使用默认命令,追加参数</span><br><span class="line">docker run -it --name ec2 entrypoint-centos -l</span><br><span class="line">total 56</span><br><span class="line">drwxr-xr-x   1 root root 4096 Jul 14 06:43 .</span><br><span class="line">drwxr-xr-x   1 root root 4096 Jul 14 06:43 ..</span><br><span class="line">-rwxr-xr-x   1 root root    0 Jul 14 06:43 .dockerenv</span><br><span class="line">lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -&gt; usr/bin</span><br><span class="line">drwxr-xr-x   5 root root  360 Jul 14 06:43 dev</span><br><span class="line">drwxr-xr-x   1 root root 4096 Jul 14 06:43 etc</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 home</span><br><span class="line">lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -&gt; usr/lib</span><br><span class="line">lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -&gt; usr/lib64</span><br><span class="line">drwx------   2 root root 4096 Sep 15  2021 lost+found</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 media</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 opt</span><br><span class="line">dr-xr-xr-x 126 root root    0 Jul 14 06:43 proc</span><br><span class="line">dr-xr-x---   2 root root 4096 Sep 15  2021 root</span><br><span class="line">drwxr-xr-x  11 root root 4096 Sep 15  2021 run</span><br><span class="line">lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -&gt; usr/sbin</span><br><span class="line">drwxr-xr-x   2 root root 4096 Nov  3  2020 srv</span><br><span class="line">dr-xr-xr-x  13 root root    0 Jul 14 06:43 sys</span><br><span class="line">drwxrwxrwt   7 root root 4096 Sep 15  2021 tmp</span><br><span class="line">drwxr-xr-x  12 root root 4096 Sep 15  2021 usr</span><br><span class="line">drwxr-xr-x  20 root root 4096 Sep 15  2021 var</span><br></pre></td></tr></table></figure><h2 id="shell形式的ENTRYPOINT"><a href="#shell形式的ENTRYPOINT" class="headerlink" title="shell形式的ENTRYPOINT"></a>shell形式的ENTRYPOINT</h2><p>如果指定字符串形式的命令，该命令会在<code>/bin/sh -c</code>内执行，并会忽略命令行中的参数</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">FROM centos</span><br><span class="line">RUN echo &#x27;This is a test image&#x27;</span><br><span class="line">ENTRYPOINT ls -a</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># 运行,默认命令</span><br><span class="line">docker run -it --name ec1 entrypoint-centos</span><br><span class="line">.   .dockerenv  dev  home  lib64       media  opt   root  sbin  sys  usr</span><br><span class="line">..  bin         etc  lib   lost+found  mnt    proc  run   srv   tmp  var</span><br><span class="line"></span><br><span class="line"># 运行,使用默认命令,追加参数</span><br><span class="line">docker run -it --name ec2 entrypoint-centos -l</span><br><span class="line">.   .dockerenv  dev  home  lib64       media  opt   root  sbin  sys  usr</span><br><span class="line">..  bin         etc  lib   lost+found  mnt    proc  run   srv   tmp  var</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;docker基础知识点概要总结&lt;/p&gt;</summary>
    
    
    
    <category term="docker" scheme="https://blog.plcent.com/categories/docker/"/>
    
    
    <category term="docker" scheme="https://blog.plcent.com/tags/docker/"/>
    
  </entry>
  
  <entry>
    <title>使用Taro开发小程序指南</title>
    <link href="https://blog.plcent.com/taro-init-project/"/>
    <id>https://blog.plcent.com/taro-init-project/</id>
    <published>2022-04-16T15:31:14.000Z</published>
    <updated>2025-10-22T04:30:17.080Z</updated>
    
    <content type="html"><![CDATA[<p>小程序多端框架横向对比，介绍Taro的基础配置及相关资料导航</p><span id="more"></span><p><strong>阅读对象</strong>：首先需要阐明本文的受众是哪些人。因为文章只是罗列了一些 Taro 的资源，并未对实际的开发提供很多建议和深度的讲解，本文在编写之初，就默认你对小程序的开发有一定的了解，踩过一些坑，想换一种方式开发小程序，刚好你了解到 Taro，那本文对你是有价值的，方便你去找到一些和 Taro 相关的资料，加速入门。</p><hr><p>随着小程序的发展，现在主流厂商均有自己的小程序框架，如：<code>微信</code>、<code>京东</code>、<code>百度</code>、<code>支付宝</code>、<code>字节跳动</code>、<code>QQ</code>、<code>飞书</code>，虽然各端小程序开发遵循了微信小程序的开发模式，但是各家小程序又包含自己的特殊，并不能完全对齐。这导致同一套功能开发，需要兼容小程序以及 H5。</p><p>目前常见的开发模式有：</p><ol><li>针对每一个小程序做单独开发，研发投入成本较大；即原生开发；</li><li>开发 H5 版本的代码，利用小程序的 webview 加载 H5 的页面，从而屏蔽适配各家小程序的繁琐过程。例如微信的<code>kbone</code>；</li><li>使用多端开发框架，编写一套代码，通过框架编译成各家小程序代码；如：<code>Taro</code>、<code>uni-app</code>；</li></ol><p>本文介绍第三种开发模式，采用多端框架来开发小程序。市面上多端框架较多，如：<code>Taro</code>、<code>WePY</code> 、<code>uni-app</code>、<code>mpvue</code>、<code>chameleon</code>、<code>kbone</code>。那技术栈如何选型？</p><h2 id="小程序多端框架横向对比"><a href="#小程序多端框架横向对比" class="headerlink" title="小程序多端框架横向对比"></a>小程序多端框架横向对比</h2><p>市面上已经存在众多大牛对现存的小程序多端框架进行评测。这里给出几个比较好的评测文章。</p><p><a href="https://taro-docs.jd.com/taro/blog/2019-03-12-mini-program-framework-full-review">小程序框架全面测评（2019-03-12），来自 Taro 官方</a><br><a href="https://juejin.cn/post/6844904118901817351">跨端开发框架深度横评之 2020 版（2020-04-09），来自 uni-app 官方，掘金</a></p><p>这里需要提的是微信官方推出的<a href="https://wechat-miniprogram.github.io/kbone/docs/#%E4%BB%8B%E7%BB%8D">kbone</a>，它实现了一个适配器，在适配层里模拟出了浏览器环境，让 Web 端的代码可以不做什么改动便可运行在小程序里。如果你只需要支持微信小程序和 H5，毕竟是微信官方推出的，可以关注下这个解决方案。</p><p>截止目前来看，在小程序开发领域，国内开发者使用最多的应当是<code>Taro</code>、<code>uni-app</code>、<code>kbone</code>。其他开发框架已经逐渐被遗弃。就各家投入来看，各框架的版本迭代和修复 BUG 的效率都很不错，公司均有专门的团队。所以在采坑方面，目前不用太担心，出现问题官方修复速度都不错。</p><h2 id="如何使用-Taro"><a href="#如何使用-Taro" class="headerlink" title="如何使用 Taro"></a>如何使用 Taro</h2><p>如果你不了解<a href="https://taro-docs.jd.com/taro/docs">Taro</a>，可以在官网了解<a href="https://taro-docs.jd.com/taro/docs/">https://taro-docs.jd.com/taro/docs</a>。</p><p>官方提供了比较详细的教程告知如何初始化 Taro 项目，<a href="https://taro-docs.jd.com/taro/docs/GETTING-STARTED">Taro 安装及使用</a>，你可以按照<a href="https://taro-docs.jd.com/taro/docs/folder">基础教程</a>&gt;<a href="https://taro-docs.jd.com/taro/docs/config-detail">进阶教程</a>的方式进行入门。</p><p>当然官方也有入门教程可以参考<a href="https://taro-docs.jd.com/taro/docs/guide">Taro 渐进式入门教程</a>，看完基本了解如何使用 Taro 了。</p><p>其中你需要了解 Taro 的<a href="https://taro-docs.jd.com/taro/docs/config">编译配置</a>，以及 Taro 如何定义<a href="https://taro-docs.jd.com/taro/docs/size">设计稿及尺寸单位</a>。</p><h3 id="编译配置"><a href="#编译配置" class="headerlink" title="编译配置"></a>编译配置</h3><p>编译配置存放于项目根目录下的 config 目录中，包含三个文件：</p><ul><li>index.js 是通用配置</li><li>dev.js 是项目预览时的配置</li><li>prod.js 是项目打包时的配置</li></ul><p>详细的编译配置参数参见<a href="https://taro-docs.jd.com/taro/docs/config-detail">编译配置详情</a>。按照文档介绍配置项目即可。</p><p>其中需要说明的是，此处的配置是针对 Trao 的编译打包行为进行的配置。在小程序开发中，各大平台通常会对小程序的包大小进行限制。例如：</p><ul><li>微信小程序限制单包大小不得超过 2M，总包不得超过 20M。<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html">微信小程序开发文档-分包加载</a></li><li>支付宝小程序单包大小不得超过 2M，总包不得超过 8M。<a href="https://opendocs.alipay.com/mini/framework/subpackages#%E5%88%86%E5%8C%85%E5%A4%A7%E5%B0%8F%E9%99%90%E5%88%B6">支付宝小程序开发文档-分包大小限制</a></li><li>字节小程序单包大小不得超过 2M，总包不得超过 16M。<a href="https://microapp.bytedance.com/docs/zh-CN/mini-app/develop/framework/subpackages/introduction">字节小程序开发温暖的-分包简介</a></li></ul><p>在这种情况下，Taro 编译完成后，主包很容易就会超过 2M 的限制。常见的方式是：</p><ul><li>移除包中的静态资源，改成服务器加载，例如图片上传到 CDN</li><li>压缩代码</li></ul><h4 id="使用-terser-webpack-plugin-压缩代码"><a href="#使用-terser-webpack-plugin-压缩代码" class="headerlink" title="使用 terser-webpack-plugin 压缩代码"></a>使用 terser-webpack-plugin 压缩代码</h4><p>在<code>/config/dev.js</code>中添加以下配置</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">TerserPlugin</span> = <span class="built_in">require</span>(<span class="string">&quot;terser-webpack-plugin&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">mini</span>: &#123;</span><br><span class="line">    <span class="attr">webpackChain</span>: <span class="function">(<span class="params">chain</span>) =&gt;</span> &#123;</span><br><span class="line">      chain.<span class="title function_">merge</span>(&#123;</span><br><span class="line">        <span class="attr">optimization</span>: &#123;</span><br><span class="line">          <span class="attr">minimize</span>: <span class="literal">true</span>,</span><br><span class="line">          <span class="attr">minimizer</span>: [</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">TerserPlugin</span>(&#123;</span><br><span class="line">              <span class="attr">test</span>: [<span class="string">&quot;common.js&quot;</span>, <span class="string">&quot;taro.js&quot;</span>, <span class="string">&quot;vendors.js&quot;</span>, <span class="string">&quot;app.js&quot;</span>], <span class="comment">// 参与压缩的文件</span></span><br><span class="line">            &#125;),</span><br><span class="line">          ],</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>在 Taro 编译的过程中，还需要一个配置文件，用来告诉 Taro，编译成各端小程序，需要依照何种规则进行编译。</p><h3 id="设计稿及尺寸单位"><a href="#设计稿及尺寸单位" class="headerlink" title="设计稿及尺寸单位"></a>设计稿及尺寸单位</h3><p>Taro 默认以 750px 作为换算尺寸标准，如果设计稿不是以 750px 为标准，则需要在项目配置 config&#x2F;index.js 中进行设置。所以在项目设计之初，最好和设计人员确认，以 Iphon6 作为标准尺寸进行设计。</p><p>或许你会好奇，为何移动端会以 750px 作为设计标准，你可以阅读<br><a href="https://blog.csdn.net/weixin_45785873/article/details/106948607">移动开发的设计稿为什么大多数是 750px</a>。<br><a href="https://www.jianshu.com/p/cf600c2930cb">移动端 Web 页面适配浅析</a><br><a href="https://juejin.cn/post/6844903951012200456#heading-24">深入浅出移动端适配（总结版）</a></p><p>总之，移动端开发在单位处理上是个大坑，但是好在 Taro 帮我们处理了这些问题，你只需要根据设计稿标注的尺寸进行代码编写即可。即从设计稿上量的长度 100px，那么尺寸书写就是 100px，当转成微信小程序的时候，尺寸将默认转换为 100rpx，当转成 H5 时将默认转换为以 rem 为单位的值。这一切都是透明的。</p><p>你需要如下定义</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// /config/index.js</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="attr">designWidth</span>: <span class="number">750</span>, <span class="comment">// 设计稿尺寸</span></span><br><span class="line">  <span class="attr">deviceRatio</span>: &#123; <span class="comment">// 针对不同设计稿尺寸的处理换算规则</span></span><br><span class="line">    <span class="number">640</span>: <span class="number">2.34</span> / <span class="number">2</span>,</span><br><span class="line">    <span class="number">750</span>: <span class="number">1</span>,</span><br><span class="line">    <span class="number">828</span>: <span class="number">1.81</span> / <span class="number">2</span>,</span><br><span class="line">    <span class="number">375</span>: <span class="number">2</span> / <span class="number">1</span></span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如果你不希望转码单位，可以大写字母的 Px 或 PX 这会被 Taro 会被忽略。</p><h2 id="Vue-的支持"><a href="#Vue-的支持" class="headerlink" title="Vue 的支持"></a>Vue 的支持</h2><p>Taro 支持使用 Vue&#x2F;Vue3 的语法开发，但是并不是完全支持。<br>主要的差别有：</p><ul><li>事件，使用<code>@tap</code>替代<code>@click</code></li><li>在 Vue 中使用 jsx 时，事件名称的首字母需要大写，例如 onGetphonenumber</li><li>无法使用 stopPropagation<a href="https://taro-docs.jd.com/taro/docs/vue-overall#%E9%98%BB%E6%AD%A2%E6%BB%9A%E5%8A%A8%E7%A9%BF%E9%80%8F">阻止滚动穿透</a></li></ul><blockquote><p>经过测试，<code>@tap=&quot;e =&gt; {e.stopPropagation(); handleTapEvent(); }&quot;</code> 这种写法可以阻止冒泡</p></blockquote><ul><li>Taro 中 <a href="https://taro-docs.jd.com/taro/docs/vue-overall#ref">ref</a> 存在差别，无法获取大大小信息</li><li>不支持 <code>&lt;style scoped&gt;</code>，需要保证各个页面定义的样式不会相互影响，官方建议使用 cssModules 代替。<a href="https://github.com/NervJS/taro/issues/6662">#6662</a>。简单的方式可以使用 scss，每个页面均定义一个和页面同名的 css 父类，该页面的所有样式均写在该样式内，通过<code>namespace</code>的方式进行屏蔽。</li><li>不支持 vue-router，可以使用官方的<a href="https://taro-docs.jd.com/taro/docs/router">路由</a>方案</li></ul><p>官方列出了一个不能完全兼容 Vue 的情况。参见<a href="https://taro-docs.jd.com/taro/docs/vue3#%E5%85%B6%E5%AE%83%E9%99%90%E5%88%B6">其他限制</a></p><h2 id="如何选择-UI-框架"><a href="#如何选择-UI-框架" class="headerlink" title="如何选择 UI 框架"></a>如何选择 UI 框架</h2><p>Taro 内置封装了小程序提供的原生组件功能，你可以使用 Taro 的方式调用原生组件。</p><p>由于 Taro 的工作原理，导致 web 的生态无法在 taro 中完全使用，需要针对 Taro 做定制化开发。UI 也是，好在现在有比较优秀的第三方的 UI 框架可以选择。</p><h3 id="NutUI"><a href="#NutUI" class="headerlink" title="NutUI"></a>NutUI</h3><p><a href="https://nutui.jd.com/#/intro">NutUI 3.0</a></p><p>京东官方出品的 UI 框架，截止 2022 年 4 月 17 号，最新版本为<a href="https://github.com/jdf2e/nutui/releases/tag/v3.1.18">v3.1.18</a>。UI 风格是京东商城的风格，支持自定义主题，组件丰富，有很多商城特有组件，例如地址，商品卡片等，问题解决速度很快。</p><h3 id="taro-ui-vue3"><a href="#taro-ui-vue3" class="headerlink" title="taro-ui-vue3"></a>taro-ui-vue3</h3><p><a href="https://b2nil.github.io/taro-ui-vue3/">taro-ui-vue3</a></p><p>taro-ui-vue3 是一款基于 Taro 框架开发, 并采用 Vue 3.0 重写的 Taro UI 组件库。组件功能丰富，常用开发均可以支持。</p><h3 id="Taroify"><a href="#Taroify" class="headerlink" title="Taroify"></a>Taroify</h3><p><a href="https://taroify.gitee.io/taroify.com/introduce/">Taroify</a></p><p>Taroify 是移动端组件库 <a href="https://github.com/youzan/vant">Vant</a> 的 Taro React 版本，两者基于相同的视觉规范，提供近似一致的 API 接口，助力开发者快速搭建小程序应用。如果你之前习惯<a href="https://github.com/youzan/vant">Vant</a>进行开发，可以尝试。</p><h3 id="taro-color-ui"><a href="#taro-color-ui" class="headerlink" title="taro-color-ui"></a>taro-color-ui</h3><p><a href="https://gengar-666.github.io/taro-color-ui/#/">taro-color-ui</a></p><p>color-ui 是之前使用经验就是需要下载官方的 demo 进行魔改，虽然很好看但是不是很方便，taro 版本提供了简单的方式使用，非大团队支持，完善度还有待提升。尝鲜可以使用，可以应付常见开发需求。</p><h2 id="Taro-物料市场"><a href="#Taro-物料市场" class="headerlink" title="Taro 物料市场"></a>Taro 物料市场</h2><p><a href="https://taro-ext.jd.com/">Taro 物料市场</a></p><p>taro 为了丰富生态，创建的物料市场，你可以在市场中找到一些现有的解决方法，目前内容不是很多，现有工具如果出现问题，需要自己下载源码进行魔改。</p><h3 id="Taro-社区"><a href="#Taro-社区" class="headerlink" title="Taro 社区"></a>Taro 社区</h3><p><a href="https://taro-club.jd.com/">Taro 社区</a></p><p>可以在社区中查找常见问题的处理方法</p><h2 id="结束语"><a href="#结束语" class="headerlink" title="结束语"></a>结束语</h2><p>Taro 最为目前比较优秀的解决方法，虽然有其不足之处，但也为小程序的开发提供了一种新的开发体验。</p><p>借助<code>kbone</code>文档的一句话来说，每个方案都有自己的优劣，不存在能够完美解决所有问题的方案。但是，在特定的需求下，选择自己合适的方案，会让开发效率成倍的提升。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;小程序多端框架横向对比，介绍Taro的基础配置及相关资料导航&lt;/p&gt;</summary>
    
    
    
    <category term="taro" scheme="https://blog.plcent.com/categories/taro/"/>
    
    
    <category term="taro" scheme="https://blog.plcent.com/tags/taro/"/>
    
    <category term="wechat" scheme="https://blog.plcent.com/tags/wechat/"/>
    
    <category term="miniprograme" scheme="https://blog.plcent.com/tags/miniprograme/"/>
    
  </entry>
  
  <entry>
    <title>fetch用法</title>
    <link href="https://blog.plcent.com/fetch-api/"/>
    <id>https://blog.plcent.com/fetch-api/</id>
    <published>2021-09-07T06:52:03.000Z</published>
    <updated>2025-10-22T04:32:15.438Z</updated>
    
    <content type="html"><![CDATA[<p>这篇文章系统梳理了JavaScript中Fetch API的核心用法，涵盖语法、参数配置及关键注意事项，为实际请求调用提供清晰指引。</p><span id="more"></span><h1 id="Fetch-API"><a href="#Fetch-API" class="headerlink" title="Fetch API"></a>Fetch API</h1><p>详尽的MDN文档：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API">https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API</a></p><p>使用Fetch：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch">https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API&#x2F;Using_Fetch</a></p><h2 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Promise</span>&lt;<span class="title class_">Response</span>&gt; <span class="title function_">fetch</span>(input[, init]);</span><br></pre></td></tr></table></figure><h4 id="input"><a href="#input" class="headerlink" title="input &lt;String | Request&gt;"></a>input &lt;String | <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Request"><code>Request</code></a>&gt;</h4><p>定义要获取的资源。他接受一个字符串或者一个<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Request"><code>Request</code></a>对象。<code>Request()</code> 和 <code>fetch()</code> 接受同样的参数。你可以这样使用：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> request = <span class="keyword">new</span> <span class="title class_">Request</span>(<span class="string">&#x27;xxx.png&#x27;</span>, init)</span><br><span class="line"><span class="title function_">fetch</span>(request)</span><br><span class="line"></span><br><span class="line"># 等价于</span><br><span class="line"><span class="title function_">fetch</span>(<span class="string">&#x27;xxx.png&#x27;</span>, init)</span><br></pre></td></tr></table></figure><h4 id="init-可选"><a href="#init-可选" class="headerlink" title="init 可选"></a>init <code>可选</code></h4><p>一个配置参数对象，可选的配置项包括：</p><ul><li><p><code>method</code>：请求方式，<code>GET</code>、<code>POST</code>、<code>DELETE</code>、<code>PUT</code>等</p></li><li><p><code>headers</code>：请求头。形式为 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Headers"><code>Headers</code></a> 的对象 或 一个对象。大概形式如下：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> headers = <span class="keyword">new</span> <span class="title class_">Headers</span>()</span><br><span class="line">headers.<span class="title function_">append</span>(<span class="string">&#x27;content-type&#x27;</span>, <span class="string">&#x27;application/json&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="title function_">fetch</span>(input, &#123;</span><br><span class="line"><span class="attr">headers</span>: headers</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">fetch</span>(input, &#123;</span><br><span class="line"><span class="attr">headers</span>: &#123;</span><br><span class="line">        content-<span class="attr">type</span>: <span class="string">&#x27;application/json&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure></li><li><p><code>body</code>：请求体。可能是一个 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Blob"><code>Blob</code></a>、<a href="https://developer.mozilla.org/en-US/docs/Web/API/BufferSource"><code>BufferSource</code> (en-US)</a>、<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/FormData"><code>FormData</code></a>、<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams"><code>URLSearchParams</code></a> 或者 <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/USVString"><code>USVString</code></a> 对象（说白了就是字符串）。注意 GET 或 HEAD 方法的请求不能包含 body 信息。</p><blockquote><p>正常的<code>POST</code>请求中，<code>body</code>入参是一个字符串，所以发送一个<code>JSON</code>对象需要经过<code>JSON.stringify</code>处理。在<code>GET</code>、 <code>HEAD</code>请求中，不可以指定<code>body</code>参数，否则会报错。</p></blockquote></li><li><p><code>mode</code>: 请求跨域设置。接受以下数据枚举： <code>cors</code>、 <code>no-cors</code>或者 <code>same-origin（默认值）</code></p><ul><li><code>same-origin（默认值）</code>：该模式是不允许跨域的，它需要遵守同源策略，否则浏览器会返回一个error告知不能跨域；其对应的<code>response.type</code>为<code>basic</code>。</li><li><code>cors</code>：该模式支持跨域请求，顾名思义它是以CORS的形式跨域；当然该模式也可以同域请求不需要后端额外的CORS支持；其对应的<code>response.type</code>为<code>cors</code>。</li><li><code>no-cors</code>：该模式用于跨域请求但是服务器不带CORS响应头，也就是服务端不支持CORS；这也是fetch的特殊跨域请求方式；其对应的<code>response.type</code>为<code>opaque</code>。</li></ul><blockquote><p>设置该字段，会被赋值到请求头字段<code>Sec-Fetch-Mode</code>中，根据设置字段的不同，在响应对象<code>response.type</code>中会返回不同的信息</p></blockquote></li><li><p><code>credentials</code>：请求cookie。接受以下数据枚举：<code>omit</code>（默认值）、<code>same-origin</code>或者 <code>include</code>。</p><blockquote><p>（自 2017 年 8 月 25 日以后，默认的 credentials 政策变更为 <code>same-origin</code>。Firefox 也在 61.0b13 版本中进行了修改，参见：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Request/credentials">Request.credentials</a>）。为了保证各个版本的一致性，建议使用是明确指定credentials。</p><p>注：fetch-polyfill whatwg-fetch采用默认值<code>same-origin</code>：<a href="https://github.com/github/fetch/blob/d1d09fb8039b4b8c7f2f5d6c844ea72d8a3cefe6/fetch.js#L367">fetch.js#L367</a></p></blockquote><ul><li><code>omit</code>：从不发送cookies</li><li><code>same-origin</code>：只有当URL与响应脚本同源才发送 cookies、 HTTP Basic authentication 等验证信息。(浏览器默认值,在旧版本浏览器，例如safari 11依旧是omit，safari 12已更改)</li><li><code>include</code>：不论是不是跨域的请求，总是发送请求资源域在本地的 cookies、 HTTP Basic authentication 等验证信息。 ( 推荐使用)</li></ul></li><li><p><code>cache</code>：请求的 cache 模式。接受以下数据枚举： <code>default</code>、 <code>no-store</code>、 <code>reload</code> 、 <code>no-cache </code>、 <code>force-cache </code>或者 <code>only-if-cached</code> 。</p><blockquote><p>详细参见MDN说明：<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Request/cache">Fetch Request Cache</a>、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control">HTTP Headers Cache-Control</a></p></blockquote><ul><li><code>default</code>：表示请求时不传 <code>Cache-Control</code> 这个标头。</li><li><code>reload</code>：表示本次请求忽略浏览器已经有的缓存（相当于 Ctrl + R 强制刷新），但本次请求的结果还是会遵循响应的 <code>Cache-Control</code> 标头的值来进行缓存存储。跟 <code>no-store</code> 的不同点在于 <code>no-store</code> 本次请求强制刷新了，下次如果另一个请求 <code>Cache-Control</code> 再指定成别的值比如 <code>only-if-cached</code>，完全不会命中缓存，因为 <code>no-store</code> 压根没把响应结果存在本地；而 <code>reload</code> 第一次强制刷新，第二次是的 <code>only-if-cached</code> 之类的就会命中缓存。</li></ul></li><li><p><code>redirect</code>：重定向设置。<code>follow</code> (自动重定向)、<code>error</code> (如果产生重定向将自动终止并且抛出一个错误）、<code>manual</code> (手动处理重定向)。在Chrome中默认使用<code>follow（</code>Chrome 47之前的默认值是<code>manual</code>）。</p><ul><li><code>follow</code>：默认值，<code>fetch()</code>跟随 HTTP 跳转。</li><li><code>error</code>：如果发生跳转，<code>fetch()</code>就报错。</li><li><code>manual</code>：<code>fetch()</code>不跟随 HTTP 跳转，但是<code>response.url</code>属性会指向新的 URL，<code>response.redirected</code>属性会变为<code>true</code>，由开发者自己决定后续如何处理跳转。</li></ul></li><li><p><code>referrer</code>：请求的引用者设置。可以为任意字符串，如果<code>referrer</code>的值为空字符串，则不发送referrer表头。</p></li><li><p><code>referrerPolicy</code>：指定了HTTP头部referer字段的值。可能为以下值之一： <code>no-referrer</code>、 <code>no-referrer-when-downgrade</code> 、<code>origin</code>、 <code>origin-when-cross-origin</code>、 <code>unsafe-url </code>。</p><ul><li><code>no-referrer-when-downgrade</code>：默认值，总是发送<code>Referer</code>标头，除非从 HTTPS 页面请求 HTTP 资源时不发送。</li><li><code>no-referrer</code>：不发送<code>Referer</code>标头。</li><li><code>origin</code>：<code>Referer</code>标头只包含域名，不包含完整的路径。</li><li><code>origin-when-cross-origin</code>：同源请求<code>Referer</code>标头包含完整的路径，跨域请求只包含域名。</li><li><code>same-origin</code>：跨域请求不发送<code>Referer</code>，同源请求发送。</li><li><code>strict-origin</code>：<code>Referer</code>标头只包含域名，HTTPS 页面请求 HTTP 资源时不发送<code>Referer</code>标头。</li><li><code>strict-origin-when-cross-origin</code>：同源请求时<code>Referer</code>标头包含完整路径，跨域请求时只包含域名，HTTPS 页面请求 HTTP 资源时不发送该标头。</li><li><code>unsafe-url</code>：不管什么情况，总是发送<code>Referer</code>标头。</li></ul></li></ul><blockquote><p>由于fetch接受Request对象作为入参，Request的所有参数均可以作为fetch的初始化参数进行使用，详细参数使用可以参见<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Request">Request</a>文档</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;这篇文章系统梳理了JavaScript中Fetch API的核心用法，涵盖语法、参数配置及关键注意事项，为实际请求调用提供清晰指引。&lt;/p&gt;</summary>
    
    
    
    <category term="javascript" scheme="https://blog.plcent.com/categories/javascript/"/>
    
    
    <category term="fetch" scheme="https://blog.plcent.com/tags/fetch/"/>
    
    <category term="javascript" scheme="https://blog.plcent.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>mysql-数据迁移</title>
    <link href="https://blog.plcent.com/mysql-dump-source/"/>
    <id>https://blog.plcent.com/mysql-dump-source/</id>
    <published>2021-09-01T06:50:35.000Z</published>
    <updated>2025-10-22T04:29:01.219Z</updated>
    
    <content type="html"><![CDATA[<p>简单介绍mysql自带数据备份工具mysqldump和数据导入</p><span id="more"></span><h1 id="mysql数据导入导出"><a href="#mysql数据导入导出" class="headerlink" title="mysql数据导入导出"></a>mysql数据导入导出</h1><h2 id="mysqldump"><a href="#mysqldump" class="headerlink" title="mysqldump"></a>mysqldump</h2><p><code>mysqldump</code> 是 <code>MySQL</code> 自带的逻辑备份工具。</p><p>它的备份原理是通过协议连接到 <code>MySQL</code> 数据库，将需要备份的数据查询出来，将查询出的数据转换成对应的<code>insert</code> 语句，当我们需要还原这些数据时，只要执行这些 <code>insert</code> 语句，即可将对应的数据还原。</p><p><code>mysqldump</code>优点包括在恢复之前查看甚至编辑输出的便利性和灵活性。您可以克隆用于开发和 DBA 工作的数据库，或生成现有数据库的细微变化以进行测试。它不是用于备份大量数据的快速或可扩展的解决方案。对于大数据量，即使备份步骤花费合理的时间，恢复数据也可能非常缓慢，因为重放 SQL 语句涉及用于插入、索引创建等的磁盘 I&#x2F;O。</p><p>mysql 官方文档 <a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html">https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html</a></p><h3 id="命令格式"><a href="#命令格式" class="headerlink" title="命令格式"></a>命令格式</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mysqldump [options] db_name [tbl_name ...]</span><br><span class="line">mysqldump [options] --databases db_name ...</span><br><span class="line">mysqldump [options] --all-databases</span><br></pre></td></tr></table></figure><h3 id="常用选项说明"><a href="#常用选项说明" class="headerlink" title="常用选项说明"></a>常用选项说明</h3><table><thead><tr><th>参数名</th><th>缩写</th><th>含义</th></tr></thead><tbody><tr><td>–host</td><td>-h</td><td>服务器IP地址</td></tr><tr><td>–port</td><td>-P</td><td>服务器端口号</td></tr><tr><td>–user</td><td>-u</td><td>MySQL 用户名</td></tr><tr><td>–pasword</td><td>-p</td><td>MySQL 密码</td></tr><tr><td>–databases</td><td></td><td>指定要备份的数据库</td></tr><tr><td>–all-databases</td><td></td><td>备份mysql服务器上的所有数据库</td></tr><tr><td><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_add-drop-database"><code>--add-drop-database</code></a></td><td></td><td>在每个 CREATE DATABASE 语句之前添加 DROP DATABASE 语句</td></tr><tr><td><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_add-drop-table">–add-drop-table</a></td><td></td><td>在每个 CREATE TABLE 语句之前添加 DROP TABLE 语句。默认添加drop语句</td></tr><tr><td><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_opt">–opt</a></td><td></td><td>–add-drop-table –add-locks –create-options –disable-keys –extended-insert –lock-tables –quick –set-charset 语句的简写。该选项默认启用。</td></tr><tr><td><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_add-drop-table">–skip-add-drop-table</a></td><td></td><td>不要在每个 CREATE TABLE 语句之前添加 DROP TABLE 语句</td></tr><tr><td><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_extended-insert">–extended-insert</a></td><td></td><td>使用多行 INSERT 语法。输出一条insert语句</td></tr><tr><td><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_extended-insert">–skip-extended-insert</a></td><td></td><td>关闭–extended-insert。输出多条insert语句</td></tr><tr><td>–compact</td><td></td><td>压缩模式，产生更少的输出</td></tr><tr><td>–comments</td><td></td><td>添加注释信息</td></tr><tr><td>–complete-insert</td><td></td><td>输出完成的插入语句</td></tr><tr><td>–lock-tables</td><td>-l</td><td>备份前，锁定所有数据库表</td></tr><tr><td>–no-create-db&#x2F;–no-create-info</td><td></td><td>禁止生成创建数据库语句</td></tr><tr><td>–no-data</td><td></td><td>不写入任何表行信息（即不转储表内容）。如果您只想转储<a href="https://dev.mysql.com/doc/refman/5.6/en/create-table.html"><code>CREATE TABLE</code></a>表的语句</td></tr><tr><td>–force</td><td></td><td>当出现错误时仍然继续备份操作</td></tr><tr><td>–default-character-set</td><td></td><td>指定默认字符集</td></tr><tr><td><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_add-locks">–add-locks</a></td><td></td><td>备份数据库表时锁定数据库表。生产环境慎用</td></tr><tr><td>–where&#x3D;’<em><code>where_condition</code></em>‘</td><td>-w</td><td>仅转储由给定<code>WHERE</code>条件选择的行 。</td></tr><tr><td>–quick<code>, </code>-q</td><td>-q</td><td>一次一行地从服务器检索表的行</td></tr><tr><td><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_single-transaction">–single-transaction</a></td><td></td><td>在从服务器转储数据之前发出 BEGIN SQL 语句。一致性备份</td></tr><tr><td>–skip-opt</td><td></td><td>关闭由 –opt 设置的选项。避免锁表备份</td></tr><tr><td>–result-file</td><td>&gt;</td><td>导出结果输出到文件</td></tr></tbody></table><p>全部选项参见<a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html">https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html</a></p><h3 id="常见示例"><a href="#常见示例" class="headerlink" title="常见示例"></a>常见示例</h3><ol><li>导出所有数据库</li></ol><p>该命令会导出mysql中所有的数据库内容，如果你是全表备份，</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqldump -u用户名 -p密码 --all-databases &gt; ~/all.sql</span><br></pre></td></tr></table></figure><ol start="2"><li>导出指定数据库</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqldump -u用户名 -p密码 --databases db1 &gt; ~/db1.sql</span><br></pre></td></tr></table></figure><p>该<a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_databases"><code>--databases</code></a>选项使命令行上的所有名称都被视为数据库名称。如果没有此选项，<a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html"><strong>mysqldump</strong></a>将第一个名称视为数据库名称，将后面的名称视为表名称。</p><ol start="3"><li>导出指定数据库的指定表</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqldump -u用户名 -p密码 databaseName tableName --single-transaction --set-gtid-purged=OFF &gt; ~/tableName.sql</span><br></pre></td></tr></table></figure><ol start="4"><li>导出数据时指定条件–where</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 只导出ID&gt;10的记录</span><br><span class="line">mysqldump -u用户名 -p密码 databaseName tableName --single-transaction --set-gtid-purged=OFF --where=&quot;id&gt;10&quot; &gt; ~/tableName.sql</span><br></pre></td></tr></table></figure><h3 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h3><h4 id="避免锁表"><a href="#避免锁表" class="headerlink" title="避免锁表"></a>避免锁表</h4><p>默认mysqldump备份会<code>lock-tables</code>，对于线上服务，锁表会影响线上业务。mysqldump提供了几种方式来避免备份是锁表</p><h5 id="–single-transaction"><a href="#–single-transaction" class="headerlink" title="–single-transaction"></a>–single-transaction</h5><p><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_single-transaction">–single-transaction</a>是针对innodb引擎的，备份一致性选项，通过事务来保证数据的一致性。</p><h5 id="–skip-opt"><a href="#–skip-opt" class="headerlink" title="–skip-opt"></a>–skip-opt</h5><p>由于<a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_opt">–opt</a>选项默认启用，因此您只需指定其相反的选项 <a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_skip-opt"><code>--skip-opt</code></a>即可关闭几个默认设置。</p><h5 id="–skip-lock-tables"><a href="#–skip-lock-tables" class="headerlink" title="–skip-lock-tables"></a>–skip-lock-tables</h5><p>使用<code>--opt</code>选项时，会自动启动<code>--lock-tables</code>，如果你不想锁表操作，可以指定<code>--skip-opt</code>或者追加<code>--skip-lock-tables</code>属性来覆盖它。</p><h4 id="一条记录输出一条insert语句"><a href="#一条记录输出一条insert语句" class="headerlink" title="一条记录输出一条insert语句"></a>一条记录输出一条insert语句</h4><p><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_extended-insert">–skip-extended-insert</a> 语句可以关闭默认的多行 INSERT 语法。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqldump -u用户名 -p密码 --single-transaction --quick --set-gtid-purged=OFF --skip-extended-insert databaseName tableName &gt; ~/tableName.sql</span><br></pre></td></tr></table></figure><h4 id="转储大表"><a href="#转储大表" class="headerlink" title="转储大表"></a>转储大表</h4><p><a href="https://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_quick">–quick</a> 该选项用于转储大的表。它强制<strong>mysqldump</strong>从服务器一次一行地检索表中的行而不是检索所有行并在输出前将它缓存到内存中。</p><h3 id="导入"><a href="#导入" class="headerlink" title="导入"></a>导入</h3><h4 id="重新导入有mysqldump导出的SQL文件"><a href="#重新导入有mysqldump导出的SQL文件" class="headerlink" title="重新导入有mysqldump导出的SQL文件"></a>重新导入有mysqldump导出的SQL文件</h4><ol><li>直接通过mysql导入</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果dump.sql脚本中包含CREATE_DATABASE和USE语句，可以直接导入sql</span></span><br><span class="line"><span class="meta prompt_">shell&gt; </span><span class="language-bash">mysql &lt; dump.sql</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果不存在，在加载转储文件时指定数据库名称</span></span><br><span class="line"><span class="meta prompt_">shell&gt; </span><span class="language-bash">mysql db1 &lt; dump.sql</span></span><br></pre></td></tr></table></figure><ol start="2"><li>使用source命令</li></ol><p>进入mysql命令行，使用mysql中的source命令导入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; source dump.sql</span><br></pre></td></tr></table></figure><p>如果文件不包含<code>CREATE_DATABASE</code>和<code>USE</code>语句，需要提前创建数据库</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">shell&gt; </span><span class="language-bash">mysqladmin create db1</span></span><br></pre></td></tr></table></figure><p>或者</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; CREATE DATABASE IF NOT EXISTS db1;</span><br><span class="line">mysql&gt; USE db1;</span><br><span class="line">mysql&gt; source dump.sql</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;简单介绍mysql自带数据备份工具mysqldump和数据导入&lt;/p&gt;</summary>
    
    
    
    <category term="mysq" scheme="https://blog.plcent.com/categories/mysq/"/>
    
    
    <category term="mysql" scheme="https://blog.plcent.com/tags/mysql/"/>
    
  </entry>
  
  <entry>
    <title>vuepress学习系列/3/默认主题配置</title>
    <link href="https://blog.plcent.com/vuepress-03-default-theme-config/"/>
    <id>https://blog.plcent.com/vuepress-03-default-theme-config/</id>
    <published>2020-01-20T03:28:37.000Z</published>
    <updated>2025-10-22T04:31:22.999Z</updated>
    
    <content type="html"><![CDATA[<p>vuepress 主题介绍</p><span id="more"></span><p>官方文档参见：<a href="https://vuepress.vuejs.org/zh/theme/default-theme-config.html#%E9%A6%96%E9%A1%B5">默认主题配置</a></p><p>开始之前假设你建立了以下结构的文件内容，之后的设置也会参照这份文件内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── docs</span><br><span class="line">│   ├── .vuepress</span><br><span class="line">||└── config.js (配置文件)</span><br><span class="line">||</span><br><span class="line">│   ├── guide (指南)</span><br><span class="line">│   │   ├── README.md (指南首页)</span><br><span class="line">│   │   ├── basic-config (基本配置)</span><br><span class="line">│   │   │   └── README.vue (基本配置首页)</span><br><span class="line">│   │   └── info.md (相关信息页面)</span><br><span class="line">│   │ </span><br><span class="line">│   ├── about.md (关于我们)</span><br><span class="line">│   └── README.md (项目主页)</span><br><span class="line">│ </span><br><span class="line">└── package.json</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="导航栏"><a href="#导航栏" class="headerlink" title="导航栏"></a>导航栏</h1><h1 id="侧边栏"><a href="#侧边栏" class="headerlink" title="侧边栏"></a>侧边栏</h1><p>配置项 <code>themeConfig.sidebar</code></p><p>侧边栏默认是一个包含了多个链接的数组，数组中的每一个真实存在的文件路径。按照上面的目录结构，你想建立相应的侧边栏，你可以如下设置<code>themeConfig.sidebar</code></p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;themeConfig&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    sidebar<span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">      &#x27;/&#x27;<span class="punctuation">,</span></span><br><span class="line">      &#x27;/guide/&#x27;<span class="punctuation">,</span></span><br><span class="line">      &#x27;/guide/basic-config/&#x27;<span class="punctuation">,</span></span><br><span class="line">      &#x27;/guide/info&#x27;<span class="punctuation">,</span></span><br><span class="line">      &#x27;/about&#x27;<span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">]</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>效果如下：</p><p><img src="/vuepress-03-default-theme-config/1579510148963.png" alt="1579510148963" loading="lazy"></p><blockquote><p>侧边栏的结构和文件实际的目录结构没有关系，侧边栏信息根据<code>themeConfig.sidebar</code>参数内容生成。</p></blockquote><p>特别需要注意的是，文件和文件夹的设置方式的差别：</p><blockquote><p>文档中说：你可以省略 <code>.md</code> 拓展名，同时以 <code>/</code> 结尾的路径将会被视为 <code>*/README.md</code></p></blockquote><p>这句话你可以理解成：针对于文件夹，请设置以 <code>/</code> 结尾。</p><p>如果侧边栏路径指向一个实际的文件，例如<code>about.md</code>文件，侧边栏你可以设置成<code>/about</code>，他将实际使用 <code>/about.md</code>文件，将生成<code>http:localhost:8000/about.html</code>页面路径。</p><p>如果是一个目录，例如<code>guide</code>，请设置成<code>/guide/</code>，他将实际使用 <code>/guide/README.md</code>文件，将生成<code>http:localhost:8000/guide/</code></p><h2 id="侧边栏名称"><a href="#侧边栏名称" class="headerlink" title="侧边栏名称"></a>侧边栏名称</h2><p>默认情况下，侧边栏将自动提取文件内第一个标题作为导航标题，无论当前标题是第几级标题，如果你想指定标题名称，请使用一个格式为 <code>[link, text]</code> 的数组。</p><h2 id="侧边栏层级深度"><a href="#侧边栏层级深度" class="headerlink" title="侧边栏层级深度"></a>侧边栏层级深度</h2><p>类似于官网中的侧边栏信息，他存在一定的层级深度。</p><p><img src="/vuepress-03-default-theme-config/1579510936334.png" alt="1579510936334" loading="lazy"></p><p>默认情况下，侧边栏会自动地显示由当前页面的标题（headers）组成的链接，并按照页面本身的结构进行嵌套。</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 一级标题</span></span><br><span class="line">内容部分</span><br><span class="line"></span><br><span class="line"><span class="section">## 二级标题</span></span><br><span class="line">内容部分</span><br><span class="line"></span><br><span class="line"><span class="section">### 三级标题</span></span><br><span class="line">内容部分</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="/vuepress-03-default-theme-config/1579511258773.png" alt="1579511258773" loading="lazy"></p><p>默认情况下，层级深度只展示到二级标题，但是你可通过<code>themeConfig.sidebarDepth</code>属性修改默认行为。</p><p><code>0</code>：禁用标题链接，只提取<code>h1</code>的标题；</p><p><code>1</code>：默认值，他将提取到<code>h1</code>、<code>h2</code>的标题；</p><p><code>2</code>：最大值，将提取<code>h1</code>、<code>h2</code>、<code>h3</code>的标题。</p><p>设置方式有两种：</p><ol><li><p>在<code>themeConfig.sidebarDepth</code>设置，他将影响所有页面的侧边栏层级。</p></li><li><p>在文件中使用<code>YAML</code>格式设置，将单独影响当前页面：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line"><span class="section">sidebarDepth: 2</span></span><br><span class="line"><span class="section">---</span></span><br></pre></td></tr></table></figure></li></ol><h2 id="显示所有页面的标题链接"><a href="#显示所有页面的标题链接" class="headerlink" title="显示所有页面的标题链接"></a>显示所有页面的标题链接</h2><p>默认情况下，侧边栏只会显示由当前活动页面的标题（headers）组成的链接，你可以将 <code>themeConfig.displayAllHeaders</code> 设置为 <code>true</code> 来显示所有页面的标题链接：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">themeConfig</span>: &#123;</span><br><span class="line">    <span class="attr">displayAllHeaders</span>: <span class="literal">true</span> <span class="comment">// 默认值：false</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>设置该属性，所有侧边栏的所有菜单均会展开，否则，只将展开当前获得菜单。</p></blockquote><h2 id="侧边栏分组"><a href="#侧边栏分组" class="headerlink" title="侧边栏分组"></a>侧边栏分组</h2><p>分组是将在同一个组内的菜单生成一个折叠的菜单，如果将上例中的侧边栏修改为：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;themeConfig&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    sidebar<span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">      <span class="string">&quot;/&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="punctuation">&#123;</span></span><br><span class="line">        title<span class="punctuation">:</span> <span class="string">&quot;指南分组&quot;</span><span class="punctuation">,</span>  <span class="comment">// 必须的</span></span><br><span class="line">        path<span class="punctuation">:</span> <span class="string">&quot;/guide/&quot;</span><span class="punctuation">,</span>   <span class="comment">// 可选的, 应该是一个绝对路径</span></span><br><span class="line">        collapsable<span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span> <span class="comment">// 可选的, 是否可折叠，默认值是 true，为false时该分组将永远都是展开状态</span></span><br><span class="line">        sidebarDepth<span class="punctuation">:</span> <span class="number">2</span><span class="punctuation">,</span>   <span class="comment">// 可选的, 默认值是 1</span></span><br><span class="line">        children<span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;/guide/basic-config/&quot;</span><span class="punctuation">,</span> <span class="string">&quot;/guide/info&quot;</span><span class="punctuation">]</span> <span class="comment">// 可选的，没有时将不会有折叠效果</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">      <span class="string">&quot;/about&quot;</span></span><br><span class="line">    <span class="punctuation">]</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>他将生成如下的侧边栏：</p><p><img src="/vuepress-03-default-theme-config/1579512507035.png" alt="1579512507035" loading="lazy"></p><h2 id="多个侧边栏"><a href="#多个侧边栏" class="headerlink" title="多个侧边栏"></a>多个侧边栏</h2><p>如果你想为不同的页面组来显示不同的侧边栏，你可以如下设置：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  &quot;themeConfig&quot;: &#123;</span><br><span class="line">    sidebar: &#123;</span><br><span class="line">      &#x27;/guide/&#x27;: [</span><br><span class="line">        &#x27;&#x27;,</span><br><span class="line">        &#x27;basic-config/&#x27;,</span><br><span class="line">        &#x27;info&#x27;</span><br><span class="line">      ],</span><br><span class="line">      &quot;/&quot;: [</span><br><span class="line">        &#x27;&#x27;,</span><br><span class="line">        &#x27;about&#x27;</span><br><span class="line">      ],</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="/vuepress-03-default-theme-config/1579513820591.png" alt="1579513820591" loading="lazy"></p><blockquote><p>需要注意的是:</p><p><code>sidebar</code>属性是一个键值对对象，而不是数组。</p><p><code>/</code> 路径必须要在最后设置，<code>vuepress</code>会按顺序遍历侧边栏配置来寻找匹配的配置，如果先配置<code>/</code>，会导致之后的配置均无法找到，因为<code>/</code>可以匹配到任意模式。</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;vuepress 主题介绍&lt;/p&gt;</summary>
    
    
    
    <category term="vuepress" scheme="https://blog.plcent.com/categories/vuepress/"/>
    
    
    <category term="vuepress" scheme="https://blog.plcent.com/tags/vuepress/"/>
    
  </entry>
  
  <entry>
    <title>vuepress学习系列/1/初次认识</title>
    <link href="https://blog.plcent.com/vuepress-01-first-learning/"/>
    <id>https://blog.plcent.com/vuepress-01-first-learning/</id>
    <published>2020-01-16T14:28:37.000Z</published>
    <updated>2025-10-22T04:30:51.603Z</updated>
    
    <content type="html"><![CDATA[<p>vuepress 基础介绍</p><span id="more"></span><h3 id="vuepress-初识"><a href="#vuepress-初识" class="headerlink" title="vuepress 初识"></a>vuepress 初识</h3><p>之所以会了解到vuepress，是在学习element-ui源码时，想自己搭建一个elemen-ui那样的技术文档网站，因为可以运行的demo让element-ui和一般的技术站点显得更为友好。</p><p>翻了源码之后发现其使用<code>vue-markdown-loader</code>来加载<code>markdown</code>文档，按照这个原理，翻看<code>vue-loader</code>官网后,发现了<code>vuepress</code>。其提供的功能基本可以满足这样的需求。本着学习的态度，开启了<code>vuepress</code>学习之旅。</p><h3 id="vuepress-能做什么"><a href="#vuepress-能做什么" class="headerlink" title="vuepress 能做什么"></a>vuepress 能做什么</h3><p>你看到的，<code>vue</code>、<code>vue-loader</code>、<code>vue-router</code>等 <code>vue </code>官方的文档,均是使用 <code>vuepress</code> 搭建的。</p><h3 id="上手"><a href="#上手" class="headerlink" title="上手"></a>上手</h3><p>开始前，先领取一份官方文档：<a href="https://vuepress.vuejs.org/zh/guide/">https://vuepress.vuejs.org/zh/guide/</a></p><p>按照 <a href="https://vuepress.vuejs.org/zh/guide/getting-started.html#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B">快速上手</a> 的步骤，安装并初始化</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">安装</span></span><br><span class="line">yarn global add vuepress # 或者：npm install -g vuepress</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建项目目录</span></span><br><span class="line">mkdir vuepress-starter &amp;&amp; cd vuepress-starter</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建一个 markdown 文件</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">可能会导致乱码的问题</span></span><br><span class="line">echo &#x27;# Hello VuePress!&#x27; &gt; README.md</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">开始写作</span></span><br><span class="line">vuepress dev .</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">构建静态文件</span></span><br><span class="line">vuepress build .</span><br></pre></td></tr></table></figure><blockquote><p>问题：启动项目后，如果你遇到乱码的问题，请不要慌张，这是你新建的 <code>README.md</code> 文件乱码导致的，将文件编码修改成 <code>utf-8</code> 即可解决该问题。</p></blockquote>]]></content>
    
    
    <summary type="html">&lt;p&gt;vuepress 基础介绍&lt;/p&gt;</summary>
    
    
    
    <category term="vuepress" scheme="https://blog.plcent.com/categories/vuepress/"/>
    
    
    <category term="vuepress" scheme="https://blog.plcent.com/tags/vuepress/"/>
    
  </entry>
  
  <entry>
    <title>vuepress学习系列/2/基本配置</title>
    <link href="https://blog.plcent.com/vuepress-02-basic-config/"/>
    <id>https://blog.plcent.com/vuepress-02-basic-config/</id>
    <published>2020-01-16T14:28:37.000Z</published>
    <updated>2025-10-22T04:31:09.476Z</updated>
    
    <content type="html"><![CDATA[<p>vuepress 基础配置介绍</p><span id="more"></span><h3 id="vuepress配置"><a href="#vuepress配置" class="headerlink" title="vuepress配置"></a>vuepress配置</h3><p>先领取一份官方文档：<a href="https://vuepress.vuejs.org/zh/guide/basic-config.html">https://vuepress.vuejs.org/zh/guide/basic-config.html</a></p><p><code>vuepress</code>的所有配置信息均放在 <code>docs/.vuepress</code> 目录下，因为 <code>vuepress</code> 建议的目录结构如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── docs</span><br><span class="line">│   ├── .vuepress (可选的)</span><br><span class="line">│   │   ├── components (可选的)</span><br><span class="line">│   │   ├── theme (可选的)</span><br><span class="line">│   │   │   └── Layout.vue</span><br><span class="line">│   │   ├── public (可选的)</span><br><span class="line">│   │   ├── styles (可选的)</span><br><span class="line">│   │   │   ├── index.styl</span><br><span class="line">│   │   │   └── palette.styl</span><br><span class="line">│   │   ├── templates (可选的, 谨慎配置)</span><br><span class="line">│   │   │   ├── dev.html</span><br><span class="line">│   │   │   └── ssr.html</span><br><span class="line">│   │   ├── config.js (可选的)</span><br><span class="line">│   │   └── enhanceApp.js (可选的)</span><br><span class="line">│   │ </span><br><span class="line">│   ├── README.md</span><br><span class="line">│   ├── guide</span><br><span class="line">│   │   └── README.md</span><br><span class="line">│   └── config.md</span><br><span class="line">│ </span><br><span class="line">└── package.json</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>目录结构文档：<a href="https://vuepress.vuejs.org/zh/guide/directory-structure.html#%E9%BB%98%E8%AE%A4%E7%9A%84%E9%A1%B5%E9%9D%A2%E8%B7%AF%E7%94%B1">https://vuepress.vuejs.org/zh/guide/directory-structure.html</a></p><p>新建配置文件只需要在<code>.vuepress</code>下新建文件<code>config.js</code>即可：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt; <span class="built_in">mkdir</span> .vuepress &amp;&amp; <span class="built_in">touch</span> .vuepress/config.js</span><br></pre></td></tr></table></figure><p>一个 VuePress 网站必要的配置文件是 <code>.vuepress/config.js</code>，它应该导出一个 JavaScript 对象：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">title</span>: <span class="string">&#x27;Hello VuePress&#x27;</span>,</span><br><span class="line">  <span class="attr">description</span>: <span class="string">&#x27;Just playing around&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="完整基本配置"><a href="#完整基本配置" class="headerlink" title="完整基本配置"></a>完整基本配置</h3><p>官方文档地址：<a href="https://vuepress.vuejs.org/zh/config/#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE">基本配置</a>，具体配置请参照官方文档。这里只列出一些不好理解的属性。</p><blockquote><p>加 ☆ 的属性表示不知道该属性如何使用。</p></blockquote><ul><li><p>☆ <a href="https://vuepress.vuejs.org/zh/config/#temp">temp</a>  指定客户端文件的临时目录。</p><blockquote><p>默认的临时文件放在 <code>node_modules/@vuepress/core/.temp</code> 下</p></blockquote></li><li><p>☆ <a href="https://vuepress.vuejs.org/zh/config/#shouldprefetch">shouldPrefetch</a>  一个函数，用来控制对于哪些文件，是需要生成 <code>&lt;link rel=&quot;prefetch&quot;&gt;</code> 资源提示的。请参考 <a href="https://ssr.vuejs.org/zh/api/#shouldprefetch">shouldPrefetch</a>。</p><blockquote><p>该参数用于服务端渲染</p></blockquote></li><li><p><a href="https://vuepress.vuejs.org/zh/config/#cache">cache</a>  此选项可以用于指定 cache 的路径，同时也可以通过设置为 <code>false</code> 来在每次构建之前删除 cache。</p></li><li><p><a href="https://vuepress.vuejs.org/zh/config/#extrawatchfiles">extraWatchFiles</a>  指定额外的需要被监听的文件。</p></li><li><p><a href="https://vuepress.vuejs.org/zh/config/#patterns">patterns</a>  指定将解析哪些文件。默认值：<code>[&#39;**/*.md&#39;, &#39;**/*.vue&#39;]</code>。</p><blockquote><p>你可以修改该属性,用来屏蔽部分文件,，让他们在编译时不会被包含进来。<code>[&#39;**/page/*.md&#39;]</code>只包含<code>page</code>目录下的<code>.md</code>文件</p></blockquote></li><li></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;vuepress 基础配置介绍&lt;/p&gt;</summary>
    
    
    
    <category term="vuepress" scheme="https://blog.plcent.com/categories/vuepress/"/>
    
    
    <category term="vuepress" scheme="https://blog.plcent.com/tags/vuepress/"/>
    
  </entry>
  
  <entry>
    <title>2019 年终总结和反思</title>
    <link href="https://blog.plcent.com/summary-and-relection-in-2019/"/>
    <id>https://blog.plcent.com/summary-and-relection-in-2019/</id>
    <published>2019-12-12T05:08:06.000Z</published>
    <updated>2025-10-22T03:32:04.991Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="密码错误，请重试。" data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.">  <script id="hbeData" type="hbeData" data-hmacdigest="284a72938452997e295571437366d81c88948de27152d2b39171d8020f92060e">37e838bebf05349d6f5e0362e359992139629fa70dce2215dd6403978223be83e03d50b9e30c2cb9bff59d4c083b9b7ba03ccfcbf6bc427fc71846dc5471705b87e56e96a432def89a68568d69a5695d7152f2ed9a3067cf01fe2c273016e29fd5fdf332a9450d35109bd2f4a34d6c03e9d4332f0deed911c163114f18f437b301c1bf24a0e4caf84adbd677fa4a9e767f035b2677e646c87f997f63f5538bcc73bdba805b78e8ae1c4124d23ac14c5e29d044124b39b1de2b3b63e22989a75efe4ca66cd6a2401a2a2c65b3ea3654ee49c2bd1baba00bb9616e4fd59fa72bfaa8fa00a7bfc80217a125f0ba91cc73c210ecc8a1e37c19d82b5c0c98f511ca4a21630a445f247b7708f1fa8340225850b7596900d69fd3d5ac451c2829e6800f7432e2858369e3352a3184b42f93b95a5719f8b395b50fca9b66433e1ee9a49ea9ff85ec922cf511a285ff404b3b6ebc86b296376d410489d4fc8a9a0a3fdaabf7bf912c343b43cff023880ce18dfd40fc2ab1450bf410351ac542b96f79b29de9c9cc72b5f2c19b8bae0b65af2682320cd0b57901aead84f8eb71aab97d558a364a00ade959a6fa6e0b0248f18fda70270016a1b069ac9cbb3a870d893ad1bda3bc6c35508997394c9d53619c5ca89cbf1a65b69bfeb7d1e3e1d6893d42730b5ca4ec4ba3f99e7bd44b9d488588063f925727be19a85e32d0db7c61c60792d1986682858d901e5466f162b263fa3ac8a442983a64f75cfeee6883e298ccb0657592929f4bb73597a516fee1bf3d7386dfa7573a64a1bbc5b2e8e7a5b4c0fff7c129ac667525a1e3e2f7d0b8f98b0d309beb84f42f5dfbe930a060e9f115125f5b7a3da470ef5fa6c0fba0474323d54a3d74bb184e7e611336a97fcad05ae2970fab0a30a085129f1aa49fd7cf2b5c08461873ea4ac58b7d425104f34486bbd7ac9f0111724ca7dfc1c8be6c6a348383a94f5f562b9373200254ddbfd11994148ceac7639e43ff66c58b0309c73ecd074e3b755e42f479e74b99eda172375932c5f97f528472d770e38382e98ec0b2823b046c6a140bae214a14b03c8fe7898a113c84afebaa7285285f9fa43869af5d0e7777fc34be8f80dbb7363cc3ac3c741b1674874c60b46d43e73e430f12a82f87e673a58831e4e7f28933edb9faadf74a7df74eaaf828d8aae17bc292ab49d0de1f680414c34d69bac24229f188119a5a2c54e3da10fe19a30cdd586aba1c0e6213922bf62cfccf9e2aae8e5d300d02efc7424e6f1ed6b9b46de1ffb52d4354ef2e0cef21417d9548ff71c2ec6574c954ba730534df92d60eea39e2426ad89d0a0608d6654544f46c95faff93540e92493fbae5bf9f9f12c1d9a06db881240e84bf05f6c9180e1a68d0cb02c2cc6f14616e24c04a95a4047b2f8b3ebf0a943326157f1c6f464a632c332582b63cfc8cbfbb518a2e9c33ae3a05e65d5a450fb397b8a5288a58e77ffb147a6baaf87eeccff8509571d0d44cac804abc5396b308773746968c4fa212fead89abd3685b348cead48301038592bf933b3f7a8c798d99205d2e7b439efa874b5518b6924f0fbc2b26102c3b3909347b364f67992f758e8aabde878d6f62047d233823d707573ce833f90e28945f3fbb3927c82221c63122df99eb5b4fae962429bf9c9e53560513f1d3ddc7e06e94f8bc781c9d817501ec58bbb28f9149a45d17e6119a42ebc2ff59e3eebeb762fab9d9ef40e541dfd184ecde2324ebbb34ca549e3e86a5a75a1f8e3088c9e40e1c592d7646a4893ca904302de05c08d4be39e93b698fc5f0ff58a5ea42f1e397a824b8bdf385d37be24f64f524a99cb0ed05ad87740ab5bbcfc23f37b850bcb05146ba81bc5d5fea8705e58c519459dbd4218161346f0fb9e4d3eec229a5a7a0e47a293441595cf2d26280b4045c81c1154eda705b70f5638cb0c51ee558325f24e99abb9a24eb93aa0d08239c7bb5d0d9b0cded293e39585091173a29b409b6f20b86e9675b731cf37c677dfdbc51b89db2cd02700ecb2c62e916a0a00d8d69aa1624bdf31a3aaeea080885bf85eea83b65d5c951d5ea5209e5b755d4eb3c3e127ee516a22298622fad6f80592d913a97644b05e5c8dd68bd44a203f227721aab7ad647e2477147f5140828c59e91fcdb1c0759eb91861b89ac7f468a47e8cb256a4554b4be9e61ef7bf09771e91225fea6ebbc4325d686aa493bcf37e1ca6cd8e67e6d1e507314f8aa0aac55f03a36062f19ec4504e7a8037d5c401edaca172ae06d37f11e26c7b9409e08e90767b9ec02ca2b9c40ef45a14a4b126b5c115eafc02cbce13638092074875215150eedb690f5e6c00f2293c7f23dfad0686a94f91e356424111ac98e48ba896a54a397349293873152db049b1b9b78749a65b87a84262f9a3b2085236b17b024116b75ac2d9a45950257541dfd3a1e8f2c329debf6eeb3409c38fb5f80580aa08113483a0575c97156e692034860c7f8944bbf2487cb567bdc18298039fb585a0017e816a034491b6e620ded7e6eb785c265bcecfd46f0211b4c62afb54abde65b3c556b77f92942c552542de22bc94f117668c4bb9c886d35f9222ea7cf9e390e537eb78f7b1712c348e569796c833dec3b9da8e725e2e8c74b2d598ae41ac3ffd30eaf4c26dc25f24017fa6b76015fc3be0928e2697a70c7c0fc6192c1f91bc989eb71f033282eb9ab3df1b8a95aeb8bc87da415c6248719068c38e4a0b4cb83ae8d32d70754b3f80ae9ed474e948b9475bf42c898c3779a49c6eb131d9b456fa683d8cce2b0cf9140c88a17a4e6a1f85e06aaa213de85f51322afea6fd5d4ba8fcb39edb2655df1bec2f10e647f65af9975fa26d65566eeab197d7eef39a658c1369532b9a32fcc3a29867f42c02dcdcc03b3b62e869fdb3b3f13edfbd2111b164a6c99dc9c0c3e30add85dbc41a38386f477621963df2bd654952d2c911e9542211266993bb698eec05e3dfa774ab2637be8288ab3af51ad50225fe67ec29ab5febb475b2de70eafd1aa74ee3de79a79a01d5cfc407a2487edb9ef796b837528ebc5a2ff633270016dd89a99740817d643b9cf1673100efe903d2ffc206bc67abc9a37109af297d14546c18d26ba88b4412c7afa1a938fe6ad900e0879e3cc2e1c854d953d6305decf81ca0b54bb4c46cb9823848b940f2752d7f354325c6477938b43ada2182c65f213e9baaa46f906e3c9b5c86586288bea62c14a9ba358f6332371b054b6929aa779baf9170bbad9b35e250b5b3d4c13e75bb748d8c377a0d81c2241743bb4bf8baf4a09383a7448d27bd78cebd4e6504c09df9633fb526a4b4188a74c3a0dae36f11f3c12eb318ab9c8a62fa3864f0e12b0708d5bb4e12ab9445fda69fd96231f609feae71aec1cb1f33e18edd706846b1079359dfb29b5a49545b4ce861dbd83e2166b82be5f2e46e445a70b1f18c8c5b186ca3b8419c0a9a82428f72e83b9acb995df59d1ae8c65d8c2df70479f108f49f90a416259aca60f2d3f1e3716712224f504e2b1e7ccd9932794799c27e5854a41975aa24615d224acfa8956687f5a54c855c9a8d9e475d99a3b7479d831a8fbb132f45e8869176a2298c89043bfdb101bdbf64c3bb25055f3517b8a78a11449f8b3c5382a5ea7e189a0a5c59f5ed6e9bde9f299761685bc76f7d4dccbb57ff1334090b78b556a6bf41dd0e0cd3b917d27f11db8705e0578b30138fd2900a4d5e6cdda8e92ff35a1b37d42aba16b7f6cb94d60bd0df7dc66ce40739ea986ae113d17453a4d9c388a3bef6da0a3c43fa25e9d4ad32ddb260ebd130068a72a961949704ac701be76d02cadacee3dabe2c83f94f3f3e4edede22834479368f33e6c2f8b6bca8d7c5ca4ea645522096cc6ec997e03a7af1290613f6d8ab7e6ecf5722d5c9412e989a69bec5ee1f6a6b7a01cbfa29729a385e0659bbe0c876c8ffc531076f51459ce767c4980f01bb0766be1e3def24fa03f2691766a457002a5c733bb444be4e01b13d6f4e0661407d2d82628eeb573b97ea210ba9113d167886c95849ce28cc387a6fe4ebf51861e6e0d1bdc6fda96b9808693b457d1c9ba2f542de5b8485dd27c21ce94ddf1773f618f2f552e4d1c629d717c8224709517952c9ee449aa49e13f6e989786ed9e1b7916855bce1c8d8c18b4a18cd44b4655e41a85f65bfe6bca751e73e37a564017255a1ec846039dc35aac3e60e1040ddc697fedede901ab7eb0d5c6dcb4c84f09a639d7b7812f372ca6a7d11fea662851754ae14a698dccbaf246a2fac18e740f9c380d533ab2216a820b2ed78d0186b25092a7753effed3b9a89221a9567304da5247febcfad2adb4567dbe09d272ea825e3dc77b7a67866300a751f1fd45b380e3af4970fd23033a9cdbb7ba35cf8895815d5d208d91207f1e30578c267f7534d2590d4dfa111d75d69958521a761102cc689b3073fff78a80cc2e0daf78242b5fd5814a10a3747aa0848d649df7406f2102fd66a7bcb4fba4b757921db46d7576d482ebbc7389303f1dc0bc8b47ff02b8152378f4982b84b1d1840e2d048c12cb42faa9f8a42c59035475e6dfb7cff94c72770b3fcaaaa2c95696a40d45a18d04e347da4c6a6689d13bfc9eeca84559f2e81cb32e724ebfc766fdde21de6247330a49b1638f1e4b22dbe724da387389f1083daa4323f8ae4bcc8938e53fb5a91772272fab25ff281ec671414c10de435b8bf389c9eb95c6a885b92e860634fb182911433340867388bcd7343af0b0861c7840057f4e5dca55dd716ceb404efd7a2a5ff92ddc5ee4137be0eb9ae26e079dee284c9faa4c3caf4df750aba7987a3c8c82717f8db73ea9b60428d374330d1015f8ad8264ed3184ad46b5b034d3e5a3b7bc153826eab9679c53ffb1309274501c079149917f67d8f7299fd9756633f12f009815c2bdd1febc8ca3a36d48469b651df6a7234fd16ea38b2b1294149566484b067f3ee24f87d77f9f8af5399d20126265c1227459179315b9e9d39e204dad2480603403e13af9a57f235bfa66f7e7ee9d8eba28c9175d8daabfa7e8b260e8306557c4c6e4dec3db869cb230b21c8dd041a34a23fccdf2a815a449a19e8f6a796e534eb88049ef14a54624c4ac3794b2ff0030306fc19598152f9d75f1bbb8d823f600cbd06c9d9ba5b08d14b5a4d885fa8dd18393dd61f682ed229fff709caa4d65d60d2d4b69b6897cbbaca846b824ccbe5162d42972d7fe3fcd37513def07f2ad22d30884ed7c9d8bd0ef21440c1d7152b6316224685bd152ae22a577bdb3833afae35ad6cb62ad4a4a166eebc2f9c6c6493511585dd26b91571fb1e83a395ac41b2d2e6869b11b2dbe958e4d6cfe27749f5be26181acf3973832a289cda18fb53c829429e094a48d5d28f2a34d1261df0a028990925830f1a6af9815e2f1d9fc7a0d15be4d552d13a7d1446ff72cbeed282b20f347b866fc8ce8e753e1df558e2371423711f0522aea6943fb25b47dc6a8608098daadb7e52de406bcc949d1286bbb156b619c3da8710731c4e3a2f73200b04b2774a93ee648afdec181acb67a439a46f34660e9b5d6b112dfe86b9a69784e363e164ed49f9456f0b78e7498df4a1ccdc2d657363f08151df74ca09df9dae4fc0bd432f36c4c59b3f12ad8222bd4ad4b85dd7dac34baee489f2382d69133246d83544d6515acea204ff789ad71b0523a641f59ebfb7ecf4cf19893dc223adf701711f2487fe35e9106dd8b92403de5d425ceb40c76c4544fbd118923c190d8aa24c7fde0f015d4e5293</script>  <div class="hbe hbe-content">    <div class="hbe hbe-input hbe-input-default">      <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass">      <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass">        <span class="hbe hbe-input-label-content hbe-input-label-content-default">继续阅读请输入密码！</span>      </label>    </div>  </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
    
    
    <summary type="html">这是一篇私密文章！</summary>
    
    
    
    <category term="个人" scheme="https://blog.plcent.com/categories/%E4%B8%AA%E4%BA%BA/"/>
    
    
    <category term="个人" scheme="https://blog.plcent.com/tags/%E4%B8%AA%E4%BA%BA/"/>
    
  </entry>
  
  <entry>
    <title>Hexo主题pure使用指南</title>
    <link href="https://blog.plcent.com/hexo-theme-pure/"/>
    <id>https://blog.plcent.com/hexo-theme-pure/</id>
    <published>2019-11-05T06:34:15.000Z</published>
    <updated>2025-10-22T04:32:45.286Z</updated>
    
    <content type="html"><![CDATA[<p><code>hexo</code> 主题 <code>pure</code> 项目相关信息:</p><blockquote><p>预览地址: <a href="https://blog.cofess.com/">https://blog.cofess.com</a><br>项目地址: <a href="https://github.com/cofess/hexo-theme-pure">https://github.com/cofess/hexo-theme-pure</a><br>中文使用文档: <a href="https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md">https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md</a></p></blockquote><span id="more"></span><h3 id="使用前请操作"><a href="#使用前请操作" class="headerlink" title="使用前请操作"></a>使用前请操作</h3><p>使用该主题前, 请先复制 <code>theme/pure/_source/</code> 目录下的所有内容到 <code>blog path/source/</code> 目录下<br>原因在于该目录下有建好的菜单 <code>categories</code>(分类)、<code>tags</code>(标签)、<code>repository</code>(项目)、<code>books</code>(书单)、<code>links</code>(友链)、<code>about</code>(关于)页面</p><p>当你使用自动生成分类、标签，展示github项目时</p><h3 id="文章目录索引"><a href="#文章目录索引" class="headerlink" title="文章目录索引"></a>文章目录索引</h3><p>在文章详情页, 展示一个文章目录</p><ol><li>主题配置文件中开启配置:</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">config</span><br><span class="line">  toc: true # 是否开启文章章节目录导航</span><br></pre></td></tr></table></figure><ol start="2"><li>在文章顶部将该文章开启索引, 如:</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: Hexo主题pure使用指南</span><br><span class="line">date: 2019-11-05 14:34:15</span><br><span class="line">tags: </span><br><span class="line">- hexo主题</span><br><span class="line"></span><br><span class="line">categories:</span><br><span class="line">- hexo</span><br><span class="line"></span><br><span class="line">toc: true # 是否启用内容索引</span><br><span class="line">sidebar: none # 是否启用sidebar侧边栏，none：不启用</span><br><span class="line">---</span><br></pre></td></tr></table></figure><h3 id="侧边栏"><a href="#侧边栏" class="headerlink" title="侧边栏"></a>侧边栏</h3><p>主题配置项中, 侧边栏可以如下配置:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"># 侧边栏</span><br><span class="line">sidebar: right</span><br><span class="line"># 侧边栏启用哪些模块</span><br><span class="line">widgets:</span><br><span class="line">  - board # 公告</span><br><span class="line">  - category # 分类</span><br><span class="line">  - tag # 标签</span><br><span class="line">  - tagcloud # 标签云</span><br><span class="line">  - archive # 归档</span><br><span class="line">  - recent_posts # 最近文章</span><br><span class="line"></span><br><span class="line"># 归档列表的展示方式</span><br><span class="line">archive_type: &#x27;monthly&#x27; # 归档方式:  yearly | monthly</span><br><span class="line">show_count: true # 显示每个归档的文章总数</span><br></pre></td></tr></table></figure><h3 id="图集"><a href="#图集" class="headerlink" title="图集"></a>图集</h3><p>在文章详情页中, 涉及的图片可以使用图集功能, 在点击一张图片时, 放大图片.<br>主题的图册公告是使用<a href="https://github.com/fancyapps/fancybox">fancybox</a>实现, 可以参照github</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># Fancybox</span><br><span class="line"># 图集功能</span><br><span class="line">fancybox: true</span><br></pre></td></tr></table></figure><h3 id="展示github项目"><a href="#展示github项目" class="headerlink" title="展示github项目"></a>展示github项目</h3><p>在左侧菜单<code>项目</code>中, 点击展示自己的github项目</p><ol><li>在主题配置文件中 <code>_config.yml</code> 修改, 请配置自己github用户名</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">github: </span><br><span class="line">  username: caoruiy  # github用户名</span><br></pre></td></tr></table></figure><ol start="2"><li>新建<code>repository</code>页面:</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt; hexo new repository</span><br></pre></td></tr></table></figure><blockquote><p>你也可以直接复制 <code>theme/pure/_source/</code> 目录下 <code>repository文件夹</code> 到 <code>博客根目录/source/</code> 目录下</p></blockquote><ol start="3"><li>将文件内容修改为:</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: Repositories</span><br><span class="line">layout: repository</span><br><span class="line">comments: false</span><br><span class="line">sidebar: none</span><br><span class="line">---</span><br></pre></td></tr></table></figure><blockquote><p>关键内容为 <code>layout: repository</code>, 包含该属性才可以展示github项目</p></blockquote><h3 id="评论功能"><a href="#评论功能" class="headerlink" title="评论功能"></a>评论功能</h3><p>主题集成了<a href="https://disqus.com/">disqus</a>、<a href="http://www.uyan.cc/">友言</a>、<a href="https://livere.com/">来必力</a>、<a href="https://github.com/imsun/gitment">gitment</a>、<a href="https://github.com/gitalk/gitalk">gitalk</a>评论系统，选择其中一种即可</p><p>你可以在主题配置文件中修改评论工具</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">comment:</span><br><span class="line">  type: valine  # 启用哪种评论系统</span><br></pre></td></tr></table></figure><h4 id="Valine"><a href="#Valine" class="headerlink" title="Valine"></a>Valine</h4><p>一个无后端的评论框工具, 其依赖于 <a href="https://leancloud.cn/">Leancloud</a> 开发, 所以使用前需要先注册 <a href="https://leancloud.cn/">Leancloud</a> 账号</p><p>如何开始? 你可以从 <a href="https://valine.js.org/quickstart.html">Valine-快速开始</a> 教程开始, 教程包含了一步一步的指引教程.</p><h5 id="Valine配置项"><a href="#Valine配置项" class="headerlink" title="Valine配置项"></a>Valine配置项</h5><p>主题valine评论框提供了以下配置项</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">valine: # Valine官方地址: https://valine.js.org</span><br><span class="line">  appid:  # 你的 leancloud 应用 appid</span><br><span class="line">  appkey:  # 你的 leancloud 应用 appkey</span><br><span class="line">  notify: true # 是否开始评论邮件提醒, 教程: https://github.com/xCss/Valine/wiki</span><br><span class="line">  verify: false # 是否开始验证码功能, 开始邮件提醒会自动开启验证码功能</span><br><span class="line">  placeholder: 说点什么... # 输入框默认内容</span><br><span class="line">  avatar: mm # 头像展示方式, 具体设置项教程: https://valine.js.org/configuration.html#avatar</span><br><span class="line">  meta: nick,mail,link # 自定义评论信息</span><br><span class="line">  pageSize: 10 # 评论列表分页</span><br><span class="line">  lang: zh-cn, # 多语言支持 zh-cn | en</span><br><span class="line">  visitor: true # 文章阅读量统计:  https://valine.js.org/visitor.html</span><br><span class="line">  highlight: true # 代码高亮</span><br><span class="line">  recordIP: true # 记录评论者的IP</span><br></pre></td></tr></table></figure><blockquote><p>关于邮件提醒: 只有在回复评论时, 并且填写了邮箱的评论才会收到回复提醒<br>关于文章阅读量统计: 开启阅读量统计, 会在详情页标题下展示阅读量数据</p></blockquote><h3 id="搜索功能"><a href="#搜索功能" class="headerlink" title="搜索功能"></a>搜索功能</h3><p>主题提供内置的<code>搜索功能</code>和<code>百度搜索</code>, <code>百度搜索</code>就是使用百度的SEO搜索, 个人觉得不是很实用, 不建议开启.</p><p>在主题配置文件 <code>_config.yml</code> 中配置:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># Search</span><br><span class="line">search:</span><br><span class="line">  insight: true # 在使用搜索功能前, 你需要安装 `hexo-generator-json-content`</span><br><span class="line">  baidu: false # 使用百度搜索前, 你必须禁用其他所有的搜索功能</span><br></pre></td></tr></table></figure><h4 id="内置搜索"><a href="#内置搜索" class="headerlink" title="内置搜索"></a>内置搜索</h4><p>使用搜索功能前需要先安装:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -S hexo-generator-json-content </span><br></pre></td></tr></table></figure><p>项目地址: <a href="https://github.com/alexbruno/hexo-generator-json-content">https://github.com/alexbruno/hexo-generator-json-content</a></p><p>在你运行 <code>hexo g</code> 或者 <code>hexo s</code> 时生效，在 <code>hexo g</code> 生成站点时, 会在根目录下生成 <code>content.json</code> 该文件内容即为搜索内容。</p><p>你可以对搜索内容进行自定义的配置， 只要在 <code>_config.yml</code> 中配置 <a href="https://github.com/alexbruno/hexo-generator-json-content#defaults"><code>jsonContent</code></a>即可:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"># 示例: 隐藏分类和标签的搜索</span><br><span class="line">jsonContent:</span><br><span class="line">  dateFormat: DD/MM/YYYY</span><br><span class="line">  posts:</span><br><span class="line">    title: true</span><br><span class="line">    date: true</span><br><span class="line">    path: true</span><br><span class="line">    text: true</span><br><span class="line">    raw: false</span><br><span class="line">    content: false</span><br><span class="line">    slug: false</span><br><span class="line">    updated: false</span><br><span class="line">    comments: false</span><br><span class="line">    link: false</span><br><span class="line">    permalink: false</span><br><span class="line">    excerpt: false</span><br><span class="line">    categories: false</span><br><span class="line">    tags: false</span><br><span class="line">    author: false</span><br></pre></td></tr></table></figure><h3 id="文章阅读数量统计"><a href="#文章阅读数量统计" class="headerlink" title="文章阅读数量统计"></a>文章阅读数量统计</h3><p>主题提供 <a href="http://busuanzi.ibruce.info/">不蒜子</a> 和 基于 leancloud 的统计</p><p>但是经过验证, 发现基于leancloud的统计不生效, 不知原因, 实现等效的方法就是: </p><p>评论框使用<code>valine</code>评论框(主题已经内置), 同时开启 <code>visitor: true</code> 配置项项即可</p><h3 id="字数统计-阅读时长"><a href="#字数统计-阅读时长" class="headerlink" title="字数统计&amp;阅读时长"></a>字数统计&amp;阅读时长</h3><p>主题内置了该功能, 使用前需要先安装插件:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -S hexo-wordcount</span><br></pre></td></tr></table></figure><p>主题配置文件中, 开启设置即可:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># wordcount</span><br><span class="line">postCount:</span><br><span class="line">  enable: true</span><br><span class="line">  wordcount: true  # 文章字数统计</span><br><span class="line">  min2read: true  # 阅读时长预计</span><br></pre></td></tr></table></figure><h3 id="友情链接"><a href="#友情链接" class="headerlink" title="友情链接"></a>友情链接</h3><p>复制 <code>theme/pure/_source/</code> 目录下 <code>links文件夹</code> 到 <code>blog path/source/</code> 目录下<br>在 hexo 目录下的 source 文件夹内创建一个名为 _data（禁止改名）的文件夹。</p><p>然后在文件内创建一个名为 <code>links.yml</code> 的文件,在其中添加相关数据即可。</p><p>单个友情链接的格式为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Name:</span><br><span class="line">    link: http://example.com</span><br><span class="line">    avatar: http://example.com/avatar.png</span><br><span class="line">    desc: &quot;这是一个描述&quot;</span><br></pre></td></tr></table></figure><p>添加多个友情链接，我们只需要根据上面的格式重复填写即可。</p><ul><li><p>将 Name 改为友情链接的名字，例如 Cofess。</p></li><li><p><a href="http://example.com/">http://example.com</a> 为友情链接的地址。</p></li><li><p><a href="http://example.com/avatar.png">http://example.com/avatar.png</a> 为友情链接的头像。</p></li><li><p>这是一个描述 为友情链接描述。</p></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;code&gt;hexo&lt;/code&gt; 主题 &lt;code&gt;pure&lt;/code&gt; 项目相关信息:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;预览地址: &lt;a href=&quot;https://blog.cofess.com/&quot;&gt;https://blog.cofess.com&lt;/a&gt;&lt;br&gt;项目地址: &lt;a href=&quot;https://github.com/cofess/hexo-theme-pure&quot;&gt;https://github.com/cofess/hexo-theme-pure&lt;/a&gt;&lt;br&gt;中文使用文档: &lt;a href=&quot;https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md&quot;&gt;https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="hexo" scheme="https://blog.plcent.com/categories/hexo/"/>
    
    
    <category term="hexo主题" scheme="https://blog.plcent.com/tags/hexo%E4%B8%BB%E9%A2%98/"/>
    
  </entry>
  
</feed>
