<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>LuminDream</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://www.lumindream.site/</id>
  <link href="https://www.lumindream.site/" rel="alternate"/>
  <link href="https://www.lumindream.site/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, LuminDream</rights>
  <subtitle>运维技术博客 · 书山有路勤为径</subtitle>
  <title>LuminDream's Blogs</title>
  <updated>2025-08-28T02:00:00.000Z</updated>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="随笔" scheme="https://www.lumindream.site/categories/%E9%9A%8F%E7%AC%94/"/>
    <category term="AI" scheme="https://www.lumindream.site/tags/AI/"/>
    <category term="运维" scheme="https://www.lumindream.site/tags/%E8%BF%90%E7%BB%B4/"/>
    <category term="随笔" scheme="https://www.lumindream.site/tags/%E9%9A%8F%E7%AC%94/"/>
    <content>
      <![CDATA[<h1 id="当-AI-走进运维：这半年的观察与思考"><a href="#当-AI-走进运维：这半年的观察与思考" class="headerlink" title="当 AI 走进运维：这半年的观察与思考"></a>当 AI 走进运维：这半年的观察与思考</h1><p>写这篇随笔时，正值 2025 年 8 月底。回看这一年多，AI 对运维工作的渗透比我想象中快，但方式又和很多人最初预测的不一样。趁着周末，把这段时间的观察整理成文字——不谈宏大叙事，只说我自己和身边真实发生的变化。</p><h2 id="一、它真实地改变了我的日常"><a href="#一、它真实地改变了我的日常" class="headerlink" title="一、它真实地改变了我的日常"></a>一、它真实地改变了我的日常</h2><h3 id="排障：从”搜答案”到”问模型”"><a href="#排障：从”搜答案”到”问模型”" class="headerlink" title="排障：从”搜答案”到”问模型”"></a>排障：从”搜答案”到”问模型”</h3><p>现在拿到一个报错，我的第一反应已经不是复制去搜索引擎，而是把上下文完整地丢给大模型：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 我现在喂给 AI 的&quot;排障提问模板&quot;（比直接贴一行报错有用得多）</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># 【环境】CentOS 7.9，Nginx 1.20，后端 Java 8 微服务</span></span><br><span class="line"><span class="comment"># 【现象】高峰期 502 增多，Nginx error.log 出现 upstream timed out</span></span><br><span class="line"><span class="comment"># 【已排查】后端存活、连接池未满、upstream 配置如下（贴配置）</span></span><br><span class="line"><span class="comment"># 【疑问】还有哪些方向没查？</span></span><br></pre></td></tr></table></figure><p>把环境、现象、已做过的排查都交代清楚后，模型给的”嫌疑列表”质量明显高出一截——它经常能补上我没想到的方向，比如”检查 keepalive 超时与后端半连接数”这类容易被忽略的点。它不一定直接给答案，但确实帮我缩短了定位时间，尤其是那些”我怀疑是 A，其实是 B”的场景。</p><h3 id="脚本与文档：初稿它写，质量关我把"><a href="#脚本与文档：初稿它写，质量关我把" class="headerlink" title="脚本与文档：初稿它写，质量关我把"></a>脚本与文档：初稿它写，质量关我把</h3><p>写脚本的效率提升是最直观的。以前写一个日志统计脚本，从回忆语法到调试干净要小半天；现在把需求描述清楚，模型给的初稿基本能用，我再按生产标准改：补参数校验、加失败处理、写清日志输出。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 典型协作流程（我在终端里的真实工作方式）</span></span><br><span class="line"><span class="comment"># 1. 描述需求：统计 access.log 中 5xx 占比，按小时输出，超过 10% 告警</span></span><br><span class="line"><span class="comment"># 2. 模型给初稿，我改造成巡检规范（函数、局部变量、日志落盘）</span></span><br><span class="line"><span class="comment"># 3. 手工验证两遍：造一条异常数据确认能触发告警</span></span><br></pre></td></tr></table></figure><p>文档也受益——接口变更说明、故障复盘的结构化模板，让 AI 生成初稿再人工校对，省下的时间都花在了把话说准确上。</p><h3 id="知识库：把团队的经验”喂”给-AI"><a href="#知识库：把团队的经验”喂”给-AI" class="headerlink" title="知识库：把团队的经验”喂”给 AI"></a>知识库：把团队的经验”喂”给 AI</h3><p>企业内部最大的变化，是知识库问答助手的落地。我们把历年的故障记录、变更文档、环境清单整理成语料，做检索增强问答，值班同学遇到问题先问它：</p><table><thead><tr><th>语料类型</th><th>具体内容</th><th>价值</th></tr></thead><tbody><tr><td>故障复盘</td><td>根因、处理链路、止血动作</td><td>新人不用”重新踩一遍坑”</td></tr><tr><td>变更记录</td><td>什么时间改了什么、影响面</td><td>快速定位”是不是变更引起的”</td></tr><tr><td>环境清单</td><td>机器清单、拓扑、账号归属</td><td>少问”这台是干嘛的”</td></tr><tr><td>常见问题</td><td>运维知识库 FAQ</td><td>值班第一道过滤</td></tr></tbody></table><p>以前”老员工离职知识就断了”的问题，第一次有了系统性的解法。今年年初 DeepSeek-R1 开源之后，这类私有化部署的成本变得可接受，身边不少团队都在做类似的事。</p><h2 id="二、我实际用-AI-做什么：一张分布表"><a href="#二、我实际用-AI-做什么：一张分布表" class="headerlink" title="二、我实际用 AI 做什么：一张分布表"></a>二、我实际用 AI 做什么：一张分布表</h2><table><thead><tr><th>场景</th><th>频率</th><th>AI 的角色</th><th>我的把关点</th></tr></thead><tbody><tr><td>报错分析 &#x2F; 排障方向</td><td>每天多次</td><td>给嫌疑列表</td><td>环境上下文是否交代清楚</td></tr><tr><td>脚本 &#x2F; 配置初稿</td><td>每天</td><td>写初稿</td><td>生产标准改造 + 验证</td></tr><tr><td>文档 &#x2F; 复盘结构</td><td>每周</td><td>搭框架</td><td>事实准确性</td></tr><tr><td>告警 &#x2F; 日志模式分析</td><td>每周</td><td>找规律</td><td>数据口径是否正确</td></tr><tr><td>知识库检索问答</td><td>每天</td><td>定位沉淀文档</td><td>答案要回到原文核对</td></tr></tbody></table><div class="note info flat"><p>一个值得记住的观察：<strong>AI 用得越多，越发现”把问题描述清楚”本身是稀缺能力</strong>——环境、现象、已排查项、期望输出，这些信息组织得好，AI 和同事都能更快帮你。</p></div><h2 id="三、它没有改变的东西"><a href="#三、它没有改变的东西" class="headerlink" title="三、它没有改变的东西"></a>三、它没有改变的东西</h2><p>线上出了问题，模型可以告诉我”可能的原因”，但它不会替我被扣绩效，也不会替我跟业务方解释为什么影响了半小时。故障处理里最重的部分从来不是”知道答案”，而是<strong>在信息不完整、时间紧迫、多方压力下做决策</strong>——这部分需要的不是知识，是判断和担当。</p><p>还有一个更微妙的点：模型的建议在”标准环境”里很准，在生产环境里经常差一口气。我们的环境有太多历史包袱——遗留脚本、没文档的配置、说不清来由的依赖——这些”非标准”的东西模型看不到，只有人对这套系统的理解是完整的。所以 AI 给我的建议，我默认只信一半，另一半要靠对业务和环境的理解去校准。</p><p>关于”判断力”这件事，我在之前的文章里也聊过：排障的本质不是背命令，而是沿着正确的链路缩小范围——<a href="/2023/05/17/%E8%BF%9B%E7%A8%8B%E4%B8%8E%E6%80%A7%E8%83%BD%E6%8E%92%E6%9F%A5%E5%AE%9E%E6%88%98/">《进程与性能排查实战》</a>、<a href="/2023/04/26/%E6%97%A5%E5%BF%97%E6%8E%92%E6%9F%A5%E4%BD%93%E7%B3%BBjournalctl%E4%B8%8E%E7%94%9F%E4%BA%A7%E6%97%A5%E5%BF%97%E8%BD%AE%E8%BD%AC/">《日志排查体系》</a> 里写的就是这套思路，AI 帮我把”缩小范围”这步做得更快，但”判断哪个方向值得查”仍然是人。</p><p>随着 AI 生成代码的能力变强，<strong>代码以外的质量责任反而更重了</strong>：变更的影响范围、回滚方案、监控覆盖——这些”上线前的最后一道关”，从来都是人在把。</p><h2 id="四、行业里几个真实的时间点"><a href="#四、行业里几个真实的时间点" class="headerlink" title="四、行业里几个真实的时间点"></a>四、行业里几个真实的时间点</h2><p>这几个是我确切经历过的节点，写在这里提醒自己别被一时喧嚣带偏：</p><ul><li><strong>2016 年</strong>：Gartner 提出 AIOps 概念，”智能运维”的口号喊了很多年；</li><li><strong>2021 年</strong>：GitHub Copilot 发布，代码辅助工具进入大众视野；</li><li><strong>2023 年</strong>：GPT-4、Claude 3 相继到来，大模型开始真正”能用”；</li><li><strong>2024-12</strong>：DeepSeek-V3 发布，开源模型性能第一次追上闭源第一梯队；</li><li><strong>2025-01</strong>：DeepSeek-R1 开源推理模型引爆讨论，也把”私有化部署大模型”的成本打了下来；</li><li><strong>2025 上半年</strong>：身边越来越多团队做出内部 AI 助手，AIOps 的落地场景回归理性——告警降噪、日志异常检测、根因分析辅助这三件事，做得比”端到端自动运维”实在得多。</li></ul><div class="note warning flat"><p>写到这里特别提醒自己：<strong>AI 的发展太快，任何”预测”过三个月就会失真</strong>。这篇随笔只记录 2025 年 8 月这个时点真实发生的事，不做预言。下个季度回来看，大概率又不一样了。</p></div><h2 id="五、我给自己定的三条原则"><a href="#五、我给自己定的三条原则" class="headerlink" title="五、我给自己定的三条原则"></a>五、我给自己定的三条原则</h2><ol><li><strong>把它当放大器，不当拐杖</strong>：AI 帮我做得更快的事，我要清楚每一步在干什么——它错了我也要能看出来；</li><li><strong>围绕”判断力”积累</strong>：命令和语法可以被生成，但对系统边界的理解、对风险的嗅觉、对业务的认知，只会越来越值钱；</li><li><strong>文档和知识库变成硬资产</strong>：以前写文档是交接用，现在它们还是 AI 助手的”饲料”——写清楚、结构化，AI 才能帮上忙。</li></ol><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>2025 年的这个夏天，AI 对运维来说既不是革命也不是泡沫。它更像一个”能力很强的实习生”：上手快、知识面广，但需要有人定方向、把关、兜底。而我想要的定位，就是那个把关和兜底的人——顺便把实习生用得越来越好。</p>]]>
    </content>
    <id>https://www.lumindream.site/2025/08/28/%E5%BD%93AI%E8%B5%B0%E8%BF%9B%E8%BF%90%E7%BB%B4%E8%BF%99%E5%8D%8A%E5%B9%B4%E7%9A%84%E8%A7%82%E5%AF%9F%E4%B8%8E%E6%80%9D%E8%80%83/</id>
    <link href="https://www.lumindream.site/2025/08/28/%E5%BD%93AI%E8%B5%B0%E8%BF%9B%E8%BF%90%E7%BB%B4%E8%BF%99%E5%8D%8A%E5%B9%B4%E7%9A%84%E8%A7%82%E5%AF%9F%E4%B8%8E%E6%80%9D%E8%80%83/"/>
    <published>2025-08-28T02:00:00.000Z</published>
    <summary>从 DeepSeek 开源到企业内部 AI 助手落地，一个运维工程师在 2025 年夏天的真实观察：它改变了什么、改变不了什么、以及我们该往哪走。</summary>
    <title>当 AI 走进运维：这半年的观察与思考</title>
    <updated>2025-08-28T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="Shell脚本与工具" scheme="https://www.lumindream.site/categories/Shell%E8%84%9A%E6%9C%AC%E4%B8%8E%E5%B7%A5%E5%85%B7/"/>
    <category term="JSON" scheme="https://www.lumindream.site/tags/JSON/"/>
    <category term="Shell" scheme="https://www.lumindream.site/tags/Shell/"/>
    <content>
      <![CDATA[<h1 id="JSON-速通：运维视角的配置规范与排错"><a href="#JSON-速通：运维视角的配置规范与排错" class="headerlink" title="JSON 速通：运维视角的配置规范与排错"></a>JSON 速通：运维视角的配置规范与排错</h1><p>运维每天都在和 JSON 打交道——Prometheus 告警规则、Grafana Dashboard、K8s 资源清单、各种服务配置文件，全是 JSON 或它的表亲 YAML。但大多数人只在”报错时”才想起它的语法。这篇用运维视角把 JSON 速通一遍。</p><h2 id="一、JSON-是什么（一句话）"><a href="#一、JSON-是什么（一句话）" class="headerlink" title="一、JSON 是什么（一句话）"></a>一、JSON 是什么（一句话）</h2><p><strong>JSON &#x3D; 用文本表示”键值对 + 嵌套”的数据格式</strong>，人和机器都能读。本质就是一棵树。</p><h2 id="二、只有-6-种数据类型（背下来）"><a href="#二、只有-6-种数据类型（背下来）" class="headerlink" title="二、只有 6 种数据类型（背下来）"></a>二、只有 6 种数据类型（背下来）</h2><table><thead><tr><th>类型</th><th>写法</th><th>示例</th></tr></thead><tbody><tr><td>字符串</td><td>双引号</td><td><code>&quot;nginx&quot;</code></td></tr><tr><td>数字</td><td>直接写</td><td><code>80</code>、<code>1.5</code></td></tr><tr><td>布尔</td><td>true&#x2F;false</td><td><code>true</code></td></tr><tr><td>数组</td><td>方括号</td><td><code>[&quot;a&quot;,&quot;b&quot;]</code></td></tr><tr><td>对象</td><td>花括号</td><td><code>{&quot;key&quot;:&quot;value&quot;}</code></td></tr><tr><td>空</td><td>null</td><td><code>null</code></td></tr></tbody></table><p><strong>注意：字符串必须双引号，单引号在 JSON 里是非法字符</strong>——这是新手第一大坑。</p><h2 id="三、结构速记：它就是一棵树"><a href="#三、结构速记：它就是一棵树" class="headerlink" title="三、结构速记：它就是一棵树"></a>三、结构速记：它就是一棵树</h2><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></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;server&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;host&quot;</span><span class="punctuation">:</span> <span class="string">&quot;10.0.8.11&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;port&quot;</span><span class="punctuation">:</span> <span class="number">80</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;enabled&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;tags&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;web&quot;</span><span class="punctuation">,</span> <span class="string">&quot;prod&quot;</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;note&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">null</span></span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>读法：<code>server</code> 是根对象 → 里面 5 个键值对 → <code>tags</code> 是数组。<strong>心里有一棵树，嵌套就永远不乱。</strong></p><h2 id="四、运维真实配置长什么样"><a href="#四、运维真实配置长什么样" class="headerlink" title="四、运维真实配置长什么样"></a>四、运维真实配置长什么样</h2><p>Prometheus 告警规则（每段都是”对象数组”）：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">[</span></span><br><span class="line">  <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;alert&quot;</span><span class="punctuation">:</span> <span class="string">&quot;NodeDown&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;expr&quot;</span><span class="punctuation">:</span> <span class="string">&quot;up == 0&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;for&quot;</span><span class="punctuation">:</span> <span class="string">&quot;5m&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;labels&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;severity&quot;</span><span class="punctuation">:</span> <span class="string">&quot;critical&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;annotations&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;summary&quot;</span><span class="punctuation">:</span> <span class="string">&quot;节点 &#123;&#123; $labels.instance &#125;&#125; 挂了&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">]</span></span><br></pre></td></tr></table></figure><h2 id="五、最容易写错的-7-个坑（重点看）"><a href="#五、最容易写错的-7-个坑（重点看）" class="headerlink" title="五、最容易写错的 7 个坑（重点看）"></a>五、最容易写错的 7 个坑（重点看）</h2><ol><li><strong>单引号</strong>：JSON 字符串只能用双引号；</li><li><strong>多余逗号</strong>：最后一个元素后面不能有逗号（<code>[&quot;a&quot;,&quot;b&quot;,]</code> ✗）；</li><li><strong>少了逗号</strong>：对象&#x2F;数组元素之间必须有逗号；</li><li><strong>括号不配对</strong>：花括号方括号成对出现，层数多时从里往外数；</li><li><strong>键没加引号</strong>：键必须是双引号字符串（<code>{host: &quot;x&quot;}</code> ✗，<code>{&quot;host&quot;:&quot;x&quot;}</code> ✓）；</li><li><strong>注释</strong>：JSON 不支持注释（YAML 的注释习惯别带进来）；</li><li><strong>值裸写</strong>：<code>undefined</code>、<code>NaN</code> 不是合法值，用 <code>null</code>。</li></ol><h2 id="六、怎么快速校验「我写的-JSON-对不对」"><a href="#六、怎么快速校验「我写的-JSON-对不对」" class="headerlink" title="六、怎么快速校验「我写的 JSON 对不对」"></a>六、怎么快速校验「我写的 JSON 对不对」</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><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"># jq（神器，还能提取字段）：解析失败会明确报出行列</span></span><br><span class="line">jq . config.json</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提取/过滤（运维高频）</span></span><br><span class="line">jq <span class="string">&#x27;.server.port&#x27;</span> config.json          <span class="comment"># 取值</span></span><br><span class="line">jq <span class="string">&#x27;.[] | select(.alert==&quot;NodeDown&quot;)&#x27;</span> rules.json   <span class="comment"># 过滤</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># python 兜底（没装 jq 时）</span></span><br><span class="line">python3 -m json.tool config.json</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在线校验：json.cn 等（生产环境别贴敏感配置！）</span></span><br></pre></td></tr></table></figure><h2 id="七、3-分钟上手练习"><a href="#七、3-分钟上手练习" class="headerlink" title="七、3 分钟上手练习"></a>七、3 分钟上手练习</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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 写一个 10 行配置，用 jq 校验</span></span><br><span class="line"><span class="comment"># 2. 故意写错一处（忘了逗号），看 jq 报错的行号位置</span></span><br><span class="line"><span class="comment"># 3. 用 jq 提取嵌套字段，习惯&quot;树上取值&quot;的思维</span></span><br></pre></td></tr></table></figure><h2 id="八、一句话总结"><a href="#八、一句话总结" class="headerlink" title="八、一句话总结"></a>八、一句话总结</h2><p>JSON 的规矩只有 6 种类型和 7 个坑，<strong>写完先 <code>jq .</code> 校验再贴进生产配置</strong>——这一条习惯能避开 90% 的配置文件事故。遇到 YAML&#x2F;TOML 同理，格式校验永远在”应用重启”之前。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/08/27/json%E9%80%9F%E9%80%9A%E8%BF%90%E7%BB%B4%E8%A7%86%E8%A7%92%E7%9A%84%E9%85%8D%E7%BD%AE%E8%A7%84%E8%8C%83%E4%B8%8E%E6%8E%92%E9%94%99/</id>
    <link href="https://www.lumindream.site/2023/08/27/json%E9%80%9F%E9%80%9A%E8%BF%90%E7%BB%B4%E8%A7%86%E8%A7%92%E7%9A%84%E9%85%8D%E7%BD%AE%E8%A7%84%E8%8C%83%E4%B8%8E%E6%8E%92%E9%94%99/"/>
    <published>2023-08-27T02:00:00.000Z</published>
    <summary>服务配置、Prometheus 告警规则、K8s 资源清单全是 JSON 系格式：6 种数据类型、7 个高频写错点、jq/python 快速校验，运维够用版。</summary>
    <title>JSON 速通：运维视角的配置规范与排错</title>
    <updated>2023-08-27T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="网络与安全" scheme="https://www.lumindream.site/categories/%E7%BD%91%E7%BB%9C%E4%B8%8E%E5%AE%89%E5%85%A8/"/>
    <category term="网络" scheme="https://www.lumindream.site/tags/%E7%BD%91%E7%BB%9C/"/>
    <category term="HTTP" scheme="https://www.lumindream.site/tags/HTTP/"/>
    <content>
      <![CDATA[<h1 id="HTTP-协议与-Web-服务排障"><a href="#HTTP-协议与-Web-服务排障" class="headerlink" title="HTTP 协议与 Web 服务排障"></a>HTTP 协议与 Web 服务排障</h1><p>浏览器报个 502、504，运维的第一反应应该不是”重启”,而是能准确说出这个状态码代表哪一层出了问题。这篇把 HTTP 协议的生产用法整理成一套排障体系。</p><h2 id="一、HTTP-是什么"><a href="#一、HTTP-是什么" class="headerlink" title="一、HTTP 是什么"></a>一、HTTP 是什么</h2><p>HTTP（超文本传输协议）把超文本文档从 Web 服务器传输到浏览器，应用层协议，基于 TCP 80&#x2F;443。</p><p>URL 组成：<code>协议://主机:端口/路径</code>。三个特点：</p><ol><li><strong>请求&#x2F;响应模型</strong>：客户端发请求，服务端回响应；</li><li><strong>无状态</strong>：HTTP 本身不记录用户状态（靠 Cookie&#x2F;Session 补）；</li><li><strong>基于 TCP</strong>：先三次握手，再传 HTTP 报文。</li></ol><p>一条命令看全流程（<code>curl -v</code> 是 Web 排障的第一工具）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">curl -v http://www.example.com/</span><br><span class="line"><span class="comment"># Trying 1.1.1.1...          ← DNS 解析出的 IP</span></span><br><span class="line"><span class="comment"># Connected to ...            ← TCP 连接建立（三次握手）</span></span><br><span class="line"><span class="comment"># &gt; GET /index.html HTTP/1.1  ← 发出请求</span></span><br><span class="line"><span class="comment"># &lt; HTTP/1.1 200 OK           ← 收到响应</span></span><br></pre></td></tr></table></figure><h2 id="二、请求方法与响应结构"><a href="#二、请求方法与响应结构" class="headerlink" title="二、请求方法与响应结构"></a>二、请求方法与响应结构</h2><p><strong>GET vs POST</strong>：GET 参数在 URL 里（<code>?a=1&amp;b=2</code>），POST 参数在请求体里。POST 更安全——参数不留在日志和地址栏。</p><p>响应报文：状态行（<code>HTTP/1.1 200 OK</code>）+ 头部 + 响应体。</p><h2 id="三、状态码：生产高频场景（面试必问）"><a href="#三、状态码：生产高频场景（面试必问）" class="headerlink" title="三、状态码：生产高频场景（面试必问）"></a>三、状态码：生产高频场景（面试必问）</h2><table><thead><tr><th>状态码</th><th>含义</th><th>排障方向</th></tr></thead><tbody><tr><td><strong>502 Bad Gateway</strong></td><td>反向代理连不上后端（Tomcat 挂了&#x2F;端口不通&#x2F;连接数满）</td><td><code>ss -lnt</code> 看后端端口 → tail 后端日志 → curl 后端健康检查</td></tr><tr><td><strong>504 Gateway Timeout</strong></td><td>连上了后端但响应超时（后端慢&#x2F;排队）</td><td>后端日志、慢查询、线程池满</td></tr><tr><td><strong>503 Service Unavailable</strong></td><td>服务暂时不可用（重启&#x2F;维护&#x2F;限流）</td><td>看部署状态、限流配置</td></tr><tr><td><strong>403 Forbidden</strong></td><td>无权限（nginx deny&#x2F;目录权限）</td><td>nginx 配置、文件权限</td></tr><tr><td><strong>404 Not Found</strong></td><td>资源不存在</td><td>路径写错、静态资源没部署</td></tr></tbody></table><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">curl -s -o /dev/null -w <span class="string">&quot;%&#123;http_code&#125;&quot;</span> http://localhost/   <span class="comment"># 快速看状态码</span></span><br></pre></td></tr></table></figure><h2 id="四、关键头部字段（运维用途）"><a href="#四、关键头部字段（运维用途）" class="headerlink" title="四、关键头部字段（运维用途）"></a>四、关键头部字段（运维用途）</h2><table><thead><tr><th>头部</th><th>运维用途</th></tr></thead><tbody><tr><td>Server</td><td><code>curl -I</code> 识别 Web 服务版本（安全审计&#x2F;指纹）</td></tr><tr><td>Referer</td><td>防盗链判断——图片 403 先看 Referer</td></tr><tr><td>Host</td><td>决定 Nginx 走哪个 server 块——多站点访问错页面先查 Host</td></tr><tr><td>User-Agent</td><td>区分爬虫&#x2F;正常用户（封爬虫按 UA）</td></tr></tbody></table><h2 id="五、重定向-301-302-304"><a href="#五、重定向-301-302-304" class="headerlink" title="五、重定向 301&#x2F;302&#x2F;304"></a>五、重定向 301&#x2F;302&#x2F;304</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">301 永久重定向：域名换了 / HTTP 跳 HTTPS（SEO 权重转移）</span><br><span class="line">302 临时重定向：临时跳转（登录后跳回、活动页）</span><br><span class="line">304 Not Modified：资源没变直接用缓存（配合 Last-Modified/ETag）</span><br></pre></td></tr></table></figure><p>Nginx 配置示例：</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line">    <span class="attribute">server_name</span> www.example.com;</span><br><span class="line">    <span class="attribute">return</span> <span class="number">301</span> https://<span class="variable">$host</span><span class="variable">$request_uri</span>;   <span class="comment"># HTTP 全站跳 HTTPS</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="六、PV-UV-IP（站长口径）"><a href="#六、PV-UV-IP（站长口径）" class="headerlink" title="六、PV &#x2F; UV &#x2F; IP（站长口径）"></a>六、PV &#x2F; UV &#x2F; IP（站长口径）</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">PV（Page View）：页面浏览量，一个人点 2 次算 2 个 PV</span><br><span class="line">UV（Unique Visitor）：独立访客（去重 Cookie/设备），只算 1 个</span><br><span class="line">IP：独立 IP 数（同一 NAT 出口只算 1 个）</span><br></pre></td></tr></table></figure><p>经典计算题：公司大厦 100 人、每人 2 台设备、走同一个 NAT 出口、每人点 2 次 → PV&#x3D;400、UV&#x3D;200、IP&#x3D;1。<strong>PV ≥ UV ≥ IP 永远成立</strong>；IP 在 NAT 场景只是近似值。</p><h2 id="七、Web-全链路排障（面试讲故障故事用）"><a href="#七、Web-全链路排障（面试讲故障故事用）" class="headerlink" title="七、Web 全链路排障（面试讲故障故事用）"></a>七、Web 全链路排障（面试讲故障故事用）</h2><p>用户报”网站打不开”，从外层到内层逐层看：</p><figure class="highlight text"><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">用户浏览器 → DNS 解析 → 防火墙/安全组 → 负载均衡健康检查 → Nginx 日志</span><br><span class="line">(access/error) → Tomcat 日志 → MySQL 慢查询 → 监控图（Zabbix/Prometheus）</span><br></pre></td></tr></table></figure><p>入门手段永远是一句话：<strong>先 curl 本地确认服务在，再一层层往外查</strong>。用户反馈”打开慢”时用浏览器 F12 → Network → Timing 看各段耗时，定位是 DNS 慢、TCP 慢还是 TTFB（服务端处理慢）——比瞎猜快得多。</p><p>HTTP 这一层是 Web 排障的”界面层”：状态码告诉你错在哪一段，头部告诉你细节，curl 帮你复现全过程。配合前面的 TCP 和 DNS 知识，一条链路就完整了。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/08/24/http%E5%8D%8F%E8%AE%AE%E4%B8%8Eweb%E6%9C%8D%E5%8A%A1%E6%8E%92%E9%9A%9C/</id>
    <link href="https://www.lumindream.site/2023/08/24/http%E5%8D%8F%E8%AE%AE%E4%B8%8Eweb%E6%9C%8D%E5%8A%A1%E6%8E%92%E9%9A%9C/"/>
    <published>2023-08-24T02:00:00.000Z</published>
    <summary>网站报错怎么快速定位：HTTP 报文结构、请求方法、状态码语义（502/504/503/403/404）、关键头部字段、301/302/304 区别，以及全链路排查流程。</summary>
    <title>HTTP 协议与 Web 服务排障</title>
    <updated>2023-08-24T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="网络与安全" scheme="https://www.lumindream.site/categories/%E7%BD%91%E7%BB%9C%E4%B8%8E%E5%AE%89%E5%85%A8/"/>
    <category term="DNS" scheme="https://www.lumindream.site/tags/DNS/"/>
    <category term="网络" scheme="https://www.lumindream.site/tags/%E7%BD%91%E7%BB%9C/"/>
    <content>
      <![CDATA[<h1 id="DNS-解析原理与排障实战"><a href="#DNS-解析原理与排障实战" class="headerlink" title="DNS 解析原理与排障实战"></a>DNS 解析原理与排障实战</h1><p>“网站打不开”的排查里，DNS 是最容易被忽略、又最常出问题的一层——IP 能访问、域名不能，十有八九就是它。这篇把 DNS 的完整解析流程和排障方法讲透。</p><h2 id="一、DNS-是什么"><a href="#一、DNS-是什么" class="headerlink" title="一、DNS 是什么"></a>一、DNS 是什么</h2><p>DNS（域名系统）把域名翻译成 IP，好比电话簿：记名字不记号码。端口：一般走 <strong>UDP 53</strong>，数据量大或区域传输时走 <strong>TCP 53</strong>。</p><p>常用记录类型：</p><table><thead><tr><th>记录</th><th>作用</th><th>示例</th></tr></thead><tbody><tr><td>A</td><td>域名 → IPv4</td><td><a href="http://www.example.com/">www.example.com</a> → 1.1.1.1</td></tr><tr><td>AAAA</td><td>域名 → IPv6</td><td>—</td></tr><tr><td>CNAME</td><td>别名（CDN 加速常用）</td><td>www 指向 cdn.example.com</td></tr></tbody></table><p>常用公共 DNS：阿里 <code>223.5.5.5</code>、腾讯 <code>119.29.29.29</code>、<code>114.114.114.114</code>、谷歌 <code>8.8.8.8</code>。</p><h2 id="二、完整解析流程（递归-迭代）"><a href="#二、完整解析流程（递归-迭代）" class="headerlink" title="二、完整解析流程（递归 + 迭代）"></a>二、完整解析流程（递归 + 迭代）</h2><p>以浏览器输入 <code>www.baidu.com</code> 为例：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">第1步 查浏览器缓存</span><br><span class="line">第2步 查操作系统缓存</span><br><span class="line">第3步 查本地 hosts 文件（Windows: C:\Windows\System32\drivers\etc\hosts；Linux: /etc/hosts）</span><br><span class="line">第4步 都没命中 → 请求本地 DNS 服务器（LDNS，如 223.5.5.5）【递归查询】</span><br><span class="line">第5步 LDNS 先查自己的缓存，没有则开始【迭代查询】：</span><br><span class="line">   ① LDNS 问根域名服务器&quot;.&quot;（全球 13 个根，内置在 LDNS 里）</span><br><span class="line">   ② 根服务器返回 .com 顶级域服务器 IP</span><br><span class="line">   ③ LDNS 问 .com 顶级域服务器 → 返回 baidu.com 权威服务器 IP</span><br><span class="line">   ④ LDNS 问 baidu.com 权威服务器 → 权威服务器查 A 记录，返回 www.baidu.com 的 IP</span><br><span class="line">第6步 LDNS 缓存一份，把 IP 返回给客户端；客户端也缓存一份</span><br><span class="line">第7步 浏览器用 IP 与服务器建立 TCP 连接</span><br></pre></td></tr></table></figure><p>两种查询方式（面试必答）：</p><ul><li><strong>递归查询</strong>：客户端 → 本地 DNS。客户端只问一次，LDNS 负责跑腿；</li><li><strong>迭代查询</strong>：本地 DNS → 根 → 顶级 → 权威。LDNS 逐级问，每级只告诉”下一级去哪问”。</li></ul><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><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">yum install -y bind-utils</span><br><span class="line"></span><br><span class="line">dig www.baidu.com            <span class="comment"># 最详细（推荐）</span></span><br><span class="line">dig +trace www.baidu.com     <span class="comment"># 看完整迭代链路（劫持排查神器）</span></span><br><span class="line">nslookup www.baidu.com       <span class="comment"># 基础查询</span></span><br><span class="line">host www.baidu.com           <span class="comment"># 精简查询</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 常见排查点：</span></span><br><span class="line"><span class="built_in">cat</span> /etc/resolv.conf         <span class="comment"># nameserver 配置</span></span><br><span class="line">grep domain /etc/hosts       <span class="comment"># hosts 有没有被污染</span></span><br></pre></td></tr></table></figure><h2 id="四、三个真实故障案例"><a href="#四、三个真实故障案例" class="headerlink" title="四、三个真实故障案例"></a>四、三个真实故障案例</h2><h3 id="案例-1：网站突然打不开，IP-能访问、域名不能"><a href="#案例-1：网站突然打不开，IP-能访问、域名不能" class="headerlink" title="案例 1：网站突然打不开，IP 能访问、域名不能"></a>案例 1：网站突然打不开，IP 能访问、域名不能</h3><p>排查链路：<code>nslookup 域名</code> → 超时&#x2F;无记录 → 查 <code>/etc/resolv.conf</code> → 发现 nameserver 写的是内网 DNS → 换 <code>223.5.5.5</code> 立即可解析。</p><p>根因：公司内网 DNS 故障&#x2F;上游被污染。解决：切换 DNS 或同时配置多个 nameserver（<code>nameserver 223.5.5.5</code> + <code>nameserver 114.114.114.114</code>）。</p><h3 id="案例-2：dig-trace-发现权威服务器返回异常-IP（域名被劫持）"><a href="#案例-2：dig-trace-发现权威服务器返回异常-IP（域名被劫持）" class="headerlink" title="案例 2：dig +trace 发现权威服务器返回异常 IP（域名被劫持）"></a>案例 2：dig +trace 发现权威服务器返回异常 IP（域名被劫持）</h3><p>现象：解析结果指向一个不明 IP，访问弹广告。</p><p>处理：联系域名服务商核查解析记录；检查是否有 CNAME 被篡改；确认域名管理后台没有被盗号（查登录记录、改强密码）。</p><h3 id="案例-3：CDN-切换后部分地区访问慢"><a href="#案例-3：CDN-切换后部分地区访问慢" class="headerlink" title="案例 3：CDN 切换后部分地区访问慢"></a>案例 3：CDN 切换后部分地区访问慢</h3><p>现象：CDN 配置已切换，但部分用户还访问旧节点。</p><p>根因：<strong>LDNS 缓存了旧 IP，TTL 未到</strong>。处理：等 TTL 过期，或通知运营商刷新缓存。</p><p><strong>生产规范</strong>：改解析前先看当前 TTL，<strong>提前把 TTL 调小（如 300 秒）再改记录，改完再恢复 TTL</strong>——避免切换后长时间缓存旧地址。</p><h2 id="五、DNS-排障心法"><a href="#五、DNS-排障心法" class="headerlink" title="五、DNS 排障心法"></a>五、DNS 排障心法</h2><p>遇到”域名不通”，按这个顺序走：<strong>本机 dig 看解析结果 → hosts 有没有污染 → resolv.conf 对不对 → 换公共 DNS 交叉验证 → dig +trace 看链路 → 联系域名服务商</strong>。其中”换公共 DNS 交叉验证”能快速区分是”本地 DNS 问题”还是”权威解析问题”，是效率最高的一步。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/08/17/dns%E8%A7%A3%E6%9E%90%E5%8E%9F%E7%90%86%E4%B8%8E%E6%8E%92%E9%9A%9C%E5%AE%9E%E6%88%98/</id>
    <link href="https://www.lumindream.site/2023/08/17/dns%E8%A7%A3%E6%9E%90%E5%8E%9F%E7%90%86%E4%B8%8E%E6%8E%92%E9%9A%9C%E5%AE%9E%E6%88%98/"/>
    <published>2023-08-17T02:00:00.000Z</published>
    <summary>网站打不开先查 DNS：递归与迭代查询全流程、dig/nslookup/host 用法、三个真实解析故障案例（解析超时/被劫持/CDN 缓存）。</summary>
    <title>DNS 解析原理与排障实战</title>
    <updated>2023-08-17T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="网络与安全" scheme="https://www.lumindream.site/categories/%E7%BD%91%E7%BB%9C%E4%B8%8E%E5%AE%89%E5%85%A8/"/>
    <category term="网络" scheme="https://www.lumindream.site/tags/%E7%BD%91%E7%BB%9C/"/>
    <category term="TCP" scheme="https://www.lumindream.site/tags/TCP/"/>
    <content>
      <![CDATA[<h1 id="TCP-协议实战：握手、挥手与连接排障"><a href="#TCP-协议实战：握手、挥手与连接排障" class="headerlink" title="TCP 协议实战：握手、挥手与连接排障"></a>TCP 协议实战：握手、挥手与连接排障</h1><p>TCP 是面试必问、排障必用的核心协议。三次握手为什么是三次？大量 CLOSE_WAIT 怎么办？这篇把原理和排障串成一条线，附抓包实证。</p><h2 id="一、TCP-vs-UDP：先分清楚"><a href="#一、TCP-vs-UDP：先分清楚" class="headerlink" title="一、TCP vs UDP：先分清楚"></a>一、TCP vs UDP：先分清楚</h2><table><thead><tr><th>特性</th><th>TCP</th><th>UDP</th></tr></thead><tbody><tr><td>连接</td><td>面向连接（三次握手）</td><td>无连接</td></tr><tr><td>可靠</td><td>可靠（确认重传）</td><td>不可靠</td></tr><tr><td>效率</td><td>低</td><td>高</td></tr><tr><td>应用</td><td>HTTP&#x2F;HTTPS、邮件、FTP</td><td>DNS(53)、视频流、语音、DHCP</td></tr></tbody></table><p>类比记忆：TCP 是”外卖必须送到你手里（有确认）”，UDP 是”放门口就走（无确认）”。端口范围 1~65535。</p><h2 id="二、三次握手（原理-抓包）"><a href="#二、三次握手（原理-抓包）" class="headerlink" title="二、三次握手（原理 + 抓包）"></a>二、三次握手（原理 + 抓包）</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><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">客户端 C                          服务端 S</span><br><span class="line">   │  SYN(seq=x)                    │</span><br><span class="line">   │───────────────────────────────&gt;│  S 收到，状态 SYN_RCVD</span><br><span class="line">   │  SYN+ACK(seq=y, ack=x+1)       │</span><br><span class="line">   │&lt;───────────────────────────────│</span><br><span class="line">   │  ACK(ack=y+1)                  │</span><br><span class="line">   │───────────────────────────────&gt;│  连接建立</span><br></pre></td></tr></table></figure><p>三个关键点（面试背诵版）：</p><ol><li><strong>SYN 报文不携带数据，但消耗一个序列号</strong>；</li><li><strong>第 2 次握手把”确认 ACK”和”请求 SYN”合并成一个报文</strong>——所以是三次不是四次；</li><li>seq&#x2F;ack 都 +1 是确认机制核心：<code>ack = 对方 seq + 1</code>，表示”下次该收 x+1 了”。</li></ol><p>抓包实证（tcpdump 抓 80 端口）看三个包的 seq&#x2F;ack 严格递进——<code>第 2 个包 ack = 第 1 个包 seq+1</code>。</p><p><strong>为什么不能只有两次握手？</strong> 场景：客户端发出 SYN 在网络滞留，超时重发后正常完成连接并释放；此时滞留的旧 SYN 才到达服务端——如果只有两次握手，服务端会为这个”已失效的请求”建立连接并一直占用资源。<strong>三次握手里，服务端发出 SYN+ACK 后必须等客户端的 ACK 才建立</strong>——客户端没发新请求就不会回 ACK，服务端等不到就自动放弃。一句话：<strong>两次握手无法确认”客户端能收到服务端的报文”，也无法拒绝失效的旧请求</strong>。</p><h2 id="三、四次挥手与-2MSL"><a href="#三、四次挥手与-2MSL" class="headerlink" title="三、四次挥手与 2MSL"></a>三、四次挥手与 2MSL</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">客户端 C                            服务端 S</span><br><span class="line">   │  FIN(seq=m)                     │</span><br><span class="line">   │───────────────────────────────&gt;│</span><br><span class="line">   │  ACK(ack=m+1)                   │  S 还有数据要发，先确认</span><br><span class="line">   │&lt;───────────────────────────────│</span><br><span class="line">   │   ...S 继续发剩余数据...          │</span><br><span class="line">   │  FIN(seq=n)                     │</span><br><span class="line">   │&lt;───────────────────────────────│</span><br><span class="line">   │  ACK(ack=n+1)                   │  C 进入 TIME_WAIT，等 2MSL</span><br><span class="line">   │───────────────────────────────&gt;│</span><br></pre></td></tr></table></figure><p><strong>为什么挥手 4 次而握手 3 次？</strong> 握手时服务端可以把”确认+请求”合并成一个包（SYN+ACK）；挥手时服务端收到 FIN 后<strong>可能还有数据要发，不能立刻 FIN</strong>，必须先 ACK 再等数据发完单独 FIN——所以多一次。</p><p><strong>挥手后客户端为什么要等 2MSL（Linux 默认约 60s）？</strong></p><ol><li>最后的 ACK 可能丢失——服务端没收到会重发 FIN，客户端在 TIME_WAIT 期间还能再回一次 ACK；</li><li>保证旧报文在网络中彻底消失，不会污染新连接。</li></ol><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></pre></td><td class="code"><pre><span class="line">ss -tulnp    <span class="comment"># 查看连接状态统计</span></span><br><span class="line">ss -s        <span class="comment"># 汇总</span></span><br></pre></td></tr></table></figure><p>三类生产高频异常：</p><table><thead><tr><th>状态</th><th>含义</th><th>处理</th></tr></thead><tbody><tr><td>大量 <strong>CLOSE_WAIT</strong></td><td>对端关了，<strong>应用没关连接</strong>（代码层泄漏）</td><td>查应用：Java 连接池泄漏、请求未关闭；<code>ss -lnt | grep CLOSE_WAIT</code> 确认，修代码&#x2F;调连接池</td></tr><tr><td>大量 <strong>TIME_WAIT</strong></td><td>主动断开方等待 2MSL</td><td>高并发短连接的正常现象；用 keep-alive 连接复用减少；<code>net.ipv4.tcp_tw_reuse=1</code> 谨慎开启</td></tr><tr><td>大量 <strong>SYN_RCVD</strong></td><td>收到 SYN 未完成握手，半连接堆积</td><td>可能被 SYN 洪水攻击；查半连接队列 <code>ss -lnt | grep SYN</code>，上限 <code>net.ipv4.tcp_max_syn_backlog</code>，配合防火墙限速</td></tr></tbody></table><p><strong>连接不上的四步排查</strong>（任何”连不上”都按这个顺序）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1. ss -lnt            <span class="comment"># 服务有没有监听</span></span><br><span class="line">2. telnet IP 端口      <span class="comment"># 端口通不通（不通→防火墙/安全组）</span></span><br><span class="line">3. 本机 curl           <span class="comment"># 服务本身是否正常</span></span><br><span class="line">4. 抓包看握手          <span class="comment"># tcpdump -i eth0 port 端口：SYN 有没有到、有没有回 SYN-ACK</span></span><br></pre></td></tr></table></figure><p>TCP 的问题说到底是”连接建不起来（握手）”和”连接关不掉（挥手&#x2F;资源泄漏）”两类。把状态机和排障命令对应起来，大部分网络故障都能落地到具体的一层。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/08/10/tcp%E5%8D%8F%E8%AE%AE%E5%AE%9E%E6%88%98%E6%8F%A1%E6%89%8B%E6%8C%A5%E6%89%8B%E4%B8%8E%E8%BF%9E%E6%8E%A5%E6%8E%92%E9%9A%9C/</id>
    <link href="https://www.lumindream.site/2023/08/10/tcp%E5%8D%8F%E8%AE%AE%E5%AE%9E%E6%88%98%E6%8F%A1%E6%89%8B%E6%8C%A5%E6%89%8B%E4%B8%8E%E8%BF%9E%E6%8E%A5%E6%8E%92%E9%9A%9C/"/>
    <published>2023-08-10T02:00:00.000Z</published>
    <summary>面试必问、生产必用的 TCP：三次握手为什么是三次、四次挥手为什么要等 2MSL、CLOSE_WAIT/TIME_WAIT/SYN_RCVD 三种异常状态的排查与处理。</summary>
    <title>TCP 协议实战：握手、挥手与连接排障</title>
    <updated>2023-08-10T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="网络与安全" scheme="https://www.lumindream.site/categories/%E7%BD%91%E7%BB%9C%E4%B8%8E%E5%AE%89%E5%85%A8/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="网络基础" scheme="https://www.lumindream.site/tags/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80/"/>
    <category term="IP" scheme="https://www.lumindream.site/tags/IP/"/>
    <content>
      <![CDATA[<h1 id="网络基础与-IP-子网规划实战"><a href="#网络基础与-IP-子网规划实战" class="headerlink" title="网络基础与 IP 子网规划实战"></a>网络基础与 IP 子网规划实战</h1><p>网络是运维一切排障的地基。报障电话里”上不了网””跨网段不通”的根因，80% 落在 IP 规划、掩码、网关这三件事上。这篇把网络基础与 IP 子网规划完整过一遍。</p><h2 id="一、网络单位换算（先把这个算明白）"><a href="#一、网络单位换算（先把这个算明白）" class="headerlink" title="一、网络单位换算（先把这个算明白）"></a>一、网络单位换算（先把这个算明白）</h2><p>网络里最常见的”看起来很快”陷阱：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">100Mbps 网卡 = 每秒传输 100M 个 bit</span><br><span class="line">1 byte = 8 bit</span><br><span class="line">100Mbps = 100000/8 KByte/s = 12500 KB/s ≈ 12.5 MB/s</span><br><span class="line">千兆网卡 = 100 MB/s</span><br></pre></td></tr></table></figure><p><strong>所以百兆网卡实际跑 12.5MB&#x2F;s 是”满速”</strong>，不是网卡坏了。存储单位按 1024 进制（K&#x2F;M&#x2F;G&#x2F;T），网络单位按 1000 进制，这个差异也是排障时对不上数的主要原因。</p><h2 id="二、网络设备三个角色"><a href="#二、网络设备三个角色" class="headerlink" title="二、网络设备三个角色"></a>二、网络设备三个角色</h2><ul><li><strong>交换机（二层）</strong>：让同一网络内的多台主机互通。靠 MAC 地址寻址（网卡物理地址，全球唯一，16 进制）。早期靠广播发数据，广播太多会形成”广播风暴”——拆成多个小局域网（广播域）解决；</li><li><strong>路由器（三层）</strong>：实现不同局域网互通，隔离广播风暴。路由 &#x3D; 数据跨网段到达目的地的传递过程；</li><li><strong>网关</strong>：去往其他网段的必经之路（路由器的 IP）。<strong>看路由表</strong>：</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">route -n</span><br><span class="line"><span class="comment"># 0.0.0.0  10.0.8.254  0.0.0.0  UG  eth0   ← 默认路由，10.0.8.254 是网关</span></span><br></pre></td></tr></table></figure><p>口诀记忆：<strong>交换机 &#x3D; 认识的人（局域网内），路由器 &#x3D; 朋友介绍的朋友（跨网段）</strong>。</p><h2 id="三、分层模型：OSI-七层-vs-TCP-IP-四层"><a href="#三、分层模型：OSI-七层-vs-TCP-IP-四层" class="headerlink" title="三、分层模型：OSI 七层 vs TCP&#x2F;IP 四层"></a>三、分层模型：OSI 七层 vs TCP&#x2F;IP 四层</h2><p>OSI 七层（从下到上）：物理层 → 数据链路层 → 网络层 → 传输层 → 会话层 → 表示层 → 应用层。实际用的是 TCP&#x2F;IP 四层（网络接口&#x2F;网络&#x2F;传输&#x2F;应用）。</p><p><strong>数据封装与解封装</strong>：</p><figure class="highlight text"><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">发送（封装，从上到下逐层加头）：应用 → TCP头+数据 → IP头+TCP头+数据 → 帧头+... → 比特流</span><br><span class="line">接收（解封装，从下到上逐层去头）：逆过程</span><br></pre></td></tr></table></figure><p>排障时”数据走到哪一层断了”是核心思路：物理层不通看网线&#x2F;网卡，网络层不通看 IP&#x2F;路由，传输层不通看端口，应用层不通看服务。</p><h2 id="四、IP-地址与子网划分"><a href="#四、IP-地址与子网划分" class="headerlink" title="四、IP 地址与子网划分"></a>四、IP 地址与子网划分</h2><h3 id="分类与私有地址"><a href="#分类与私有地址" class="headerlink" title="分类与私有地址"></a>分类与私有地址</h3><p>IP &#x3D; 网络号 + 主机号。公网地址全球唯一（Inter NIC 分配），私网地址组织内部使用可重复（RFC 1918）：</p><figure class="highlight text"><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">A类 10.0.0.0/8        B类 172.16.0.0/12      C类 192.168.0.0/16</span><br><span class="line">默认掩码：/8=255.0.0.0   /16=255.255.0.0       /24=255.255.255.0</span><br></pre></td></tr></table></figure><h3 id="子网掩码与可用主机数"><a href="#子网掩码与可用主机数" class="headerlink" title="子网掩码与可用主机数"></a>子网掩码与可用主机数</h3><p>掩码的作用：区分网络号与主机号（网络位为 1，主机位为 0）。</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">一个网段可用地址 = 2^n - 2（n=主机位数，去掉网络地址和广播地址）</span><br><span class="line">/24：2^8-2 = 254 台可用</span><br><span class="line">/29：2^3-2 = 6 台可用</span><br><span class="line">/30：2^2-2 = 2 台（点对点链路常用）</span><br></pre></td></tr></table></figure><h3 id="子网划分（向主机位借位）"><a href="#子网划分（向主机位借位）" class="headerlink" title="子网划分（向主机位借位）"></a>子网划分（向主机位借位）</h3><p>生产场景：运营商给了 <code>116.63.0.10/29</code>——实际可用 6 个 IP（网络地址 .9 之后的 6 个，网关一般用第一个可用）。</p><figure class="highlight text"><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">172.20.1.0/18 → 掩码 255.255.192.0</span><br><span class="line">（11111111 11111111 11000000 00000000，网络位 18 位）</span><br></pre></td></tr></table></figure><p>划分的意义：<strong>防止地址浪费、隔离广播域、降低网关负载</strong>。计算工具用 subnet 计算器，但面试和排障要能手算掩码和可用数。</p><h3 id="VLSM-CIDR"><a href="#VLSM-CIDR" class="headerlink" title="VLSM &#x2F; CIDR"></a>VLSM &#x2F; CIDR</h3><ul><li>VLSM：可变长子网掩码——大段里再细分小段（如 &#x2F;24 拆 4 个 &#x2F;26）；</li><li>CIDR：无类域间路由——<code>/n</code> 记法的来源，IP 段合并表达（如 10.0.8.0&#x2F;24 表示整个网段）。</li></ul><h2 id="五、Linux-网卡配置（CentOS-7）"><a href="#五、Linux-网卡配置（CentOS-7）" class="headerlink" title="五、Linux 网卡配置（CentOS 7）"></a>五、Linux 网卡配置（CentOS 7）</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><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 文件：/etc/sysconfig/network-scripts/ifcfg-eth0</span></span><br><span class="line">TYPE=Ethernet</span><br><span class="line">BOOTPROTO=none          <span class="comment"># 服务器固定 IP</span></span><br><span class="line">IPADDR=10.0.8.11</span><br><span class="line">PREFIX=24</span><br><span class="line">GATEWAY=10.0.8.1</span><br><span class="line">DNS1=223.5.5.5</span><br><span class="line">ONBOOT=<span class="built_in">yes</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 生效：systemctl restart network（或 nmcli con reload）</span></span><br><span class="line"><span class="comment"># 临时加 IP（重启失效）：</span></span><br><span class="line">ip addr add 10.0.8.12/24 dev eth0</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><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">ping -c3 10.0.8.1            <span class="comment"># 连通性（不通 ≠ 不可达——可能禁 ICMP）</span></span><br><span class="line">traceroute www.example.com    <span class="comment"># 路由跟踪，看卡在哪一跳（跨机房慢排查）</span></span><br><span class="line">telnet 10.0.8.11 3306        <span class="comment"># 端口通不通（服务级别，比 ping 高一层）</span></span><br><span class="line">nc -vz 10.0.8.11 22          <span class="comment"># netcat 快速端口检测</span></span><br><span class="line">ss -tulnp                    <span class="comment"># 监听端口与状态（比 netstat 快）</span></span><br><span class="line">ss -lnt | grep SYN           <span class="comment"># 半连接队列（SYN 洪水排查）</span></span><br><span class="line">tcpdump -i eth0 tcp port 22  <span class="comment"># 抓包（看握手、看请求有没有到本机）</span></span><br><span class="line">nmap -sT -p 80,443 10.0.8.11 <span class="comment"># 端口扫描（只扫自己管理的资产！）</span></span><br><span class="line">route -n                     <span class="comment"># 路由表</span></span><br><span class="line">curl -v http://10.0.8.11/    <span class="comment"># 应用层连通 + 全流程</span></span><br></pre></td></tr></table></figure><p><strong>上不了网排查流程（从下往上逐层排除）</strong>：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">1. 网卡/物理层：ip a 看 IP 有没有、网线灯亮不亮</span><br><span class="line">2. 网络层：ping 网关 → 通了说明本段通；ping 公网 IP（如 223.5.5.5）→ 不通查路由</span><br><span class="line">3. 传输层：telnet 目标端口</span><br><span class="line">4. 应用层：DNS 能不能解析（nslookup）、服务起没起</span><br></pre></td></tr></table></figure><p>哪一层断了就处理哪一层——这是网络排障唯一正确的打开方式。下一篇把 TCP 协议本身讲透。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/08/03/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80%E4%B8%8EIP%E5%AD%90%E7%BD%91%E8%A7%84%E5%88%92%E5%AE%9E%E6%88%98/</id>
    <link href="https://www.lumindream.site/2023/08/03/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80%E4%B8%8EIP%E5%AD%90%E7%BD%91%E8%A7%84%E5%88%92%E5%AE%9E%E6%88%98/"/>
    <published>2023-08-03T02:00:00.000Z</published>
    <summary>从网速换算到子网划分：网络单位与设备、OSI/TCP/IP 分层、IP 分类与子网掩码、借位划分与 VLSM/CIDR，附网卡配置和常用排障命令。</summary>
    <title>网络基础与 IP 子网规划实战</title>
    <updated>2023-08-03T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="rsync" scheme="https://www.lumindream.site/tags/rsync/"/>
    <category term="备份" scheme="https://www.lumindream.site/tags/%E5%A4%87%E4%BB%BD/"/>
    <category term="定时任务" scheme="https://www.lumindream.site/tags/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1/"/>
    <content>
      <![CDATA[<h1 id="定时备份与实时同步落地：cron-rsync-sersync"><a href="#定时备份与实时同步落地：cron-rsync-sersync" class="headerlink" title="定时备份与实时同步落地：cron + rsync + sersync"></a>定时备份与实时同步落地：cron + rsync + sersync</h1><p>上一篇配好了 rsync 备份通道，但”能传”不等于”可靠”。真正的企业备份要有三件事：<strong>定时自动跑、校验完整性、失败要告警</strong>。这篇把备份闭环补完，再加一份”实时同步”方案。</p><h2 id="一、定时备份：一个完整的客户端脚本"><a href="#一、定时备份：一个完整的客户端脚本" class="headerlink" title="一、定时备份：一个完整的客户端脚本"></a>一、定时备份：一个完整的客户端脚本</h2><p>脚本职责：打包要备份的内容 → 携带 md5 校验信息 → 推送到备份服务器 → 本地只留最近 7 天。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># 客户端备份脚本：/server/scripts/client_rsync_backup.sh</span></span><br><span class="line"><span class="comment"># 1. 定义变量</span></span><br><span class="line">BACKUP_SERVER=<span class="string">&quot;backup-server&quot;</span></span><br><span class="line">BACKUP_MODULE=<span class="string">&quot;web01&quot;</span></span><br><span class="line">SRC_DIR=<span class="string">&quot;/server/scripts /etc/nginx /var/www&quot;</span></span><br><span class="line">DST=<span class="string">&quot;/backup&quot;</span></span><br><span class="line">TS=$(<span class="built_in">date</span> +%F)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 创建备份目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="variable">$DST</span>/<span class="variable">$TS</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 打包对应文件（已存在不重复打包）</span></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$SRC_DIR_ROOT</span> 2&gt;/dev/null</span><br><span class="line">[ -f <span class="variable">$DST</span>/<span class="variable">$TS</span>/scripts.tar.gz ] || tar zcf <span class="variable">$DST</span>/<span class="variable">$TS</span>/scripts.tar.gz -C /server scripts</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 携带 md5 校验信息</span></span><br><span class="line">find <span class="variable">$DST</span>/<span class="variable">$TS</span> -<span class="built_in">type</span> f -name <span class="string">&quot;*.tar.gz&quot;</span> | xargs <span class="built_in">md5sum</span> &gt; <span class="variable">$DST</span>/<span class="variable">$TS</span>/md5_<span class="variable">$TS</span>.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 推送至备份服务器</span></span><br><span class="line">rsync -av --password-file=/etc/rsync.pass <span class="variable">$DST</span>/ rsync://<span class="variable">$BACKUP_SERVER</span>::<span class="variable">$BACKUP_MODULE</span>/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 本地保留最近 7 天</span></span><br><span class="line">find <span class="variable">$DST</span> -mtime +7 -<span class="built_in">exec</span> <span class="built_in">rm</span> -rf &#123;&#125; \;</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 每天 01:00 执行</span><br><span class="line">0 1 * * * /server/scripts/client_rsync_backup.sh &gt;&gt; /var/log/backup.log 2&gt;&amp;1</span><br></pre></td></tr></table></figure><h2 id="二、校验-邮件告警（服务端）"><a href="#二、校验-邮件告警（服务端）" class="headerlink" title="二、校验 + 邮件告警（服务端）"></a>二、校验 + 邮件告警（服务端）</h2><p>备份传完不算完，还得确认<strong>备份是完整的</strong>。服务端每天对账：用客户端留下的 md5 文件校验落盘数据，结果发邮件给管理员。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># 服务端校验脚本：/server/scripts/check_backup.sh</span></span><br><span class="line"><span class="comment"># 1. 定义变量</span></span><br><span class="line">BACKUP_DIR=<span class="string">&quot;/backup/web01&quot;</span></span><br><span class="line">TS=$(<span class="built_in">date</span> +%F)</span><br><span class="line">MAIL_TO=<span class="string">&quot;ops@example.com&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 用 flag 文件做 md5 校验，结果存 result_日期</span></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$BACKUP_DIR</span></span><br><span class="line">[ -f <span class="variable">$TS</span>/md5_<span class="variable">$TS</span>.txt ] || <span class="built_in">exit</span> 1</span><br><span class="line"><span class="built_in">md5sum</span> -c <span class="variable">$TS</span>/md5_<span class="variable">$TS</span>.txt &gt; result_<span class="variable">$TS</span>.txt 2&gt;&amp;1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 把校验结果发给管理员</span></span><br><span class="line">mailx -s <span class="string">&quot;web01 备份校验 <span class="subst">$(date +%F)</span>&quot;</span> <span class="variable">$MAIL_TO</span> &lt; result_<span class="variable">$TS</span>.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 清理：删除超过 7 天的校验结果、超过 180 天的备份数据</span></span><br><span class="line">find <span class="variable">$BACKUP_DIR</span> -name <span class="string">&quot;result_*&quot;</span> -mtime +7 -delete</span><br><span class="line">find <span class="variable">$BACKUP_DIR</span> -<span class="built_in">type</span> d -mtime +180 -<span class="built_in">exec</span> <span class="built_in">rm</span> -rf &#123;&#125; \;</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 每天 05:00 执行校验（备份 01:00 完成后，留足传输时间）</span><br><span class="line">0 5 * * * /server/scripts/check_backup.sh</span><br></pre></td></tr></table></figure><p>没有变量的备份是”假备份”，而这个闭环是：<strong>传完即校验、校验完即告警、告警完留痕</strong>。</p><h2 id="三、实时同步：sersync（rsync-inotify）"><a href="#三、实时同步：sersync（rsync-inotify）" class="headerlink" title="三、实时同步：sersync（rsync + inotify）"></a>三、实时同步：sersync（rsync + inotify）</h2><p>定时任务有延迟——文件刚被篡改、或者业务要求秒级同步时，要用 inotify 监听目录变化，变化即触发 rsync。sersync 是最成熟的封装（原生 inotify-tools 脚本易漏事件）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 服务端（目标机）装 rsync 并配好多模块（同上篇 rsyncd.conf）</span></span><br><span class="line"><span class="comment"># 2. 客户端装 sersync（依赖 inotify 和 rsync）</span></span><br><span class="line">wget https://example.com/sersync.tar.gz</span><br><span class="line">tar zxf sersync.tar.gz -C /usr/local &amp;&amp; <span class="built_in">cd</span> /usr/local/sersync</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 配置 confxml.xml 关键项（先备份再改）</span></span><br><span class="line"><span class="comment"># &lt;fileSystem xfs=&quot;true&quot;/&gt;</span></span><br><span class="line"><span class="comment"># &lt;filter start=&quot;false&quot;&gt;           排除不想同步的文件（按需开启）</span></span><br><span class="line"><span class="comment">#   &lt;exclude expression=&quot;(.*)\.svn&quot;/&gt;</span></span><br><span class="line"><span class="comment"># &lt;/filter&gt;</span></span><br><span class="line"><span class="comment"># &lt;inotify&gt;</span></span><br><span class="line"><span class="comment">#   &lt;delete start=&quot;true&quot;/&gt;</span></span><br><span class="line"><span class="comment">#   &lt;createFolder start=&quot;true&quot;/&gt;</span></span><br><span class="line"><span class="comment">#   &lt;createFile start=&quot;true&quot;/&gt;</span></span><br><span class="line"><span class="comment">#   &lt;closeWrite start=&quot;true&quot;/&gt;</span></span><br><span class="line"><span class="comment">#   &lt;moveFrom start=&quot;true&quot;/&gt;</span></span><br><span class="line"><span class="comment">#   &lt;moveTo start=&quot;true&quot;/&gt;</span></span><br><span class="line"><span class="comment">#   &lt;attrib start=&quot;false&quot;/&gt;</span></span><br><span class="line"><span class="comment"># &lt;/inotify&gt;</span></span><br><span class="line"><span class="comment"># &lt;localpath watch=&quot;/data/www&quot;&gt;    监控目录</span></span><br><span class="line"><span class="comment">#   &lt;remote ip=&quot;10.0.8.41&quot; name=&quot;data&quot;/&gt;</span></span><br><span class="line"><span class="comment"># &lt;/localpath&gt;</span></span><br><span class="line"><span class="comment"># &lt;rsync&gt;</span></span><br><span class="line"><span class="comment">#   &lt;commonParams params=&quot;-az&quot;/&gt;</span></span><br><span class="line"><span class="comment">#   &lt;auth start=&quot;true&quot; users=&quot;rsync_backup&quot; passwordfile=&quot;/etc/rsync.pass&quot;/&gt;</span></span><br><span class="line"><span class="comment"># &lt;/rsync&gt;</span></span><br><span class="line"><span class="comment"># &lt;failLog path=&quot;/tmp/rsync_fail_log.sh&quot; timeToExecute=&quot;60&quot;/&gt;  失败每 60 分钟重试</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 启动（-d 守护；-r 启动前先全量同步一次）</span></span><br><span class="line">/usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml</span><br></pre></td></tr></table></figure><p>坑位提醒：<strong>同步多个目录需要多份 confxml + 多进程</strong>，一份配置管一个目录；海量文件场景先调大 inotify 上限：</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">sysctl -w fs.inotify.max_user_watches=524288</span><br></pre></td></tr></table></figure><h2 id="四、NFS-高可用演练（故障切换）"><a href="#四、NFS-高可用演练（故障切换）" class="headerlink" title="四、NFS 高可用演练（故障切换）"></a>四、NFS 高可用演练（故障切换）</h2><p>实时同步的终极用途：NFS 主备切换。两台机器保持目录一致（用上面的实时同步），主 NFS 挂了就切备机：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. nfs 与 backup 两台服务配置保持一致（共享目录、权限、运行身份 www/666）</span></span><br><span class="line"><span class="comment"># 2. 平时用 rsync(ersync) 把主机的 /data 实时同步到备机</span></span><br><span class="line"><span class="comment"># 3. 模拟故障：主 NFS 宕机</span></span><br><span class="line"><span class="comment"># 4. web 节点强制卸载主 NFS，改挂备 NFS（业务侧一条命令切换）</span></span><br><span class="line">umount -lf /data</span><br><span class="line">mount -t nfs 10.0.8.41:/data /data</span><br></pre></td></tr></table></figure><p>生产里这套再配个脚本或让业务侧感知主备地址（虚拟 IP 更好），切换时间从”小时级”降到”分钟级”。</p><h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>备份体系的完整形态：<strong>cron 定时 + rsync 传输 + md5 校验 + 邮件告警 + sersync 实时兜底</strong>。工具都是现成的，架构和脚本规范才是沉淀下来的资产——这套脚本模板之后每接一个新服务，改几个变量就能复用。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/07/20/%E5%AE%9A%E6%97%B6%E5%A4%87%E4%BB%BD%E4%B8%8E%E5%AE%9E%E6%97%B6%E5%90%8C%E6%AD%A5%E8%90%BD%E5%9C%B0cron%E5%8A%A0rsync%E5%8A%A0sersync/</id>
    <link href="https://www.lumindream.site/2023/07/20/%E5%AE%9A%E6%97%B6%E5%A4%87%E4%BB%BD%E4%B8%8E%E5%AE%9E%E6%97%B6%E5%90%8C%E6%AD%A5%E8%90%BD%E5%9C%B0cron%E5%8A%A0rsync%E5%8A%A0sersync/"/>
    <published>2023-07-20T02:00:00.000Z</published>
    <summary>把备份从&quot;手工执行&quot;变成&quot;无人值守&quot;：定时备份脚本、md5 校验与邮件告警、sersync 文件实时同步，以及一次 NFS 故障切换演练。</summary>
    <title>定时备份与实时同步落地：cron + rsync + sersync</title>
    <updated>2023-07-20T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="rsync" scheme="https://www.lumindream.site/tags/rsync/"/>
    <category term="备份" scheme="https://www.lumindream.site/tags/%E5%A4%87%E4%BB%BD/"/>
    <content>
      <![CDATA[<h1 id="rsync-备份体系：从命令到企业备份架构"><a href="#rsync-备份体系：从命令到企业备份架构" class="headerlink" title="rsync 备份体系：从命令到企业备份架构"></a>rsync 备份体系：从命令到企业备份架构</h1><p>“数据没丢过”不代表备份做得对，”数据丢过且能恢复”才算。rsync 是 Linux 备份体系里最核心的工具——增量传输、断点续传、本地&#x2F;远程全支持。这篇从命令用法讲到企业级备份架构。</p><h2 id="一、核心概念与三种模式"><a href="#一、核心概念与三种模式" class="headerlink" title="一、核心概念与三种模式"></a>一、核心概念与三种模式</h2><p>rsync 有个特性是 scp 给不了的：<strong>增量同步</strong>——只传变化的部分，第二次执行默认就是增量，不重复传。</p><p>三种传输模式：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 本地拷贝（也做增量）</span></span><br><span class="line">rsync -av /data/ /backup/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 守护进程模式（rsync://，走 873 端口，免 ssh 认证）</span></span><br><span class="line"><span class="comment">#   HOST:: 后面跟的是模块名（rsyncd.conf 里的 [backup]），不是目录路径！</span></span><br><span class="line">rsync -av /data/ rsync://backup-server::backup</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. SSH 通道模式（走系统用户 + ssh 认证）</span></span><br><span class="line">rsync -av -e ssh /data/ ops@10.0.8.41:/data/</span><br></pre></td></tr></table></figure><p><code>-a</code> 归档模式是主力，等价于 <code>-rlptgoD</code>：递归、软链接、权限、时间、属主属组、设备文件全部保留。</p><h2 id="二、–delete：最重要也最危险的参数"><a href="#二、–delete：最重要也最危险的参数" class="headerlink" title="二、–delete：最重要也最危险的参数"></a>二、–delete：最重要也最危险的参数</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 语义：让目标目录和源目录完全一致——源没有的，目标必须删</span></span><br><span class="line">rsync -av --delete /data/ /backup/</span><br></pre></td></tr></table></figure><p>两个要点：</p><ol><li><strong>源、目标都要加斜杠</strong>，否则目标里会出现 <code>源目录名/源目录名</code> 嵌套；</li><li><strong>方向要想清楚</strong>：<code>--delete</code> 是”以源为准”。企业里的经典用法是反向用——<strong>以备份服务器为准，把被黑&#x2F;被改的目录恢复成备份状态</strong>：</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 服务器代码中毒被篡改：以备份机 /backup 为准，强制恢复业务机</span></span><br><span class="line">rsync -av --delete rsync://backup-server::backup /server/www/</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><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="comment"># 1. 安装</span></span><br><span class="line">yum install -y rsync</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. /etc/rsyncd.conf</span></span><br><span class="line"><span class="built_in">cat</span> &gt; /etc/rsyncd.conf &lt;&lt;<span class="string">&#x27;EOF&#x27;</span></span><br><span class="line">uid = rsync</span><br><span class="line">gid = rsync</span><br><span class="line">use <span class="built_in">chroot</span> = no          <span class="comment"># 不禁锢；软链可指模块外，需严格管理 path 权限</span></span><br><span class="line">max connections = 10</span><br><span class="line"><span class="built_in">read</span> only = <span class="literal">false</span>        <span class="comment"># 备份机要接收数据</span></span><br><span class="line">list = <span class="literal">false</span>             <span class="comment"># 不允许列出模块</span></span><br><span class="line">auth <span class="built_in">users</span> = rsync_backup</span><br><span class="line">secrets file = /etc/rsync.passwd</span><br><span class="line">[backup]</span><br><span class="line">path = /backup</span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 创建虚拟用户（不能登录系统）</span></span><br><span class="line">useradd rsync -s /sbin/nologin -M</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 密码文件（服务端格式：用户名:密码，权限 600）</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;rsync_backup:Ops@2023&#x27;</span> &gt; /etc/rsync.passwd &amp;&amp; <span class="built_in">chmod</span> 600 /etc/rsync.passwd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 创建备份目录并授权</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /backup &amp;&amp; <span class="built_in">chown</span> rsync:rsync /backup</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 启动并验证 873 端口</span></span><br><span class="line">systemctl start rsyncd &amp;&amp; systemctl <span class="built_in">enable</span> rsyncd</span><br><span class="line">ss -tulnp | grep 873</span><br></pre></td></tr></table></figure><h2 id="四、客户端配置与免密"><a href="#四、客户端配置与免密" class="headerlink" title="四、客户端配置与免密"></a>四、客户端配置与免密</h2><p>客户端只需装 rsync 工具，两种免密方式：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 方式一：密码文件免密（客户端文件只写密码，不带用户名！）</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;Ops@2023&#x27;</span> &gt; /etc/rsync.pass &amp;&amp; <span class="built_in">chmod</span> 600 /etc/rsync.pass</span><br><span class="line">rsync -av --password-file=/etc/rsync.pass /data/ rsync://backup-server::backup</span><br><span class="line"></span><br><span class="line"><span class="comment"># 方式二：环境变量</span></span><br><span class="line"><span class="built_in">export</span> RSYNC_PASSWORD=<span class="string">&#x27;Ops@2023&#x27;</span></span><br><span class="line">rsync -av /data/ rsync://backup-server::backup</span><br></pre></td></tr></table></figure><h2 id="五、多服务器备份架构：按客户端划分模块"><a href="#五、多服务器备份架构：按客户端划分模块" class="headerlink" title="五、多服务器备份架构：按客户端划分模块"></a>五、多服务器备份架构：按客户端划分模块</h2><p>多台业务机往一台备份机同步时，<strong>不要共用同一个模块</strong>——按客户端划分模块，实现身份物理隔离：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 备份机 /etc/rsyncd.conf 里按客户端定义：</span></span><br><span class="line">[web01]</span><br><span class="line">path = /backup/web01</span><br><span class="line">auth <span class="built_in">users</span> = web01_bak</span><br><span class="line"></span><br><span class="line">[web02]</span><br><span class="line">path = /backup/web02</span><br><span class="line">auth <span class="built_in">users</span> = web02_bak</span><br></pre></td></tr></table></figure><p>每个客户端只有自己模块的密码文件，<strong>A 机器即便密码泄露也碰不到 B 的备份目录</strong>。备份机的 &#x2F;backup 目录按机器分目录，恢复时一目了然。</p><h2 id="六、SSH-免密（配套）"><a href="#六、SSH-免密（配套）" class="headerlink" title="六、SSH 免密（配套）"></a>六、SSH 免密（配套）</h2><p>需要走 SSH 通道时（如跨机房、需要系统用户权限），配置免密：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 客户端生成密钥（一路回车）</span></span><br><span class="line">ssh-keygen -t ed25519</span><br><span class="line"><span class="comment"># 分发公钥</span></span><br><span class="line">ssh-copy-id -i ~/.ssh/id_ed25519.pub ops@10.0.8.41</span><br><span class="line"><span class="comment"># 验证</span></span><br><span class="line">ssh ops@10.0.8.41 <span class="string">&#x27;hostname&#x27;</span></span><br></pre></td></tr></table></figure><h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>备份体系的正确姿势是一套组合拳：<strong>rsync 负责传、密码文件负责认证、模块隔离负责安全、–delete 负责恢复</strong>。工具本身半小时能配完，真正值钱的是架构设计——下一篇把它升级成”定时 + 校验 + 告警 + 实时同步”的完整闭环。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/07/13/rsync%E5%A4%87%E4%BB%BD%E4%BD%93%E7%B3%BB%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BC%81%E4%B8%9A%E5%A4%87%E4%BB%BD%E6%9E%B6%E6%9E%84/</id>
    <link href="https://www.lumindream.site/2023/07/13/rsync%E5%A4%87%E4%BB%BD%E4%BD%93%E7%B3%BB%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BC%81%E4%B8%9A%E5%A4%87%E4%BB%BD%E6%9E%B6%E6%9E%84/"/>
    <published>2023-07-13T02:00:00.000Z</published>
    <summary>备份是运维的底线：rsync 三种传输模式与关键参数、守护进程模式完整配置、多服务器备份架构设计（身份隔离/免密），以及 --delete 的正确用法。</summary>
    <title>rsync 备份体系：从命令到企业备份架构</title>
    <updated>2023-07-13T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="NFS" scheme="https://www.lumindream.site/tags/NFS/"/>
    <category term="存储" scheme="https://www.lumindream.site/tags/%E5%AD%98%E5%82%A8/"/>
    <content>
      <![CDATA[<h1 id="NFS-共享存储实战：从挂载到生产读写分离"><a href="#NFS-共享存储实战：从挂载到生产读写分离" class="headerlink" title="NFS 共享存储实战：从挂载到生产读写分离"></a>NFS 共享存储实战：从挂载到生产读写分离</h1><p>业务上线后没两天就会遇到一个问题：文件上传功能在多台服务器上各存各的，用户在 A 机传的图片，请求打到 B 机就 404 了。解法是让所有机器挂载同一份存储——NFS 是内网共享存储里最便宜、最常见的选择。这篇把 NFS 从原理到生产读写分离完整过一遍。</p><h2 id="一、先理解-NFS-在干什么"><a href="#一、先理解-NFS-在干什么" class="headerlink" title="一、先理解 NFS 在干什么"></a>一、先理解 NFS 在干什么</h2><p>NFS（Network File System）让你像用本地目录一样用远程目录。数据真正落在服务端，客户端只做挂载和读写。涉及两个角色：</p><ul><li><strong>服务端</strong>：共享目录方，监听 2049 端口；NFSv3 还需要 rpcbind（端口映射服务）配合；</li><li><strong>客户端</strong>：挂载方，本地挂载点只是一个”门”，读写都打到服务端。</li></ul><p>一句话记忆：<strong>服务端出目录、客户端进目录，数据永远在服务端那份。</strong></p><h2 id="二、服务端配置（6-步）"><a href="#二、服务端配置（6-步）" class="headerlink" title="二、服务端配置（6 步）"></a>二、服务端配置（6 步）</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><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"># 1. 安装（内网按网段放行 2049/rpcbind 即可，不建议直接全关防火墙）</span></span><br><span class="line">yum install -y nfs-utils</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 配置共享目录 /etc/exports</span></span><br><span class="line"><span class="comment"># 格式：共享路径  客户端地址(权限参数)</span></span><br><span class="line">/data  172.18.1.0/24(rw,<span class="built_in">sync</span>,no_root_squash)   <span class="comment"># 注意客户端地址与参数间没有空格</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 创建共享目录并授权</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /data &amp;&amp; <span class="built_in">chown</span> -R nfsnobody:nfsnobody /data</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 启动并加入开机自启（rpcbind 提供 NFSv3 端口映射，一起启）</span></span><br><span class="line">systemctl start rpcbind &amp;&amp; systemctl start nfs</span><br><span class="line">systemctl <span class="built_in">enable</span> rpcbind nfs</span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 验证：端口监听 + 实际生效的导出信息</span></span><br><span class="line">ss -tulnp | grep 2049</span><br><span class="line"><span class="built_in">cat</span> /var/lib/nfs/etab        <span class="comment"># etab 里有 /data 记录，说明 exports 配置正确</span></span><br><span class="line">exportfs -rv                 <span class="comment"># 修改 exports 后平滑加载，无需重启</span></span><br></pre></td></tr></table></figure><h2 id="三、客户端挂载（6-步）"><a href="#三、客户端挂载（6-步）" class="headerlink" title="三、客户端挂载（6 步）"></a>三、客户端挂载（6 步）</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 安装客户端</span></span><br><span class="line">yum install -y nfs-utils</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 查看服务端共享了什么</span></span><br><span class="line">showmount -e 172.18.1.31</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 挂载</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /nfsdir</span><br><span class="line">mount -t nfs 172.18.1.31:/data /nfsdir</span><br><span class="line"></span><br><span class="line"><span class="comment"># 4. 验证</span></span><br><span class="line"><span class="built_in">df</span> -h | grep nfsdir</span><br><span class="line"><span class="comment"># 172.18.1.31:/data  62G  880M  58G  2%  /nfsdir</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 5. 写入测试：客户端写，服务端能看到同一份</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;test&quot;</span> &gt; /nfsdir/test.txt &amp;&amp; <span class="built_in">ls</span> -l /data/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 6. 开机挂载（生产必须加 _netdev，避免网络未就绪时挂载失败卡开机）</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;172.18.1.31:/data  /nfsdir  nfs  defaults,_netdev 0 0&#x27;</span> &gt;&gt; /etc/fstab</span><br><span class="line">mount -a    <span class="comment"># 写完 fstab 必须用 mount -a 验证</span></span><br></pre></td></tr></table></figure><p>卸载时提示 <code>device is busy</code> 是高频小坑：先 <code>cd /</code> 再 umount；实在不行 <code>umount -lf</code> 强制卸载。</p><h2 id="四、权限与安全：生产必配的参数"><a href="#四、权限与安全：生产必配的参数" class="headerlink" title="四、权限与安全：生产必配的参数"></a>四、权限与安全：生产必配的参数</h2><p>NFS 的权限坑集中在<strong>身份映射</strong>上。服务端默认把客户端 root 映射成 nobody，但普通用户的 uid&#x2F;gid 会原样透传——两边 uid 对不上就会出现”文件能看到但没权限写”。</p><p><strong>统一身份的标准做法：all_squash + anonuid&#x2F;anongid</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 服务端 exports：</span></span><br><span class="line">/data  172.18.1.0/24(rw,<span class="built_in">sync</span>,all_squash,anonuid=666,anongid=666)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 服务端创建对应用户并授权</span></span><br><span class="line">useradd -u 666 -g 666 www -s /sbin/nologin</span><br><span class="line"><span class="built_in">chown</span> -R 666.666 /data</span><br><span class="line"></span><br><span class="line"><span class="comment"># 客户端也建同 uid 用户（统一身份，避免权限不足）</span></span><br><span class="line">useradd -u 666 -g 666 www -s /sbin/nologin</span><br></pre></td></tr></table></figure><p>这样不管客户端是谁写的，落盘统一变成 uid&#x3D;666，权限问题一次性根治。</p><p><strong>安全挂载参数（静默数据不需要执行权限）：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mount -t nfs -o noexec,nodev,nosuid 172.18.1.31:/data /nfsdir</span><br><span class="line"><span class="comment"># noexec：禁止执行（防上传木马被直接运行）</span></span><br><span class="line"><span class="comment"># nodev / nosuid：禁设备文件与提权位</span></span><br></pre></td></tr></table></figure><p><strong>性能参数（可选）：</strong> <code>noatime,nodiratime</code> 禁止更新访问时间戳，减少 NFS 写放大，高 IO 场景明显。</p><h2 id="五、生产案例：读写分离"><a href="#五、生产案例：读写分离" class="headerlink" title="五、生产案例：读写分离"></a>五、生产案例：读写分离</h2><p>需求：静态资源读多写少，且不同目录权限隔离——<code>/data/r</code> 只读、<code>/data/w</code> 可写，都映射到 www(666)。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 服务端：</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /data/&#123;r,w&#125;</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;www:x:666:666::/home/www:/sbin/nologin&#x27;</span> &gt;&gt; /etc/passwd  <span class="comment"># 或 useradd -u 666</span></span><br><span class="line"><span class="built_in">cat</span> &gt;&gt; /etc/exports &lt;&lt;<span class="string">&#x27;EOF&#x27;</span></span><br><span class="line">/data/r  172.18.1.0/24(ro,<span class="built_in">sync</span>,all_squash,anonuid=666,anongid=666)</span><br><span class="line">/data/w  172.18.1.0/24(rw,<span class="built_in">sync</span>,all_squash,anonuid=666,anongid=666)</span><br><span class="line">EOF</span><br><span class="line">exportfs -rv</span><br><span class="line"></span><br><span class="line"><span class="comment"># 客户端：</span></span><br><span class="line">mount -t nfs 172.18.1.31:/data/r /data/r</span><br><span class="line">mount -t nfs 172.18.1.31:/data/w /data/w</span><br><span class="line"><span class="built_in">touch</span> /data/r/xx &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;Read-only file system&quot;</span>   <span class="comment"># 只读目录写入报错（预期）</span></span><br><span class="line"><span class="built_in">echo</span> ok &gt; /data/w/test                             <span class="comment"># 可写目录正常</span></span><br></pre></td></tr></table></figure><h2 id="六、排障要点"><a href="#六、排障要点" class="headerlink" title="六、排障要点"></a>六、排障要点</h2><ol><li><strong>挂载报 access denied</strong>：路径写错最常见——<code>showmount -e 服务端</code> 先看服务端实际导出的名字；</li><li><strong>挂载卡住&#x2F;超时</strong>：检查 rpcbind 是否启动、2049 与 rpc 端口（111）防火墙是否放行；</li><li><strong>改完 exports 不生效</strong>：<code>exportfs -rv</code> 平滑加载，别重启 NFS 中断业务；</li><li><strong>客户端看到文件但没权限</strong>：九成是 uid 不一致，按上面统一 anonuid 方案处理。</li></ol><p>NFS 本身不复杂，把”数据在服务端、权限靠 anonuid、安全靠 noexec”这三条记住，生产基本够用。它解决的是”共享”，备份和灾备就是下一篇文章的事了。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/07/06/nfs%E5%85%B1%E4%BA%AB%E5%AD%98%E5%82%A8%E5%AE%9E%E6%88%98%E4%BB%8E%E6%8C%82%E8%BD%BD%E5%88%B0%E7%94%9F%E4%BA%A7%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB/</id>
    <link href="https://www.lumindream.site/2023/07/06/nfs%E5%85%B1%E4%BA%AB%E5%AD%98%E5%82%A8%E5%AE%9E%E6%88%98%E4%BB%8E%E6%8C%82%E8%BD%BD%E5%88%B0%E7%94%9F%E4%BA%A7%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB/"/>
    <published>2023-07-06T02:00:00.000Z</published>
    <summary>多台服务器共享同一份数据怎么做：NFS 服务端/客户端完整配置、权限与安全挂载参数、读写分离生产案例，以及挂载排障记录。</summary>
    <title>NFS 共享存储实战：从挂载到生产读写分离</title>
    <updated>2023-07-06T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="Shell脚本与工具" scheme="https://www.lumindream.site/categories/Shell%E8%84%9A%E6%9C%AC%E4%B8%8E%E5%B7%A5%E5%85%B7/"/>
    <category term="Shell" scheme="https://www.lumindream.site/tags/Shell/"/>
    <category term="三剑客" scheme="https://www.lumindream.site/tags/%E4%B8%89%E5%89%91%E5%AE%A2/"/>
    <category term="定时任务" scheme="https://www.lumindream.site/tags/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1/"/>
    <content>
      <![CDATA[<h1 id="Shell-三剑客与自动化脚本实践"><a href="#Shell-三剑客与自动化脚本实践" class="headerlink" title="Shell 三剑客与自动化脚本实践"></a>Shell 三剑客与自动化脚本实践</h1><p>运维的日常工作（看日志、查状态、做巡检）如果全靠手工敲命令，一天什么都干不了。把重复操作沉淀成脚本 + 定时任务，是运维从”救火”走向”自动化”的分水岭。这篇整理三剑客和 Shell 脚本的实战用法。</p><h2 id="一、三剑客：grep-sed-awk"><a href="#一、三剑客：grep-sed-awk" class="headerlink" title="一、三剑客：grep &#x2F; sed &#x2F; awk"></a>一、三剑客：grep &#x2F; sed &#x2F; awk</h2><h3 id="grep：过滤文本"><a href="#grep：过滤文本" class="headerlink" title="grep：过滤文本"></a>grep：过滤文本</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">grep -n <span class="string">&quot;ERROR&quot;</span> app.log          <span class="comment"># 带行号过滤</span></span><br><span class="line">grep -v <span class="string">&quot;^#&quot;</span> nginx.conf          <span class="comment"># 排除注释行</span></span><br><span class="line">egrep -n <span class="string">&quot;ERROR|WARN&quot;</span> app.log    <span class="comment"># 多关键词</span></span><br><span class="line">grep -A5 <span class="string">&quot;Exception&quot;</span> app.log     <span class="comment"># 匹配后 5 行（看异常堆栈必备）</span></span><br></pre></td></tr></table></figure><h3 id="sed：按行过滤与批量修改"><a href="#sed：按行过滤与批量修改" class="headerlink" title="sed：按行过滤与批量修改"></a>sed：按行过滤与批量修改</h3><p>sed 是流编辑器，按行处理、无需打开文件，脚本化修改配置的核心工具。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sed -n <span class="string">&#x27;10,20p&#x27;</span> nginx.conf       <span class="comment"># 打印 10-20 行</span></span><br><span class="line">sed -i <span class="string">&#x27;s/8080/8081/g&#x27;</span> nginx.conf <span class="comment"># 全局替换并写回（-i 原地修改）</span></span><br><span class="line">sed -i <span class="string">&#x27;/^#/d&#x27;</span> nginx.conf        <span class="comment"># 删除注释行</span></span><br><span class="line">sed -n <span class="string">&#x27;/^server/,/&#125;/p&#x27;</span> nginx.conf <span class="comment"># 区间匹配</span></span><br></pre></td></tr></table></figure><p>两个纪律：①<code>-i</code> 前先备份（<code>cp xxx xxx.bak</code>），改配置类文件尤其如此；②替换匹配尽量精确，避免误伤。</p><h3 id="awk：取行取列与统计"><a href="#awk：取行取列与统计" class="headerlink" title="awk：取行取列与统计"></a>awk：取行取列与统计</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">awk <span class="string">&#x27;&#123;print $1, $3&#125;&#x27;</span> access.log          <span class="comment"># 取第 1、3 列</span></span><br><span class="line">awk <span class="string">&#x27;$9 == 500 &#123;print $1&#125;&#x27;</span> access.log    <span class="comment"># 过滤 500 状态码的行</span></span><br><span class="line">awk <span class="string">&#x27;&#123;count[$1]++&#125; END&#123;for (k in count) print k, count[k]&#125;&#x27;</span> access.log | <span class="built_in">sort</span> -k2 -rn | <span class="built_in">head</span></span><br><span class="line"><span class="comment"># 统计每个 IP 的请求次数，前 10 名（日志分析高频用法）</span></span><br></pre></td></tr></table></figure><h2 id="二、Shell-脚本规范"><a href="#二、Shell-脚本规范" class="headerlink" title="二、Shell 脚本规范"></a>二、Shell 脚本规范</h2><h3 id="脚本骨架"><a href="#脚本骨架" class="headerlink" title="脚本骨架"></a>脚本骨架</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># 注释头：脚本用途、作者、修改记录（团队规范）</span></span><br><span class="line"><span class="built_in">set</span> -e          <span class="comment"># 出错即停（排障友好）</span></span><br><span class="line"><span class="comment"># 变量：统一大写或用小写下划线</span></span><br><span class="line">LOG_DIR=<span class="string">&quot;/data/logs&quot;</span></span><br></pre></td></tr></table></figure><h3 id="变量与传参"><a href="#变量与传参" class="headerlink" title="变量与传参"></a>变量与传参</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 特殊变量：$0 脚本名 $1-$9 位置参数 $# 参数个数 $? 上条命令退出码</span></span><br><span class="line"><span class="comment"># 判断：判断上一条命令是否成功就看 $?</span></span><br><span class="line">ping -c1 www.baidu.com &gt;/dev/null 2&gt;&amp;1 &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;通&quot;</span> || <span class="built_in">echo</span> <span class="string">&quot;不通&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 默认值（生产常用：环境变量没设就用默认）</span></span><br><span class="line">PORT=<span class="variable">$&#123;PORT:-3306&#125;</span></span><br><span class="line"><span class="comment"># 强制必须设置：没传参数就报错退出</span></span><br><span class="line">[ <span class="variable">$#</span> -lt 1 ] &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;用法: <span class="variable">$0</span> 参数1&quot;</span> &amp;&amp; <span class="built_in">exit</span> 1</span><br></pre></td></tr></table></figure><h3 id="条件与循环"><a href="#条件与循环" class="headerlink" title="条件与循环"></a>条件与循环</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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="comment"># 数值/字符串/文件判断</span></span><br><span class="line">[ <span class="variable">$FREE</span> -lt 10 ] &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;磁盘空间不足&quot;</span>      <span class="comment"># 数值比较</span></span><br><span class="line">[ -f /etc/nginx/nginx.conf ] &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;存在&quot;</span>  <span class="comment"># 文件判断</span></span><br><span class="line">[ -z <span class="string">&quot;<span class="variable">$VAR</span>&quot;</span> ] &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;变量为空&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 循环</span></span><br><span class="line"><span class="keyword">for</span> ip <span class="keyword">in</span> 10.0.8.11 10.0.8.12; <span class="keyword">do</span> ping -c1 -W1 <span class="variable">$ip</span> &gt;/dev/null &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$ip</span> 通&quot;</span> || <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$ip</span> 不通&quot;</span>; <span class="keyword">done</span></span><br><span class="line"><span class="keyword">while</span> <span class="built_in">read</span> line; <span class="keyword">do</span> <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$line</span>&quot;</span>; <span class="keyword">done</span> &lt; list.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># case 多路选择（服务操作脚本常用）</span></span><br><span class="line"><span class="keyword">case</span> <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="keyword">in</span></span><br><span class="line">  start) systemctl start nginx ;;</span><br><span class="line">  stop)  systemctl stop nginx ;;</span><br><span class="line">  *) <span class="built_in">echo</span> <span class="string">&quot;用法: <span class="variable">$0</span> start|stop&quot;</span> ;;</span><br><span class="line"><span class="keyword">esac</span></span><br></pre></td></tr></table></figure><h3 id="函数与局部变量"><a href="#函数与局部变量" class="headerlink" title="函数与局部变量"></a>函数与局部变量</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 函数内的变量必须用 local，防止污染全局（这也是排查&quot;变量莫名被改&quot;的常见元凶）</span></span><br><span class="line"><span class="function"><span class="title">log_info</span></span>() &#123; <span class="built_in">local</span> msg=<span class="string">&quot;<span class="variable">$1</span>&quot;</span>; <span class="built_in">echo</span> <span class="string">&quot;[INFO] <span class="subst">$(date &#x27;+%F %T&#x27;)</span> <span class="variable">$msg</span>&quot;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">check_disk</span></span>() &#123; <span class="built_in">local</span> use=$(<span class="built_in">df</span> -h / | awk <span class="string">&#x27;NR==2&#123;print $5&#125;&#x27;</span> | <span class="built_in">tr</span> -d <span class="string">&#x27;%&#x27;</span>); [ <span class="string">&quot;<span class="variable">$use</span>&quot;</span> -gt 80 ] &amp;&amp; <span class="built_in">echo</span> <span class="string">&quot;根分区使用率 <span class="variable">$&#123;use&#125;</span>%&quot;</span>; &#125;</span><br></pre></td></tr></table></figure><h2 id="三、定时任务：crontab"><a href="#三、定时任务：crontab" class="headerlink" title="三、定时任务：crontab"></a>三、定时任务：crontab</h2><p>五段式：<code>分 时 日 月 周 命令</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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">crontab -e</span><br><span class="line"><span class="comment"># 每天凌晨 2 点备份</span></span><br><span class="line">0 2 * * * /opt/scripts/backup.sh &gt;&gt; /var/log/backup.log 2&gt;&amp;1</span><br><span class="line"><span class="comment"># 每 10 分钟巡检一次</span></span><br><span class="line">*/10 * * * * /opt/scripts/check.sh</span><br><span class="line"><span class="comment"># 每周日凌晨 3 点清理</span></span><br><span class="line">0 3 * * 0 /opt/scripts/cleanup.sh</span><br><span class="line"></span><br><span class="line">crontab -l     <span class="comment"># 查看</span></span><br><span class="line">crontab -r     <span class="comment"># 删除（慎用）</span></span><br></pre></td></tr></table></figure><p>定时任务三个高频坑：</p><ol><li><strong>脚本里的环境变量（PATH）是精简的</strong>：在 crontab 里直接写 <code>rsync</code>、<code>python3</code> 可能 command not found——脚本开头显式定义或用绝对路径；</li><li><strong>输出重定向必须写</strong>：不写 <code>&gt;&gt; log 2&gt;&amp;1</code>，脚本报错内容会发到系统邮箱（没人看），排障全靠猜；</li><li><strong>任务没执行先查三件事</strong>：<code>crontab -l</code> 任务在不在、脚本权限（<code>chmod +x</code>）、手动跑一遍有没有报错。</li></ol><h2 id="四、一个完整的巡检脚本案例"><a href="#四、一个完整的巡检脚本案例" class="headerlink" title="四、一个完整的巡检脚本案例"></a>四、一个完整的巡检脚本案例</h2><p>把”每天的磁盘&#x2F;内存&#x2F;负载巡检”沉淀成脚本，配 crontab 每天跑，结果统一写到日志：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># 日常巡检：磁盘、内存、负载</span></span><br><span class="line">LOG=<span class="string">&quot;/var/log/ops/daily-check.log&quot;</span></span><br><span class="line">TS=$(<span class="built_in">date</span> <span class="string">&#x27;+%F %T&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;===== <span class="variable">$TS</span> 巡检开始 =====&quot;</span> &gt;&gt; <span class="variable">$LOG</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 磁盘使用率 TOP 检查</span></span><br><span class="line"><span class="built_in">df</span> -h | awk <span class="string">&#x27;NR&gt;1 &amp;&amp; $5+0 &gt; 80 &#123;print &quot;磁盘告警: &quot; $0&#125;&#x27;</span> &gt;&gt; <span class="variable">$LOG</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 内存</span></span><br><span class="line">free -h | awk <span class="string">&#x27;NR==2 &#123;print &quot;内存: 总量&quot;$2&quot; 已用&quot;$3&quot; 可用&quot;$7&#125;&#x27;</span> &gt;&gt; <span class="variable">$LOG</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 负载（超过核数阈值提醒）</span></span><br><span class="line">LOAD=$(<span class="built_in">uptime</span> | awk -F<span class="string">&#x27;load average:&#x27;</span> <span class="string">&#x27;&#123;print $2&#125;&#x27;</span> | <span class="built_in">cut</span> -d, -f1)</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;负载: <span class="variable">$LOAD</span>&quot;</span> &gt;&gt; <span class="variable">$LOG</span></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">0 8 * * * /opt/scripts/daily-check.sh</span><br></pre></td></tr></table></figure><p>脚本化的收益是复利式的：每次把重复操作写成脚本 + 定时任务，后面所有机器都能复用，也逼着自己把每一步操作想清楚——这正是排查和自动化能力一起提升的过程。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/06/28/shell%E4%B8%89%E5%89%91%E5%AE%A2%E4%B8%8E%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC%E5%AE%9E%E8%B7%B5/</id>
    <link href="https://www.lumindream.site/2023/06/28/shell%E4%B8%89%E5%89%91%E5%AE%A2%E4%B8%8E%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC%E5%AE%9E%E8%B7%B5/"/>
    <published>2023-06-28T02:00:00.000Z</published>
    <summary>把日常巡检变成自动化脚本：grep/sed/awk 三剑客实战、Shell 脚本规范（变量/判断/循环/函数）、crontab 定时任务与排障，附日志分析脚本案例。</summary>
    <title>Shell 三剑客与自动化脚本实践</title>
    <updated>2023-06-28T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="LVM" scheme="https://www.lumindream.site/tags/LVM/"/>
    <category term="磁盘" scheme="https://www.lumindream.site/tags/%E7%A3%81%E7%9B%98/"/>
    <content>
      <![CDATA[<h1 id="磁盘管理与-LVM-在线扩容实战"><a href="#磁盘管理与-LVM-在线扩容实战" class="headerlink" title="磁盘管理与 LVM 在线扩容实战"></a>磁盘管理与 LVM 在线扩容实战</h1><p>磁盘告警（<code>/</code> 使用率 90%）是运维半夜被叫醒的高频原因。给磁盘规划做对了两件事——用 LVM、留扩容路径——大多数告警都能在业务无感的情况下解决。这篇是磁盘管理的完整实战。</p><h2 id="一、分区表：MBR-vs-GPT"><a href="#一、分区表：MBR-vs-GPT" class="headerlink" title="一、分区表：MBR vs GPT"></a>一、分区表：MBR vs GPT</h2><table><thead><tr><th>对比项</th><th>MBR</th><th>GPT</th></tr></thead><tbody><tr><td>最大容量</td><td>2TB</td><td>大得多</td></tr><tr><td>主分区数</td><td>最多 4 个</td><td>128 个</td></tr><tr><td>工具</td><td>fdisk</td><td>parted &#x2F; gdisk</td></tr><tr><td>场景</td><td>小于 2T 的盘</td><td><strong>大于 2T 的盘必须 GPT</strong></td></tr></tbody></table><p>一条判断记住：<strong>小于 2T 用 fdisk（MBR），大于 2T 用 parted（GPT）</strong>。</p><h2 id="二、RAID-选型：一句话对比"><a href="#二、RAID-选型：一句话对比" class="headerlink" title="二、RAID 选型：一句话对比"></a>二、RAID 选型：一句话对比</h2><table><thead><tr><th>级别</th><th>最少磁盘</th><th>可用容量</th><th>容错</th><th>特点</th><th>典型场景</th></tr></thead><tbody><tr><td>RAID0</td><td>1</td><td>100%</td><td>无</td><td>最快最脆，坏一块全丢</td><td>缓存&#x2F;临时数据，生产几乎不用</td></tr><tr><td>RAID1</td><td>2</td><td>50%</td><td>1 块</td><td>完全镜像，安全但写慢</td><td>系统盘、关键小数据</td></tr><tr><td>RAID5</td><td>3</td><td>(n-1)&#x2F;n</td><td>1 块</td><td>均衡，坏 1 块靠校验重建</td><td>通用业务盘（非数据库）</td></tr><tr><td>RAID10</td><td>4</td><td>50%</td><td>每组 1 块</td><td>先镜像再条带，快且安全</td><td><strong>数据库等高 IO 关键业务</strong></td></tr></tbody></table><p>生产选型就记一条：数据库上 RAID10，通用数据 RAID5，系统盘 RAID1——不追求理论极致，追求”故障时能扛住”。</p><h2 id="三、LVM：为什么磁盘规划一定要用它"><a href="#三、LVM：为什么磁盘规划一定要用它" class="headerlink" title="三、LVM：为什么磁盘规划一定要用它"></a>三、LVM：为什么磁盘规划一定要用它</h2><p>直接分区 + 格式化虽然简单，但空间不够时只能换更大盘、迁移数据，停机时间长。LVM 的核心价值一句话：<strong>不停止服务、不卸载目录，在线扩容</strong>。</p><p>LVM 三层概念：PV（物理卷，把盘擦干净打标记）→ VG（卷组，把 PV 收进一个池）→ LV（逻辑卷，从池里切出来用）。</p><h3 id="初始化流程"><a href="#初始化流程" class="headerlink" title="初始化流程"></a>初始化流程</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. PV：把新盘变成物理卷</span></span><br><span class="line">pvcreate /dev/sdb</span><br><span class="line"><span class="comment"># 2. VG：建卷组（池）</span></span><br><span class="line">vgcreate data_vg /dev/sdb</span><br><span class="line"><span class="comment"># 3. LV：从池里切 100G 给逻辑卷</span></span><br><span class="line">lvcreate -L 100G -n data_lv data_vg</span><br><span class="line"><span class="comment"># 4. 格式化并挂载（写入 /etc/fstab 开机自动挂载）</span></span><br><span class="line">mkfs.xfs /dev/data_vg/data_lv</span><br><span class="line"><span class="built_in">mkdir</span> /data &amp;&amp; mount /dev/data_vg/data_lv /data</span><br></pre></td></tr></table></figure><h3 id="在线扩容（四层，一步都不能少）"><a href="#在线扩容（四层，一步都不能少）" class="headerlink" title="在线扩容（四层，一步都不能少）"></a>在线扩容（四层，一步都不能少）</h3><p>场景：<code>/data</code> 只剩 10% 空间，新买了一块 200G 云盘 <code>/dev/sdc</code>，不停机扩到 300G。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 物理层面：新盘变成 PV</span></span><br><span class="line">pvcreate /dev/sdc</span><br><span class="line"><span class="comment"># 2. 卷组层面：新 PV 并入 VG（池变大了）</span></span><br><span class="line">vgextend data_vg /dev/sdc</span><br><span class="line"><span class="comment"># 3. 逻辑层面：池里空间全部给 LV</span></span><br><span class="line">lvextend -l +100%FREE /dev/data_vg/data_lv</span><br><span class="line"><span class="comment"># 4. 文件系统层面：让文件系统&quot;感知&quot;变大（关键！）</span></span><br><span class="line"><span class="comment"># ext4：</span></span><br><span class="line">resize2fs /dev/data_vg/data_lv</span><br><span class="line"><span class="comment"># xfs（CentOS 7+ 默认，注意 xfs 要传挂载点而不是设备名）：</span></span><br><span class="line">xfs_growfs /data</span><br></pre></td></tr></table></figure><p>完成后 <code>df -h</code> 立刻看到 300G，<strong>全程业务无中断</strong>。踩坑点：xfs 用 <code>xfs_growfs /data</code>（挂载点），ext4 用 <code>resize2fs</code>（设备名），混用会报错。</p><h3 id="扩容后必做的巡检项"><a href="#扩容后必做的巡检项" class="headerlink" title="扩容后必做的巡检项"></a>扩容后必做的巡检项</h3><ul><li><code>pvs / vgs / lvs</code> 三连确认三层状态一致</li><li>新盘没在 fstab 里重复挂载（避免重启后两个挂载点打架）</li><li>告警阈值（如 80% 告警、90% 危险）在监控里同步更新</li></ul><h2 id="四、swap-扩容"><a href="#四、swap-扩容" class="headerlink" title="四、swap 扩容"></a>四、swap 扩容</h2><p>内存吃紧时给系统加 swap 是最快的临时缓解：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">free -h                                  <span class="comment"># 先看现状</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 1. 生成 4G 空文件</span></span><br><span class="line"><span class="built_in">dd</span> <span class="keyword">if</span>=/dev/zero of=/swapfile bs=1M count=4096 status=progress</span><br><span class="line"><span class="comment"># 2. 权限必须 600，否则 mkswap 报&quot;不安全&quot;</span></span><br><span class="line"><span class="built_in">chmod</span> 600 /swapfile</span><br><span class="line"><span class="comment"># 3. 格式化为 swap</span></span><br><span class="line">mkswap /swapfile</span><br><span class="line"><span class="comment"># 4. 启用</span></span><br><span class="line">swapon /swapfile</span><br><span class="line"><span class="comment"># 5. 写入 fstab 永久生效</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;/swapfile swap swap defaults 0 0&#x27;</span> &gt;&gt; /etc/fstab</span><br></pre></td></tr></table></figure><p>注意：swap 是缓解不是根治，长期还是看应用内存优化或扩容内存。</p><h2 id="五、一次深夜磁盘告警实录"><a href="#五、一次深夜磁盘告警实录" class="headerlink" title="五、一次深夜磁盘告警实录"></a>五、一次深夜磁盘告警实录</h2><p>凌晨 2 点收到 <code>/</code> 使用率 92% 告警。处理链路：</p><ol><li><code>df -h</code> 确认告警真实性（92%，确实是根分区）；</li><li><code>du -h --max-depth=1 -x / | sort -hr | head -10</code> 定位大头目录（<code>-x</code> 不扫挂载点，防止 NFS 卡死）→ 是 <code>/data/logs</code> 应用日志；</li><li>查 logrotate 配置——新上线的服务没配轮转，大日志一直在涨；</li><li>手工 <code>logrotate -f</code> 触发一次轮转 + 临时清理，空间回到 60%；</li><li>补上该服务的 logrotate 规则，事件闭环。</li></ol><p>磁盘管理的核心就三句话：<strong>初始化用 LVM、扩容走四层、日志交给 logrotate</strong>——做到这三点，磁盘类故障基本都能”白天处理、晚间无感”。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/06/21/%E7%A3%81%E7%9B%98%E7%AE%A1%E7%90%86%E4%B8%8ELVM%E5%9C%A8%E7%BA%BF%E6%89%A9%E5%AE%B9%E5%AE%9E%E6%88%98/</id>
    <link href="https://www.lumindream.site/2023/06/21/%E7%A3%81%E7%9B%98%E7%AE%A1%E7%90%86%E4%B8%8ELVM%E5%9C%A8%E7%BA%BF%E6%89%A9%E5%AE%B9%E5%AE%9E%E6%88%98/"/>
    <published>2023-06-21T02:00:00.000Z</published>
    <summary>磁盘空间告急时不停机扩容的完整流程：分区表选择、RAID 选型对比、LVM 四层扩容操作（ext4/xfs 区别）、swap 扩容，以及一次深夜磁盘告警的处理实录。</summary>
    <title>磁盘管理与 LVM 在线扩容实战</title>
    <updated>2023-06-21T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="网络与安全" scheme="https://www.lumindream.site/categories/%E7%BD%91%E7%BB%9C%E4%B8%8E%E5%AE%89%E5%85%A8/"/>
    <category term="网络" scheme="https://www.lumindream.site/tags/%E7%BD%91%E7%BB%9C/"/>
    <category term="iptables" scheme="https://www.lumindream.site/tags/iptables/"/>
    <category term="防火墙" scheme="https://www.lumindream.site/tags/%E9%98%B2%E7%81%AB%E5%A2%99/"/>
    <content>
      <![CDATA[<h1 id="iptables-防火墙实战：四表五链与-NAT-转发"><a href="#iptables-防火墙实战：四表五链与-NAT-转发" class="headerlink" title="iptables 防火墙实战：四表五链与 NAT 转发"></a>iptables 防火墙实战：四表五链与 NAT 转发</h1><p>iptables 劝退很多人是因为命令又多又碎。但只要先把”四表五链 + 数据包流向”这个架构想明白，规则就是往架构里填句子。这篇从架构讲起，配合两个真实的 NAT 落地方案。</p><h2 id="一、架构：四表五链-数据包流向"><a href="#一、架构：四表五链-数据包流向" class="headerlink" title="一、架构：四表五链 + 数据包流向"></a>一、架构：四表五链 + 数据包流向</h2><p>iptables 是操作内核 netfilter 的用户态工具，不是服务。规则存在内核内存，<strong>重启丢失，需手动保存</strong>。</p><p>四张表决定”干什么”：</p><table><thead><tr><th>表</th><th>作用</th><th>挂的链</th></tr></thead><tbody><tr><td>filter</td><td>过滤（默认表）：放行&#x2F;丢弃</td><td>INPUT, FORWARD, OUTPUT</td></tr><tr><td>nat</td><td>地址转换：改 IP&#x2F;端口</td><td>PREROUTING, POSTROUTING, OUTPUT</td></tr><tr><td>mangle</td><td>改包属性（TTL&#x2F;TOS&#x2F;MARK）</td><td>全部链</td></tr><tr><td>raw</td><td>绕过连接跟踪（高级优化）</td><td>PREROUTING, OUTPUT</td></tr></tbody></table><p>五条链决定”什么时候干”：</p><table><thead><tr><th>链</th><th>触发时机</th></tr></thead><tbody><tr><td>PREROUTING</td><td>路由判断前（进门）</td></tr><tr><td>INPUT</td><td>目的&#x3D;本机，进入进程前</td></tr><tr><td>FORWARD</td><td>本机转发（当路由器）</td></tr><tr><td>OUTPUT</td><td>本机进程发出后</td></tr><tr><td>POSTROUTING</td><td>路由判断后、出网卡前（出门）</td></tr></tbody></table><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">访问本机：入网卡 → PREROUTING → 路由(本机) → INPUT → 进程 → OUTPUT → POSTROUTING → 出站</span><br><span class="line">帮人转发：入网卡 → PREROUTING → 路由(转发) → FORWARD → POSTROUTING → 出站</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"># 查看（-v 带计数，-n 不反解域名）</span></span><br><span class="line">iptables -L -v -n</span><br><span class="line"><span class="comment"># 放行/拒绝</span></span><br><span class="line">iptables -A INPUT -p tcp --dport 22 -j ACCEPT</span><br><span class="line">iptables -A INPUT -p tcp --dport 3306 -s 10.0.8.0/24 -j ACCEPT   <span class="comment"># 只放行内网网段</span></span><br><span class="line">iptables -A INPUT -p tcp --dport 80 -j DROP</span><br><span class="line"><span class="comment"># 删除规则：-D 或先 -L --line-numbers 看编号再删</span></span><br><span class="line">iptables -D INPUT -p tcp --dport 80 -j DROP</span><br></pre></td></tr></table></figure><p>高频概念：</p><ul><li><strong>DROP vs REJECT</strong>：DROP 静默丢包（防扫描更安全，但客户端表现是超时）；REJECT 明确拒绝（利于调试，报错快）。对外防火墙用 DROP。</li><li><strong>匹配顺序</strong>：链内自上而下，命中即停。具体放行规则放前面，默认策略兜底。</li><li><strong>看命中次数</strong>：<code>iptables -L -v -n</code> 的 pkts&#x2F;bytes 列。排障时计数器不增长 &#x3D; 包根本没走到这条规则，往上游找。</li><li><strong>持久化</strong>：<code>iptables-save &gt; /etc/sysconfig/iptables</code>，开机 <code>iptables-restore</code> 恢复（或直接装 firewalld 管持久化）。</li></ul><h2 id="三、案例-1：SNAT-共享上网"><a href="#三、案例-1：SNAT-共享上网" class="headerlink" title="三、案例 1：SNAT 共享上网"></a>三、案例 1：SNAT 共享上网</h2><p>场景：内网 20 台服务器走一台网关机器共享上网，网关双网卡（内网 + 公网）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 开启内核转发</span></span><br><span class="line"><span class="built_in">echo</span> 1 &gt; /proc/sys/net/ipv4/ip_forward</span><br><span class="line"><span class="comment"># 永久生效：/etc/sysctl.conf 里 net.ipv4.ip_forward=1 后 sysctl -p</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 内网过来的流量出公网时把源地址换成网关公网 IP</span></span><br><span class="line">iptables -t nat -A POSTROUTING -s 10.0.8.0/24 -o eth0 -j SNAT --to-source 100.64.8.1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 放行 FORWARD</span></span><br><span class="line">iptables -A FORWARD -s 10.0.8.0/24 -j ACCEPT</span><br><span class="line">iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT</span><br></pre></td></tr></table></figure><h2 id="四、案例-2：DNAT-端口映射"><a href="#四、案例-2：DNAT-端口映射" class="headerlink" title="四、案例 2：DNAT 端口映射"></a>四、案例 2：DNAT 端口映射</h2><p>场景：公网访问 <code>100.64.8.1:8080</code>，映射到内网 Web 服务器 <code>10.0.8.11:80</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 进网关的流量，目标地址改写为内网服务器</span></span><br><span class="line">iptables -t nat -A PREROUTING -d 100.64.8.1 -p tcp --dport 8080 -j DNAT --to-destination 10.0.8.11:80</span><br><span class="line"></span><br><span class="line"><span class="comment"># 源地址也换成网关（否则内网服务器回包找不到&quot;公网客户端&quot;路由）</span></span><br><span class="line">iptables -t nat -A POSTROUTING -d 10.0.8.11 -p tcp --dport 80 -j SNAT --to-source 100.64.8.1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 放行 FORWARD，验证</span></span><br><span class="line">iptables -A FORWARD -p tcp --dport 80 -j ACCEPT</span><br><span class="line">curl http://100.64.8.1:8080</span><br></pre></td></tr></table></figure><h2 id="五、排障要点"><a href="#五、排障要点" class="headerlink" title="五、排障要点"></a>五、排障要点</h2><ol><li><strong>规则看起来对但不生效</strong>：先看 <code>iptables -L -v -n</code> 计数器，规则没命中就往上游（PREROUTING&#x2F;路由）排查；本机访问走 INPUT，转发走 FORWARD，别弄错链。</li><li><strong>NAT 后业务不通</strong>：八成忘了回程 SNAT，或没开 <code>ip_forward</code>。</li><li><strong>重启后规则全没了</strong>：没做 save&#x2F;restore——这句几乎每次踩坑都会被想起。</li></ol><p>iptables 上手后，内网隔离、端口映射、共享上网这些场景都能自己搞定，而”包往哪走”的架构感，也是后面学 nftables、云安全组时通用的底层认知。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/06/15/iptables%E9%98%B2%E7%81%AB%E5%A2%99%E5%AE%9E%E6%88%98%E5%9B%9B%E8%A1%A8%E4%BA%94%E9%93%BE%E4%B8%8ENAT%E8%BD%AC%E5%8F%91/</id>
    <link href="https://www.lumindream.site/2023/06/15/iptables%E9%98%B2%E7%81%AB%E5%A2%99%E5%AE%9E%E6%88%98%E5%9B%9B%E8%A1%A8%E4%BA%94%E9%93%BE%E4%B8%8ENAT%E8%BD%AC%E5%8F%91/"/>
    <published>2023-06-15T02:00:00.000Z</published>
    <summary>不背命令直接上手 iptables：四表五链架构与数据包流向、常用规则写法、SNAT 共享上网与 DNAT 端口映射两个生产案例，以及规则丢失的坑。</summary>
    <title>iptables 防火墙实战：四表五链与 NAT 转发</title>
    <updated>2023-06-15T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="网络与安全" scheme="https://www.lumindream.site/categories/%E7%BD%91%E7%BB%9C%E4%B8%8E%E5%AE%89%E5%85%A8/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="网络" scheme="https://www.lumindream.site/tags/%E7%BD%91%E7%BB%9C/"/>
    <category term="SSH" scheme="https://www.lumindream.site/tags/SSH/"/>
    <content>
      <![CDATA[<h1 id="网络管理与-SSH-安全加固实战"><a href="#网络管理与-SSH-安全加固实战" class="headerlink" title="网络管理与 SSH 安全加固实战"></a>网络管理与 SSH 安全加固实战</h1><p>网络是运维的”水电煤”——不通就什么都干不了，而 SSH 又是唯一的管理通道，它的安全等级直接决定服务器被不被攻破。这篇把网络基础配置和 SSH 加固基线完整过一遍。</p><h2 id="一、网卡与-DNS-配置"><a href="#一、网卡与-DNS-配置" class="headerlink" title="一、网卡与 DNS 配置"></a>一、网卡与 DNS 配置</h2><p>CentOS 7 系网卡配置在 <code>/etc/sysconfig/network-scripts/ifcfg-eth0</code>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">TYPE=Ethernet</span><br><span class="line">BOOTPROTO=none        <span class="comment"># 服务器用固定 IP：none/static；笔记本才用 dhcp</span></span><br><span class="line">NAME=eth0</span><br><span class="line">DEVICE=eth0</span><br><span class="line">ONBOOT=<span class="built_in">yes</span>            <span class="comment"># 开机自动启用</span></span><br><span class="line">IPADDR=10.0.8.11      <span class="comment"># 内网固定 IP（本机局域网内唯一）</span></span><br><span class="line">PREFIX=24</span><br><span class="line">GATEWAY=10.0.8.1</span><br><span class="line">DNS1=223.5.5.5        <span class="comment"># 阿里云公共 DNS</span></span><br></pre></td></tr></table></figure><p>改完必须重启网络服务生效：<code>systemctl restart network</code>。</p><p>DNS 排查三连：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cat</span> /etc/resolv.conf   <span class="comment"># 本机 DNS 配置</span></span><br><span class="line"><span class="built_in">cat</span> /etc/hosts         <span class="comment"># 本机 hosts 解析</span></span><br><span class="line">nslookup / dig 域名     <span class="comment"># 实际解析验证</span></span><br></pre></td></tr></table></figure><p><strong>生产教训：DNS 配错是”最隐蔽”的网络故障</strong>——服务看起来都正常，就是偶发连接超时。排查时先确认 resolv.conf 指向可达的 DNS，再看 hosts 有没有被污染（改 hosts 前先备份）。</p><p>常用公共 DNS 记住即可：<code>223.5.5.5</code>（阿里）、<code>114.114.114.114</code>（电信）、<code>8.8.8.8</code>（谷歌）、<code>202.106.0.20</code>（联通）。</p><h2 id="二、SSH-加固：生产基线"><a href="#二、SSH-加固：生产基线" class="headerlink" title="二、SSH 加固：生产基线"></a>二、SSH 加固：生产基线</h2><p>装好 openssh-server 后，<code>/etc/ssh/sshd_config</code> 按这个基线配（每项都有明确目的）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 禁止密码登录（生产必须密钥登录）</span></span><br><span class="line">PasswordAuthentication no</span><br><span class="line"><span class="comment"># 2. 禁止 root 直接登录</span></span><br><span class="line">PermitRootLogin no</span><br><span class="line"><span class="comment"># 3. 修改端口（默认 22，避开暴力破解的常规扫描）</span></span><br><span class="line">Port 2222</span><br><span class="line"><span class="comment"># 4. 连接超时（避免无效连接占资源）</span></span><br><span class="line">ClientAliveInterval 60</span><br><span class="line">ClientAliveCountMax 3</span><br><span class="line"></span><br><span class="line">systemctl restart sshd   <span class="comment"># 重启前先检查语法：sshd -t</span></span><br></pre></td></tr></table></figure><p><strong>改端口前注意</strong>：<code>sshd -t</code> 验证配置、确认防火墙放行新端口、保持当前 SSH 会话别断开，三步都做好再重启，否则容易把自己锁在外面（我见过不止一次改配置改到连不上的现场）。</p><p>密钥登录配置流程：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 客户端生成密钥：ssh-keygen -t ed25519</span></span><br><span class="line"><span class="comment"># 2. 服务端存放公钥（目录 700、文件 600，企业规范）</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /root/.ssh &amp;&amp; <span class="built_in">chmod</span> 700 /root/.ssh</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;公钥内容&quot;</span> &gt;&gt; /root/.ssh/authorized_keys &amp;&amp; <span class="built_in">chmod</span> 600 /root/.ssh/authorized_keys</span><br><span class="line"><span class="comment"># 3. 确认密钥能登录后，再把 PasswordAuthentication 改为 no</span></span><br></pre></td></tr></table></figure><h2 id="三、一次暴力破解防护实录"><a href="#三、一次暴力破解防护实录" class="headerlink" title="三、一次暴力破解防护实录"></a>三、一次暴力破解防护实录</h2><p>事件：某台云服务器的 <code>/var/log/secure</code> 里出现大量 <code>Failed password for root</code>，来自境外 IP 的扫描在持续撞库。</p><p>应对三步：</p><ol><li>立即 <code>PermitRootLogin no</code> + 改 SSH 端口，观察 secure 日志，撞库流量明显下降；</li><li>部署 fail2ban：同一 IP 连续失败 5 次封禁 10 分钟，日志里 Failed 快速归零；</li><li>长期措施：密钥登录全覆盖 + 堡垒机（JumpServer）统一入口，服务器不再直连公网。</li></ol><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></pre></td><td class="code"><pre><span class="line">ip addr                 <span class="comment"># 查看网卡 IP（ip a）</span></span><br><span class="line">ss -tulnp               <span class="comment"># 查看监听端口（替代过时的 netstat）</span></span><br><span class="line">ss -s                   <span class="comment"># 连接统计</span></span><br><span class="line">ping / traceroute       <span class="comment"># 连通性与路由路径</span></span><br><span class="line">tcpdump -i eth0 port 80 <span class="comment"># 抓包定位（网络问题的最终手段）</span></span><br></pre></td></tr></table></figure><p>常用服务端口对照：SSH 22、HTTP 80、HTTPS 443、MySQL 3306、Redis 6379、DNS 53——排查”端口不通”时先分清是防火墙拦了还是服务没监听：<code>ss -tulnp</code> 确认监听，<code>firewall-cmd --list-all</code>（或 iptables）确认放行。</p><p>网络故障排查的核心纪律：<strong>先本机后远端、先端口后路由、先防火墙后抓包</strong>，一步步缩小范围，不要上来就抓包大海捞针。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/06/08/%E7%BD%91%E7%BB%9C%E7%AE%A1%E7%90%86%E4%B8%8ESSH%E5%AE%89%E5%85%A8%E5%8A%A0%E5%9B%BA%E5%AE%9E%E6%88%98/</id>
    <link href="https://www.lumindream.site/2023/06/08/%E7%BD%91%E7%BB%9C%E7%AE%A1%E7%90%86%E4%B8%8ESSH%E5%AE%89%E5%85%A8%E5%8A%A0%E5%9B%BA%E5%AE%9E%E6%88%98/"/>
    <published>2023-06-08T02:00:00.000Z</published>
    <summary>从网卡配置到 SSH 加固的一整套网络管理实践：静态 IP 配置、DNS 解析链路、sshd_config 生产基线，以及一次暴力破解防护实录。</summary>
    <title>网络管理与 SSH 安全加固实战</title>
    <updated>2023-06-08T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="文件系统" scheme="https://www.lumindream.site/tags/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/"/>
    <content>
      <![CDATA[<h1 id="文件系统深入：inode、软硬链接与高效查找"><a href="#文件系统深入：inode、软硬链接与高效查找" class="headerlink" title="文件系统深入：inode、软硬链接与高效查找"></a>文件系统深入：inode、软硬链接与高效查找</h1><p>文件系统相关的故障往往最反直觉：<code>df -h</code> 明明有空间却写不进去、删了大文件空间却没变、文件名带特殊字符删不掉。这篇从 inode 机制讲起，把这类问题的原理和解决办法收在一起。</p><h2 id="一、inode：文件系统里最被低估的概念"><a href="#一、inode：文件系统里最被低估的概念" class="headerlink" title="一、inode：文件系统里最被低估的概念"></a>一、inode：文件系统里最被低估的概念</h2><p>文件在磁盘上分两部分：<strong>inode</strong>（存放元数据：权限、属主、大小、指向数据块的指针）和<strong>数据块</strong>（真正的内容）。文件名只是 inode 的一个”门牌”。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">ls</span> -i 文件名        <span class="comment"># 查看 inode 号</span></span><br><span class="line"><span class="built_in">stat</span> 文件名         <span class="comment"># inode 的完整元数据</span></span><br><span class="line"><span class="built_in">df</span> -i               <span class="comment"># 看 inode 使用率（IUse% 是否 100%）</span></span><br></pre></td></tr></table></figure><p><strong>经典故障：磁盘有空间但写不进去</strong>。<code>df -h</code> 还剩 20G，但建文件报 <code>No space left on device</code>——查 <code>df -i</code>，IUse% 100%，全是小文件把 inode 耗尽了。定位小文件最多的目录：</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">find /data -<span class="built_in">type</span> f | <span class="built_in">cut</span> -d/ -f3 | <span class="built_in">sort</span> | <span class="built_in">uniq</span> -c | <span class="built_in">sort</span> -nr | <span class="built_in">head</span> -10</span><br></pre></td></tr></table></figure><p>清理或归档这些小文件（通常是日志、缓存、临时文件）即可恢复。<strong>inode 或磁盘空间任意一个满，磁盘都无法写入。</strong></p><h2 id="二、软链接-vs-硬链接"><a href="#二、软链接-vs-硬链接" class="headerlink" title="二、软链接 vs 硬链接"></a>二、软链接 vs 硬链接</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">ln</span> 源文件 硬链接      <span class="comment"># 硬链接：共享同一个 inode</span></span><br><span class="line"><span class="built_in">ln</span> -s 源文件 软链接   <span class="comment"># 软链接：独立 inode，指向路径</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>特性</th><th>硬链接</th><th>软链接</th></tr></thead><tbody><tr><td>inode</td><td>相同</td><td>不同</td></tr><tr><td>删除源文件</td><td>链接依然有效</td><td>链接失效（红底白字）</td></tr><tr><td>跨文件系统</td><td>不可以</td><td>可以</td></tr><tr><td>目录</td><td>不可以</td><td>可以</td></tr></tbody></table><p>生产中最常用的其实是软链接三件事：</p><ol><li><strong>保持路径不变，解决磁盘不够</strong>：数据迁到大盘，软链回原路径，应用无感知；</li><li><strong>代码上线</strong>：<code>current -&gt; release-20230510</code>，切换即回滚；</li><li><strong>去软件版本号</strong>：<code>/usr/local/mysql -&gt; mysql-5.7.42</code>。</li></ol><h2 id="三、find：高段位用法"><a href="#三、find：高段位用法" class="headerlink" title="三、find：高段位用法"></a>三、find：高段位用法</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><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 基本：名称/类型/深度</span></span><br><span class="line">find ./ -name <span class="string">&quot;*.log&quot;</span> -<span class="built_in">type</span> f</span><br><span class="line">find ./ -maxdepth 2 -<span class="built_in">type</span> d</span><br><span class="line"></span><br><span class="line"><span class="comment"># 按大小：+10M 大于 / -10M 小于 / 组合区间</span></span><br><span class="line">find ./ -size +10M</span><br><span class="line">find ./ -size +10M -a -size -15M</span><br><span class="line"></span><br><span class="line"><span class="comment"># 按修改时间：-mtime +7 七天前改过 / -mmin -60 一小时内</span></span><br><span class="line">find ./ -mtime +7</span><br><span class="line">find ./ -mmin -30 -name <span class="string">&quot;*.txt&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按 inode 找（删特殊文件名的文件）</span></span><br><span class="line">find . -inum 123456 -delete</span><br></pre></td></tr></table></figure><p>面试和生产都高频的经典题——删 7 天前的日志：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">find /var/log -<span class="built_in">type</span> f -mtime +7 -<span class="built_in">exec</span> <span class="built_in">rm</span> -f &#123;&#125; \;</span><br><span class="line"><span class="comment"># 更稳的写法：先 -exec ls -l 复查，确认无误再执行</span></span><br><span class="line">find /var/log -<span class="built_in">type</span> f -mtime +7 -<span class="built_in">exec</span> <span class="built_in">ls</span> -l &#123;&#125; \;</span><br></pre></td></tr></table></figure><p>文件名带空格、特殊字符时用 <code>-print0</code> + <code>xargs -0</code> 安全处理：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">find . -name <span class="string">&quot;*.log&quot;</span> -print0 | xargs -0 <span class="built_in">rm</span></span><br></pre></td></tr></table></figure><h2 id="四、权限规范：三个”绝不做”"><a href="#四、权限规范：三个”绝不做”" class="headerlink" title="四、权限规范：三个”绝不做”"></a>四、权限规范：三个”绝不做”</h2><ul><li><strong>绝不做 <code>chmod 777</code></strong>：任何场景都不给全权限，最小权限原则是底线（面试问到”为什么不用 777”就答这条）；</li><li><strong>绝不拿 <code>-R</code> 递归改系统目录</strong>：<code>chmod -R</code> &#x2F; <code>chown -R</code> 只准作用于业务目录，误改 <code>/etc</code>、<code>/bin</code> 会直接搞崩系统；</li><li><strong>服务文件权限匹配运行用户</strong>：nginx 文件归 <code>nginx:nginx</code>、mysql 文件归 <code>mysql:mysql</code>，这是服务能正常读写的前提。</li></ul><p>常规权限速查：<code>644</code> 配置文件、<code>755</code> 脚本&#x2F;目录、<code>600</code> 敏感文件、<code>750</code> 业务私密目录。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">chown</span> -R nginx:nginx /usr/local/nginx/html   <span class="comment"># 部署后必做：属主属组对齐</span></span><br><span class="line"><span class="built_in">umask</span>                                          <span class="comment"># 默认权限由 022 派生：文件 644、目录 755</span></span><br></pre></td></tr></table></figure><h2 id="五、一次”空间不释放”排查实录"><a href="#五、一次”空间不释放”排查实录" class="headerlink" title="五、一次”空间不释放”排查实录"></a>五、一次”空间不释放”排查实录</h2><p>现象：删了几个 G 的大日志，<code>df -h</code> 空间一点没变。</p><p>排查：</p><ol><li><code>lsof | grep deleted</code> → 找到被删除但仍被进程持有的文件，确认真凶是正在写日志的 java 进程；</li><li>直接重启进程会导致应用短暂中断（不可取）——生产做法：<code>&gt; /proc/&lt;pid&gt;/fd/&lt;句柄号&gt;</code> 清空句柄指向的内容，空间立即释放，应用无感知；</li><li>事后把”日志按天切割 + logrotate 轮转 + 保留 7 天”写进规范，从根上避免大日志长期占用。</li></ol><p>文件系统的坑大多是”原理没吃透 + 操作不规范”叠加出来的，把 inode、链接、权限这三块理解透，排障时基本能一眼定位。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/05/31/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%B7%B1%E5%85%A5inode%E8%BD%AF%E7%A1%AC%E9%93%BE%E6%8E%A5%E4%B8%8E%E9%AB%98%E6%95%88%E6%9F%A5%E6%89%BE/</id>
    <link href="https://www.lumindream.site/2023/05/31/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%B7%B1%E5%85%A5inode%E8%BD%AF%E7%A1%AC%E9%93%BE%E6%8E%A5%E4%B8%8E%E9%AB%98%E6%95%88%E6%9F%A5%E6%89%BE/"/>
    <published>2023-05-31T02:00:00.000Z</published>
    <summary>文件删不掉、磁盘空间不释放、inode 耗尽——三个真实场景理解 Linux 文件系统：inode 机制、软硬链接区别、find 高阶用法与权限规范。</summary>
    <title>文件系统深入：inode、软硬链接与高效查找</title>
    <updated>2023-05-31T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="权限管理" scheme="https://www.lumindream.site/tags/%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86/"/>
    <category term="sudo" scheme="https://www.lumindream.site/tags/sudo/"/>
    <content>
      <![CDATA[<h1 id="用户权限与-sudo-提权规范实践"><a href="#用户权限与-sudo-提权规范实践" class="headerlink" title="用户权限与 sudo 提权规范实践"></a>用户权限与 sudo 提权规范实践</h1><p>接手一套生产环境时，我最先看的就是账号体系：有多少人知道 root 密码、普通用户被授了什么权。账号体系乱的环境，安全事件只是时间问题。这篇整理一套可落地的用户与提权规范。</p><h2 id="一、用户分类与-UID-规划"><a href="#一、用户分类与-UID-规划" class="headerlink" title="一、用户分类与 UID 规划"></a>一、用户分类与 UID 规划</h2><table><thead><tr><th>用户类型</th><th>UID</th><th>用途</th></tr></thead><tbody><tr><td>root（管理员）</td><td>0</td><td>系统管理</td></tr><tr><td>普通用户</td><td>1000+</td><td>登录操作</td></tr><tr><td>虚拟用户</td><td>1-999</td><td>跑服务用（mysql、nginx 等），不可登录</td></tr></tbody></table><p>生产铁律：<strong>任何对外服务绝不用 root 跑</strong>，每个服务建独立虚拟用户，权限最小化。</p><p>用户管理的几个关键文件：</p><ul><li><code>/etc/passwd</code>：用户信息（密码位永远是 x，真正的密码在 shadow）</li><li><code>/etc/shadow</code>：加密后的密码</li><li><code>/etc/group</code>：组信息</li><li><code>/etc/skel/</code>：新用户家目录的模板</li></ul><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">useradd ops</span><br><span class="line"><span class="comment"># 创建虚拟用户：指定 UID/GID、不建家目录、禁止登录</span></span><br><span class="line">groupadd -g 888 app</span><br><span class="line">useradd -u 888 -g 888 -M -s /sbin/nologin app</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除用户（-r 连文件一起删）</span></span><br><span class="line">userdel -r ops</span><br></pre></td></tr></table></figure><h2 id="二、su-与-su-的区别（高频踩坑点）"><a href="#二、su-与-su-的区别（高频踩坑点）" class="headerlink" title="二、su 与 su - 的区别（高频踩坑点）"></a>二、su 与 su - 的区别（高频踩坑点）</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">su ops       <span class="comment"># 借用身份，但 PATH/环境变量还是原来的（non-login shell）</span></span><br><span class="line">su - ops     <span class="comment"># 完全&quot;变成&quot;这个用户：环境、家目录、PATH 全换（login shell）</span></span><br></pre></td></tr></table></figure><p>经典坑：用 <code>su root</code>（不带横杠）切过去后 <code>echo $PATH</code> 里没有 <code>/usr/sbin</code>、<code>/sbin</code>，执行某些命令直接 <code>command not found</code>。原因就是 non-login shell 只读 <code>~/.bashrc</code>，不读 <code>/etc/profile</code> 系列。</p><table><thead><tr><th>命令</th><th>切换后身份</th><th>家目录&#x2F;HOME</th><th>环境</th><th>要输谁的密码</th></tr></thead><tbody><tr><td><code>su</code> &#x2F; <code>su root</code></td><td>root</td><td>不变</td><td>不加载 root 的</td><td>root 密码</td></tr><tr><td><code>su -</code> &#x2F; <code>su - root</code></td><td>root</td><td>&#x2F;root</td><td>加载 root 的</td><td>root 密码</td></tr><tr><td><code>su - mysql</code></td><td>mysql</td><td>&#x2F;home&#x2F;mysql</td><td>加载 mysql 的</td><td>mysql 密码</td></tr></tbody></table><h2 id="三、sudo：最小权限提权"><a href="#三、sudo：最小权限提权" class="headerlink" title="三、sudo：最小权限提权"></a>三、sudo：最小权限提权</h2><p>sudo 的正解是”把最小必要权限授给该用的人”，而不是把 root 密码交出去。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">visudo   <span class="comment"># 编辑 /etc/sudoers（自带语法检测，优先用它）</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 授权单个命令</span></span><br><span class="line">ops  ALL=(ALL)  /usr/bin/cat</span><br><span class="line"></span><br><span class="line"><span class="comment"># 授权多个命令（给开发/测试）</span></span><br><span class="line">ops  ALL=(ALL)  /usr/bin/cat,/usr/bin/cd</span><br><span class="line"></span><br><span class="line"><span class="comment"># 全权+取反（运维常用：除了 rm 都行）</span></span><br><span class="line">ops  ALL=(ALL)  NOPASSWD: ALL,!/usr/bin/rm</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用与查看</span></span><br><span class="line"><span class="built_in">sudo</span> -l                              <span class="comment"># 自己有哪些提权命令</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">cat</span> /var/log/secure             <span class="comment"># 提权执行</span></span><br></pre></td></tr></table></figure><p>sudo 配置的坑有两类：</p><ol><li><strong>给了 <code>NOPASSWD: ALL</code> 等于裸奔</strong>：提权后 rm、chmod 都能干。给 ALL 时一定要配合 <code>!</code> 取反关键危险命令，或者干脆按命令列表授。</li><li><strong>授权命令写相对路径</strong>：sudoers 里命令必须是绝对路径（<code>which cat</code> 先查绝对路径），否则规则永远不生效。</li></ol><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></pre></td><td class="code"><pre><span class="line">last      <span class="comment"># 登录详细信息（来源 IP、时间、时长）</span></span><br><span class="line">lastlog   <span class="comment"># 每个用户最后一次登录时间</span></span><br></pre></td></tr></table></figure><h2 id="五、一次-root-直登整改记录"><a href="#五、一次-root-直登整改记录" class="headerlink" title="五、一次 root 直登整改记录"></a>五、一次 root 直登整改记录</h2><p>接手时发现多台服务器 <code>sshd_config</code> 里 <code>PermitRootLogin yes</code>，且 root 用弱密码——意味着任何能猜到密码的人都能直接拿到最高权限。</p><p>整改三步：</p><ol><li>关 root 远程直登：<code>PermitRootLogin no</code>，重启 sshd；</li><li>给运维同事建 <code>ops</code> 账号，按职责授 sudo 最小权限（开发只有日志查看权，运维才有管理权）；</li><li>推行 sudo 日志留痕：<code>visudo</code> 里加上 <code>Defaults logfile=/var/log/sudo.log</code>。</li></ol><p>结果：root 密码从”人人皆知”变成”仅紧急情况两人知晓”，日常操作全部走 sudo + 留痕，事后审计有据可查。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/05/24/%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%E4%B8%8Esudo%E6%8F%90%E6%9D%83%E8%A7%84%E8%8C%83%E5%AE%9E%E8%B7%B5/</id>
    <link href="https://www.lumindream.site/2023/05/24/%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%E4%B8%8Esudo%E6%8F%90%E6%9D%83%E8%A7%84%E8%8C%83%E5%AE%9E%E8%B7%B5/"/>
    <published>2023-05-24T02:00:00.000Z</published>
    <summary>生产账号体系怎么建：用户分类与 UID 规划、passwd 文件解读、su 与 sudo 的正确用法、最小权限提权配置，以及 root 直登的整改记录。</summary>
    <title>用户权限与 sudo 提权规范实践</title>
    <updated>2023-05-24T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="性能排查" scheme="https://www.lumindream.site/tags/%E6%80%A7%E8%83%BD%E6%8E%92%E6%9F%A5/"/>
    <content>
      <![CDATA[<h1 id="进程与性能排查实战：从-ps-top-到负载分析"><a href="#进程与性能排查实战：从-ps-top-到负载分析" class="headerlink" title="进程与性能排查实战：从 ps&#x2F;top 到负载分析"></a>进程与性能排查实战：从 ps&#x2F;top 到负载分析</h1><p>“服务器变慢了”是运维收到最多的反馈，但它背后可能是 CPU、内存、磁盘 IO、网络任意一环的问题。这篇把排查思路和工具串成一条完整的链路，遇到问题按顺序走，很少会抓瞎。</p><h2 id="一、排查思路：先定位资源，再定位进程"><a href="#一、排查思路：先定位资源，再定位进程" class="headerlink" title="一、排查思路：先定位资源，再定位进程"></a>一、排查思路：先定位资源，再定位进程</h2><p>标准四问：</p><ol><li>谁在吃 CPU？→ <code>top</code> &#x2F; <code>ps aux --sort=-%cpu</code></li><li>谁在吃内存？→ <code>free -h</code> &#x2F; <code>top</code> &#x2F; <code>ps aux --sort=-%mem</code></li><li>谁在等 IO？→ <code>top</code>（看 D 状态）&#x2F; <code>iostat</code></li><li>谁在占端口&#x2F;文件？→ <code>lsof</code> &#x2F; <code>ss</code></li></ol><h2 id="二、ps：进程快照"><a href="#二、ps：进程快照" class="headerlink" title="二、ps：进程快照"></a>二、ps：进程快照</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></pre></td><td class="code"><pre><span class="line">ps aux                          <span class="comment"># 完整信息（%CPU %MEM STAT）</span></span><br><span class="line">ps -ef                          <span class="comment"># 完整格式（含 PPID、启动时间）</span></span><br><span class="line">ps aux --<span class="built_in">sort</span>=-%cpu | <span class="built_in">head</span> -20  <span class="comment"># 按 CPU 排序</span></span><br><span class="line">ps aux --<span class="built_in">sort</span>=-%mem | <span class="built_in">head</span> -20  <span class="comment"># 按内存排序</span></span><br><span class="line">ps -ef --forest | grep -A5 nginx  <span class="comment"># 进程树，看父子关系</span></span><br></pre></td></tr></table></figure><p>STAT 列是重点——它直接告诉你进程卡在哪：</p><table><thead><tr><th>状态</th><th>含义</th><th>排查提示</th></tr></thead><tbody><tr><td>R</td><td>运行&#x2F;排队等 CPU</td><td>结合 %CPU 看是否异常</td></tr><tr><td>S</td><td>睡眠等事件</td><td>正常</td></tr><tr><td>D</td><td>不可中断的磁盘等待</td><td><strong>磁盘有问题</strong>（NFS 挂、磁盘故障），kill 不掉</td></tr><tr><td>Z</td><td>僵尸进程</td><td>父进程没 wait() 收尸，找父进程处理</td></tr><tr><td>T</td><td>被暂停</td><td>如 Ctrl+Z</td></tr></tbody></table><h2 id="三、top：动态监控"><a href="#三、top：动态监控" class="headerlink" title="三、top：动态监控"></a>三、top：动态监控</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></pre></td><td class="code"><pre><span class="line">top</span><br><span class="line"><span class="comment"># 交互键：P 按CPU排序 M 按内存 T 按时间 1 展开每核 c 完整命令 H 看线程</span></span><br><span class="line">top -u www-data        <span class="comment"># 只看某用户的进程</span></span><br><span class="line">top -Hp 1234           <span class="comment"># 看线程级（排查 Java 线程吃 CPU 必备）</span></span><br></pre></td></tr></table></figure><p>负载的判读：<code>load average: 12.50, 8.30, 4.20</code> 是 1&#x2F;5&#x2F;15 分钟平均负载。<strong>负载要和 CPU 核数对比</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">nproc</span>   <span class="comment"># 查看核数</span></span><br><span class="line"><span class="comment"># 以 4 核为例：负载 &lt;4 正常；=4 跑满；&gt;4 有排队；&gt;8 严重过载立即查</span></span><br></pre></td></tr></table></figure><p>CPU 各列关注 <code>wa</code>（iowait）和 <code>si</code>（软中断）：<code>wa &gt; 20%</code> 立刻查磁盘 IO（<code>iostat</code>）；<code>si</code> 高说明网络流量大，查网卡和连接数。</p><p>内存看 <code>free -h</code>，重点盯 <code>si/so</code>（swap 换入换出）：<code>vmstat 1</code> 如果 si&#x2F;so 持续非零，说明内存吃紧在疯狂换页，要扩容或优化应用。</p><h2 id="四、lsof：谁占用了什么"><a href="#四、lsof：谁占用了什么" class="headerlink" title="四、lsof：谁占用了什么"></a>四、lsof：谁占用了什么</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></pre></td><td class="code"><pre><span class="line">lsof -i :80          <span class="comment"># 谁在监听 80 端口</span></span><br><span class="line">lsof -p 1234         <span class="comment"># 某进程打开了哪些文件</span></span><br><span class="line">lsof | grep deleted  <span class="comment"># 查&quot;文件删了但空间没释放&quot;的元凶</span></span><br><span class="line">lsof +D /data        <span class="comment"># 谁占用了某目录（umount 报 busy 时用）</span></span><br></pre></td></tr></table></figure><p>经典场景：<code>rm</code> 了大日志但 <code>df -h</code> 空间没变——进程还持有文件句柄，文件没真正释放。解决：重启进程，或 <code>&gt; /proc/进程PID/fd/句柄号</code> 清空。</p><h2 id="五、一次-Java-线程高-CPU-排查实录"><a href="#五、一次-Java-线程高-CPU-排查实录" class="headerlink" title="五、一次 Java 线程高 CPU 排查实录"></a>五、一次 Java 线程高 CPU 排查实录</h2><p>现象：业务反馈接口 P99 飙升，<code>top</code> 看到 java 进程 CPU 400%（占满 4 核）。</p><p>排查链路：</p><ol><li><code>top -Hp 1234</code> 找到最耗 CPU 的线程 PID（比如 3039）；</li><li>转十六进制：<code>printf &quot;%x\n&quot; 3039</code> → <code>bdf</code>；</li><li><code>jstack 1234 | grep -A20 &#39;nid=0xbdf&#39;</code> → 定位到具体业务线程和代码行；</li><li>发现是某个批量任务循环里不断创建连接未释放，上线前压测没覆盖到；修复后二次压测，CPU 回到 20% 以内。</li></ol><h2 id="六、工具补充记忆点"><a href="#六、工具补充记忆点" class="headerlink" title="六、工具补充记忆点"></a>六、工具补充记忆点</h2><ul><li><code>pidstat -u 2 5</code>：每 2 秒采样 5 次看进程 CPU；<code>-d</code> 看 IO；<code>-w</code> 看上下文切换（自愿切换多&#x3D;在等锁&#x2F;IO，非自愿多&#x3D;CPU 竞争激烈）</li><li><code>pmap -x &lt;pid&gt;</code>：进程内存分布</li><li><code>/proc/cpuinfo</code>、<code>/proc/meminfo</code>、<code>/proc/loadavg</code>、<code>/proc/&lt;pid&gt;/cmdline</code>：最底层数据来源，没有工具时直接读这里</li></ul><p>排查性能问题没有银弹，但固定这套”先资源、后进程、再线程”的顺序，大部分问题都能在半小时内定位到根因。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/05/17/%E8%BF%9B%E7%A8%8B%E4%B8%8E%E6%80%A7%E8%83%BD%E6%8E%92%E6%9F%A5%E5%AE%9E%E6%88%98/</id>
    <link href="https://www.lumindream.site/2023/05/17/%E8%BF%9B%E7%A8%8B%E4%B8%8E%E6%80%A7%E8%83%BD%E6%8E%92%E6%9F%A5%E5%AE%9E%E6%88%98/"/>
    <published>2023-05-17T02:00:00.000Z</published>
    <summary>线上变慢怎么办：ps/top/free/lsof 一套组合拳定位 CPU、内存、IO 瓶颈，负载与进程状态的正确解读，以及 Java 线程高 CPU 的真实排查案例。</summary>
    <title>进程与性能排查实战：从 ps/top 到负载分析</title>
    <updated>2023-05-17T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="Yum" scheme="https://www.lumindream.site/tags/Yum/"/>
    <category term="Apt" scheme="https://www.lumindream.site/tags/Apt/"/>
    <content>
      <![CDATA[<h1 id="软件包管理避坑指南：Yum-Apt-换源与生产实践"><a href="#软件包管理避坑指南：Yum-Apt-换源与生产实践" class="headerlink" title="软件包管理避坑指南：Yum &#x2F; Apt 换源与生产实践"></a>软件包管理避坑指南：Yum &#x2F; Apt 换源与生产实践</h1><p>软件管理是所有 Linux 操作的入口，装错了源、乱跑了 update，轻则环境不可用，重则直接干崩生产。这篇把两系包管理的日常操作和生产避坑点整理成一份清单。</p><h2 id="一、先建立两层结构的心智模型"><a href="#一、先建立两层结构的心智模型" class="headerlink" title="一、先建立两层结构的心智模型"></a>一、先建立两层结构的心智模型</h2><p>不管哪个发行版，软件管理都是两层：</p><ul><li><strong>高层工具</strong>（自动解决依赖）：RedHat 系 <code>yum/dnf</code>、Debian 系 <code>apt/apt-get</code>——生产中 99% 的场景用它们；</li><li><strong>底层工具</strong>（只管单个包）：<code>rpm</code>、<code>dpkg</code>——只在装本地安装包、排查依赖时用。</li></ul><p>配置文件位置：RedHat 系在 <code>/etc/yum.repos.d/</code>（每个 <code>.repo</code> 一个源），Debian 系在 <code>/etc/apt/sources.list</code> 和 <code>sources.list.d/</code>。</p><h2 id="二、RedHat-系日常操作"><a href="#二、RedHat-系日常操作" class="headerlink" title="二、RedHat 系日常操作"></a>二、RedHat 系日常操作</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><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安装</span></span><br><span class="line">yum install -y nginx              <span class="comment"># -y 自动确认（脚本里必须加）</span></span><br><span class="line">yumdownloader --resolve nginx     <span class="comment"># 只下载不安装（排查依赖问题用）</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 查询</span></span><br><span class="line">yum info nginx                    <span class="comment"># 包信息</span></span><br><span class="line">rpm -qa                           <span class="comment"># 已安装的所有包</span></span><br><span class="line">rpm -ql nginx                     <span class="comment"># 某个包装了哪些文件</span></span><br><span class="line">rpm -qf /usr/sbin/nginx           <span class="comment"># 反查：这个文件属于哪个包</span></span><br><span class="line">rpm -qi nginx                     <span class="comment"># 包的详细信息</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 升级（生产慎用！）</span></span><br><span class="line">yum update --security -y          <span class="comment"># 只更新安全补丁（生产推荐）</span></span><br><span class="line">yum update -y                     <span class="comment"># 全量更新——可能升级内核导致重启起不来</span></span><br></pre></td></tr></table></figure><p><strong>全量 <code>yum update</code> 是生产大忌</strong>。我吃过一次亏：凌晨跑了个全量升级，把内核从 3.10 升到了新版本，第二天重启服务器直接进不去系统，最后靠 grub 手动切回旧内核才救回来。从那以后生产只做 <code>--security</code> 安全更新，大版本升级一律走变更评审 + 灰度环境验证。</p><p>换源（阿里云，CentOS 7 为例）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> /etc/yum.repos.d/bak</span><br><span class="line"><span class="built_in">mv</span> /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/bak/</span><br><span class="line">curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo</span><br><span class="line">yum clean all &amp;&amp; yum makecache</span><br></pre></td></tr></table></figure><p>本地 rpm 安装（底层工具）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">rpm -ivh nginx-1.20.1-1.el7.x86_64.rpm   <span class="comment"># 安装本地包（-i 安装 -v 详细 -h 进度条）</span></span><br><span class="line">rpm -Uvh nginx-1.20.1-1.el7.x86_64.rpm   <span class="comment"># 升级安装（没装过就装，装过就升）</span></span><br><span class="line">rpm -e nginx                             <span class="comment"># 卸载</span></span><br><span class="line">rpm -e --nodeps nginx                    <span class="comment"># 强删（极少用，除非确认后果）</span></span><br></pre></td></tr></table></figure><h2 id="三、Debian-系日常操作"><a href="#三、Debian-系日常操作" class="headerlink" title="三、Debian 系日常操作"></a>三、Debian 系日常操作</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><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="comment"># 源：deb = 二进制包源（一般用不到 deb-src 源码源）</span></span><br><span class="line"><span class="comment"># 组件：main/restricted/universe/multiverse（开源程度不同）</span></span><br><span class="line"></span><br><span class="line">apt update                              <span class="comment"># 刷新索引（相当于 makecache）</span></span><br><span class="line">apt install -y nginx</span><br><span class="line">apt search nginx</span><br><span class="line">apt show nginx                          <span class="comment"># 包信息</span></span><br><span class="line">apt depends nginx                       <span class="comment"># 依赖关系</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 升级：只更新已装包（不增删依赖）</span></span><br><span class="line">apt update &amp;&amp; apt upgrade -y</span><br><span class="line"><span class="comment"># 完整升级：会处理依赖变更，可能删旧包</span></span><br><span class="line">apt full-upgrade -y</span><br><span class="line"></span><br><span class="line">apt remove nginx                        <span class="comment"># 卸载保留配置</span></span><br><span class="line">apt purge nginx                         <span class="comment"># 彻底卸载（连 /etc 配置一起删）</span></span><br><span class="line">apt autoremove -y                       <span class="comment"># 清理孤立依赖（装完卸完跑一下）</span></span><br></pre></td></tr></table></figure><p>本地 deb 安装与依赖修复：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">dpkg -i nginx_1.18.0-0ubuntu1_amd64.deb</span><br><span class="line">apt install -f -y                       <span class="comment"># 报依赖错误时修复，自动补装缺失依赖</span></span><br><span class="line">dpkg -l nginx                           <span class="comment"># 状态标记：ii=已安装, rc=删了但配置残留</span></span><br><span class="line">dpkg -S /usr/sbin/nginx                 <span class="comment"># 反查文件属于哪个包</span></span><br></pre></td></tr></table></figure><h2 id="四、两个高频排障场景"><a href="#四、两个高频排障场景" class="headerlink" title="四、两个高频排障场景"></a>四、两个高频排障场景</h2><ol><li><strong>装包报依赖错误</strong>：先 <code>yum search/yum deplist</code>（或 <code>apt depends</code>）看依赖闭包，缺什么补什么；本地包优先用高层工具的本地安装参数（<code>yum localinstall</code>），让依赖自动解决。</li><li><strong><code>rpm -qf</code> 反查没结果</strong>：文件可能是手动编译安装的，不在任何 rpm 包内——这类文件升级时要特别注意，卸载重装会丢。</li></ol><h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>包管理的核心纪律就三条：<strong>换源用国内镜像、生产只做安全更新、卸载前看清依赖提示</strong>。把这三点写进初始化检查清单（见《Linux 发行版选型与系统初始化实践》），基本能避开 90% 的软件管理事故。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/05/10/%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%AE%A1%E7%90%86%E9%81%BF%E5%9D%91%E6%8C%87%E5%8D%97yum%E4%B8%8Eapt%E6%8D%A2%E6%BA%90%E5%AE%9E%E8%B7%B5/</id>
    <link href="https://www.lumindream.site/2023/05/10/%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%AE%A1%E7%90%86%E9%81%BF%E5%9D%91%E6%8C%87%E5%8D%97yum%E4%B8%8Eapt%E6%8D%A2%E6%BA%90%E5%AE%9E%E8%B7%B5/"/>
    <published>2023-05-10T02:00:00.000Z</published>
    <summary>线上线下两套环境的软件包管理经验：yum/apt 换源、装包卸载避坑、本地 rpm/deb 安装、依赖排查，以及 update 全量升级的教训。</summary>
    <title>软件包管理避坑指南：Yum / Apt 换源与生产实践</title>
    <updated>2023-05-10T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="日志" scheme="https://www.lumindream.site/tags/%E6%97%A5%E5%BF%97/"/>
    <content>
      <![CDATA[<h1 id="日志排查体系：journalctl-与生产日志轮转"><a href="#日志排查体系：journalctl-与生产日志轮转" class="headerlink" title="日志排查体系：journalctl 与生产日志轮转"></a>日志排查体系：journalctl 与生产日志轮转</h1><p>线上出故障时，第一步永远是翻日志。但日志查得好不好，直接决定定位问题的速度。这篇整理 systemd 生态下 journald &#x2F; journalctl 的完整用法，以及生产环境怎么把日志管住、不爆盘。</p><h2 id="一、journalctl：集中式日志查询"><a href="#一、journalctl：集中式日志查询" class="headerlink" title="一、journalctl：集中式日志查询"></a>一、journalctl：集中式日志查询</h2><p>systemd 自带 <code>systemd-journald</code> 守护进程，把内核消息、系统服务、自定义服务的输出全部收集进一个二进制数据库（<code>/run/log/journal/</code> 或持久化后的 <code>/var/log/journal/</code>）。<code>journalctl</code> 就是查询它的工具。</p><p>一句话说清它的定位：”journalctl 是 systemd 生态的日志查询命令，集中管理所有 systemd 单元和内核日志，支持结构化过滤和持久化存储。”</p><h3 id="常用查询"><a href="#常用查询" class="headerlink" title="常用查询"></a>常用查询</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 看某个服务的日志（生产最常用）</span></span><br><span class="line">journalctl -u nginx.service</span><br><span class="line">journalctl -u nginx -f              <span class="comment"># 实时跟踪（类似 tail -f）</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按时间过滤</span></span><br><span class="line">journalctl --since <span class="string">&quot;2023-04-01 10:00:00&quot;</span> --<span class="keyword">until</span> <span class="string">&quot;2023-04-01 11:00:00&quot;</span></span><br><span class="line">journalctl -u 服务名 --since <span class="string">&quot;1 hour ago&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本次启动以来的日志（重启后查故障原因必备）</span></span><br><span class="line">journalctl -b                       <span class="comment"># 当前启动</span></span><br><span class="line">journalctl -b -1                    <span class="comment"># 上一次启动</span></span><br><span class="line">journalctl --list-boots             <span class="comment"># 列出所有启动记录</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 按优先级过滤</span></span><br><span class="line">journalctl -p err                   <span class="comment"># 只看错误及以上</span></span><br><span class="line"><span class="comment"># 级别：emerg, alert, crit, err, warning, notice, info, debug</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 内核日志 / 指定进程</span></span><br><span class="line">journalctl -k</span><br><span class="line">journalctl _PID=1234</span><br></pre></td></tr></table></figure><h3 id="踩过的坑：journald-没持久化"><a href="#踩过的坑：journald-没持久化" class="headerlink" title="踩过的坑：journald 没持久化"></a>踩过的坑：journald 没持久化</h3><p>有段时间重启服务器后 <code>journalctl -b -1</code> 查不到上次的日志，一度以为是命令写错了。查了一圈才发现：CentOS 7 最小化安装时，journald 的日志默认存在<strong>内存</strong>里（<code>/run/log/journal</code>），一重启全清空。</p><p>解法是建持久化目录：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p /var/log/journal</span><br><span class="line">systemd-tmpfiles --create --prefix /var/log/journal</span><br><span class="line">systemctl restart systemd-journald</span><br><span class="line"></span><br><span class="line"><span class="comment"># 同时限制日志大小防爆盘（编辑 /etc/systemd/journald.conf）</span></span><br><span class="line"><span class="comment"># SystemMaxUse=2G       日志最多占 2G，超了自动删最老的</span></span><br><span class="line"><span class="comment"># SystemKeepFree=500M   至少给系统留 500M 空闲</span></span><br><span class="line"><span class="comment"># MaxRetentionSec=1month 最多保留 1 个月</span></span><br><span class="line">systemctl restart systemd-journald</span><br></pre></td></tr></table></figure><h2 id="二、logrotate：防爆盘的根本"><a href="#二、logrotate：防爆盘的根本" class="headerlink" title="二、logrotate：防爆盘的根本"></a>二、logrotate：防爆盘的根本</h2><p>journald 只管自己的库，业务日志（nginx、应用自己打的日志）得靠 logrotate 管。配置在 <code>/etc/logrotate.conf</code>（全局）+ <code>/etc/logrotate.d/</code>（每个服务一个文件）。</p><p>以 nginx 为例的标准配置：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">/var/log/nginx/*.<span class="built_in">log</span> &#123;</span><br><span class="line">    daily              <span class="comment"># 每天切一次</span></span><br><span class="line">    rotate 7           <span class="comment"># 保留 7 份旧的</span></span><br><span class="line">    compress           <span class="comment"># 旧日志压缩成 .gz</span></span><br><span class="line">    delaycompress      <span class="comment"># 昨天的先不压，方便临时查</span></span><br><span class="line">    missingok          <span class="comment"># 文件不存在不报错</span></span><br><span class="line">    notifempty         <span class="comment"># 空文件不轮转</span></span><br><span class="line">    sharedscripts</span><br><span class="line">    postrotate</span><br><span class="line">        [ -f /var/run/nginx.pid ] &amp;&amp; <span class="built_in">kill</span> -USR1 `<span class="built_in">cat</span> /var/run/nginx.pid`  <span class="comment"># 通知 nginx 重开日志文件</span></span><br><span class="line">    endscript</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>两个验证命令先背下来：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">logrotate -d /etc/logrotate.d/nginx   <span class="comment"># 调试模式，只演练不真执行，查语法</span></span><br><span class="line">logrotate -f /etc/logrotate.d/nginx   <span class="comment"># 强制立刻轮转一次，验证生效</span></span><br></pre></td></tr></table></figure><h2 id="三、配套排查：系统日志文件"><a href="#三、配套排查：系统日志文件" class="headerlink" title="三、配套排查：系统日志文件"></a>三、配套排查：系统日志文件</h2><p>除了 journald，传统系统日志文件依然是安全排查的一线阵地：</p><ul><li><code>/var/log/messages</code>：系统日志</li><li><code>/var/log/secure</code>：系统登录和退出日志——<strong>如果 secure 里出现大量 Failed，说明有人在暴力破解密码</strong>，要立刻加固 SSH</li></ul><h2 id="四、一次”查不到日志”的完整复盘"><a href="#四、一次”查不到日志”的完整复盘" class="headerlink" title="四、一次”查不到日志”的完整复盘"></a>四、一次”查不到日志”的完整复盘</h2><p>现象：应用半夜崩溃，早上重启后想查崩溃时刻的日志，<code>journalctl -b -1</code> 只返回了启动信息，没有应用输出。</p><p>排查链路：</p><ol><li><code>journalctl --list-boots</code> 确认存在上一次启动记录 → 排除命令用错；</li><li>检查 <code>/run/log/journal</code> vs <code>/var/log/journal</code> → 发现只有内存目录，<strong>持久化没做</strong>；</li><li>补建目录并重启 journald，观察 <code>/var/log/journal</code> 开始落盘；</li><li>后续同类问题都能查到 <code>-b -1</code> 的完整日志。</li></ol><p>总结：日志体系的搭建要在上线前完成，而不是故障后才想起来——持久化、轮转、保留策略这三件事，每台新机器初始化时就要一起落下。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/04/26/%E6%97%A5%E5%BF%97%E6%8E%92%E6%9F%A5%E4%BD%93%E7%B3%BBjournalctl%E4%B8%8E%E7%94%9F%E4%BA%A7%E6%97%A5%E5%BF%97%E8%BD%AE%E8%BD%AC/</id>
    <link href="https://www.lumindream.site/2023/04/26/%E6%97%A5%E5%BF%97%E6%8E%92%E6%9F%A5%E4%BD%93%E7%B3%BBjournalctl%E4%B8%8E%E7%94%9F%E4%BA%A7%E6%97%A5%E5%BF%97%E8%BD%AE%E8%BD%AC/"/>
    <published>2023-04-26T02:00:00.000Z</published>
    <summary>日志是排障的第一现场：journalctl 结构化查询技巧、journald 持久化配置、logrotate 防爆盘方案，以及一次&quot;查不到上次日志&quot;的排查记录。</summary>
    <title>日志排查体系：journalctl 与生产日志轮转</title>
    <updated>2023-04-26T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="Systemd" scheme="https://www.lumindream.site/tags/Systemd/"/>
    <content>
      <![CDATA[<h1 id="Systemd-服务管理实战：从-Unit-编写到日常运维"><a href="#Systemd-服务管理实战：从-Unit-编写到日常运维" class="headerlink" title="Systemd 服务管理实战：从 Unit 编写到日常运维"></a>Systemd 服务管理实战：从 Unit 编写到日常运维</h1><p>把一套应用从”手动 <code>nohup</code> 启动”改成 systemd 托管，是运维规范化里回报最高的一件事——开机自启、崩溃拉起、日志集中、权限隔离一次全解决。这篇把从零手写 <code>.service</code> 到日常运维的完整过程捋一遍。</p><h2 id="一、先理解三个角色"><a href="#一、先理解三个角色" class="headerlink" title="一、先理解三个角色"></a>一、先理解三个角色</h2><ul><li><code>.service</code> 文件 &#x3D; 一份”岗位说明书”：写明怎么启动、怎么停止、什么情况下重启；</li><li><code>systemctl</code> &#x3D; 操作指令：对服务执行 <code>start / stop / enable / status</code>；</li><li><code>systemd</code> &#x3D; 管理进程：负责读懂说明书、监控所有服务。</li></ul><p>现代主流 Linux 全部用 systemd，老掉牙的 SysV init 那套（<code>/etc/inittab</code>、<code>rc.local</code> 塞脚本）只在新装系统时偶尔遇见，不建议再往里写东西。</p><h2 id="二、-service-文件的三段式"><a href="#二、-service-文件的三段式" class="headerlink" title="二、.service 文件的三段式"></a>二、.service 文件的三段式</h2><p>每个 Unit 文件由 <code>[Unit]</code>、<code>[Service]</code>、<code>[Install]</code> 三部分构成，缺一不可。放在 <code>/etc/systemd/system/</code>（管理员自定义，优先级最高）或 <code>/usr/lib/systemd/system/</code>（软件包自带）。</p><h3 id="Unit-：声明依赖"><a href="#Unit-：声明依赖" class="headerlink" title="[Unit]：声明依赖"></a>[Unit]：声明依赖</h3><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[Unit]</span></span><br><span class="line"><span class="attr">Description</span>=支付网关服务</span><br><span class="line"><span class="attr">Documentation</span>=https://wiki.internal/payment</span><br><span class="line"><span class="attr">After</span>=network.target mysql.service      <span class="comment"># 启动顺序：网络和 MySQL 之后</span></span><br><span class="line"><span class="attr">Wants</span>=mysql.service                     <span class="comment"># 弱依赖：mysql 挂了不影响本服务</span></span><br></pre></td></tr></table></figure><p>生产里最常见的坑：Java 应用在 MySQL 还没就绪时就启动了，连接池初始化报错。所以 <code>After</code> 一定要把依赖关系写清楚。</p><h3 id="Service-：定义怎么干活"><a href="#Service-：定义怎么干活" class="headerlink" title="[Service]：定义怎么干活"></a>[Service]：定义怎么干活</h3><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[Service]</span></span><br><span class="line"><span class="attr">Type</span>=simple             <span class="comment"># 默认值：ExecStart 启动的进程就是主进程</span></span><br><span class="line"><span class="attr">ExecStart</span>=/usr/bin/java -jar /app/payment/app.jar</span><br><span class="line"><span class="attr">Restart</span>=<span class="literal">on</span>-failure      <span class="comment"># 异常退出才重启（MySQL 等数据库推荐）</span></span><br><span class="line"><span class="attr">RestartSec</span>=<span class="number">10</span>           <span class="comment"># 重启间隔，防止故障时疯狂重启</span></span><br><span class="line"><span class="attr">TimeoutSec</span>=<span class="number">60</span>           <span class="comment"># 启动/停止超时</span></span><br><span class="line"><span class="attr">User</span>=appuser            <span class="comment"># 绝不用 root 跑对外服务</span></span><br><span class="line"><span class="attr">Group</span>=appgroup</span><br><span class="line"><span class="attr">LimitNOFILE</span>=<span class="number">65535</span>       <span class="comment"># 文件句柄上限，高并发服务必须调</span></span><br><span class="line"><span class="attr">PrivateTmp</span>=<span class="literal">true</span>         <span class="comment"># 独立临时目录，防 /tmp 提权</span></span><br></pre></td></tr></table></figure><p><code>Type</code> 的选择直接决定 systemd 能不能正确跟踪进程：</p><table><thead><tr><th>Type</th><th>适用场景</th></tr></thead><tbody><tr><td>simple</td><td>前台运行的程序（Node.js、Python Web 服务）</td></tr><tr><td>forking</td><td>会分叉后台的传统服务（Nginx、MySQL）</td></tr><tr><td>oneshot</td><td>执行一次就退出的脚本，配合 <code>RemainAfterExit=yes</code></td></tr><tr><td>notify</td><td>支持 sd_notify 的现代程序，就绪后主动通知</td></tr></tbody></table><h3 id="Install-：挂靠开机流程"><a href="#Install-：挂靠开机流程" class="headerlink" title="[Install]：挂靠开机流程"></a>[Install]：挂靠开机流程</h3><figure class="highlight ini"><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="section">[Install]</span></span><br><span class="line"><span class="attr">WantedBy</span>=multi-user.target</span><br></pre></td></tr></table></figure><p><code>systemctl enable</code> 的实质，就是在 <code>/etc/systemd/system/multi-user.target.wants/</code> 下创建指向本文件的符号链接，开机进入多用户模式时自动拉起。</p><h2 id="三、两个真实案例"><a href="#三、两个真实案例" class="headerlink" title="三、两个真实案例"></a>三、两个真实案例</h2><h3 id="案例-1：手工安装的-MySQL-5-7（Type-forking）"><a href="#案例-1：手工安装的-MySQL-5-7（Type-forking）" class="headerlink" title="案例 1：手工安装的 MySQL 5.7（Type&#x3D;forking）"></a>案例 1：手工安装的 MySQL 5.7（Type&#x3D;forking）</h3><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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="section">[Unit]</span></span><br><span class="line"><span class="attr">Description</span>=MySQL <span class="number">5.7</span> Database Server</span><br><span class="line"><span class="attr">After</span>=network.target</span><br><span class="line"></span><br><span class="line"><span class="section">[Service]</span></span><br><span class="line"><span class="attr">Type</span>=forking</span><br><span class="line"><span class="attr">User</span>=mysql</span><br><span class="line"><span class="attr">Group</span>=mysql</span><br><span class="line"><span class="attr">PIDFile</span>=/data/mysql/data/mysqld.pid</span><br><span class="line"><span class="attr">ExecStart</span>=/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf</span><br><span class="line"><span class="attr">ExecStop</span>=/usr/local/mysql/bin/mysqladmin -u root shutdown</span><br><span class="line"><span class="attr">Restart</span>=<span class="literal">on</span>-failure</span><br><span class="line"><span class="attr">RestartSec</span>=<span class="number">10</span></span><br><span class="line"><span class="attr">LimitNOFILE</span>=<span class="number">65535</span></span><br><span class="line"><span class="attr">PrivateTmp</span>=<span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="section">[Install]</span></span><br><span class="line"><span class="attr">WantedBy</span>=multi-user.target</span><br></pre></td></tr></table></figure><p><code>mysqld_safe</code> 会分叉出真正的 mysqld 进程，所以必须 <code>Type=forking</code> 并指定 PIDFile，否则 systemd 会误判服务已退出。</p><h3 id="案例-2：Java-微服务（Type-simple）"><a href="#案例-2：Java-微服务（Type-simple）" class="headerlink" title="案例 2：Java 微服务（Type&#x3D;simple）"></a>案例 2：Java 微服务（Type&#x3D;simple）</h3><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="section">[Unit]</span></span><br><span class="line"><span class="attr">Description</span>=Order Service</span><br><span class="line"><span class="attr">After</span>=network.target mysql.service redis.service</span><br><span class="line"><span class="attr">Wants</span>=mysql.service redis.service</span><br><span class="line"></span><br><span class="line"><span class="section">[Service]</span></span><br><span class="line"><span class="attr">Type</span>=simple</span><br><span class="line"><span class="attr">User</span>=appuser</span><br><span class="line"><span class="attr">Group</span>=appgroup</span><br><span class="line"><span class="attr">WorkingDirectory</span>=/app/order</span><br><span class="line"><span class="attr">ExecStart</span>=/opt/jdk11/bin/java -jar /app/order/order-service.jar --spring.profiles.active=prod</span><br><span class="line"><span class="attr">Restart</span>=always</span><br><span class="line"><span class="attr">RestartSec</span>=<span class="number">15</span></span><br><span class="line"><span class="attr">EnvironmentFile</span>=/etc/sysconfig/order-service</span><br><span class="line"><span class="attr">StandardOutput</span>=journal</span><br><span class="line"><span class="attr">StandardError</span>=journal</span><br><span class="line"><span class="attr">LimitNOFILE</span>=<span class="number">65536</span></span><br><span class="line"></span><br><span class="line"><span class="section">[Install]</span></span><br><span class="line"><span class="attr">WantedBy</span>=multi-user.target</span><br></pre></td></tr></table></figure><p>敏感配置（数据库密码）绝不写在 Unit 的 <code>Environment</code> 里明文，而是用 <code>EnvironmentFile</code> 指向权限 600 的配置文件，或交给密钥管理系统注入。</p><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">systemctl start/stop/restart/status 服务名</span><br><span class="line">systemctl daemon-reload              <span class="comment"># 修改 Unit 后必须重载</span></span><br><span class="line">systemctl <span class="built_in">enable</span> --now 服务名         <span class="comment"># 开机自启 + 立即启动</span></span><br><span class="line">systemctl <span class="built_in">cat</span> 服务名                  <span class="comment"># 查看服务实际生效的配置</span></span><br><span class="line">systemctl list-units --<span class="built_in">type</span>=service --state=failed   <span class="comment"># 列出所有启动失败的服务（排查必用）</span></span><br><span class="line">systemctl is-enabled 服务名           <span class="comment"># 是否开机自启</span></span><br><span class="line">systemd-analyze verify xxx.service   <span class="comment"># 校验 Unit 语法</span></span><br><span class="line">systemd-analyze security xxx.service <span class="comment"># 服务安全加固评分</span></span><br></pre></td></tr></table></figure><h2 id="五、两个排障经验"><a href="#五、两个排障经验" class="headerlink" title="五、两个排障经验"></a>五、两个排障经验</h2><ol><li><strong>改了单位文件不生效</strong>：九成是忘了 <code>systemctl daemon-reload</code>，新文件 systemd 根本不认识。</li><li><strong><code>Restart=always</code> 的服务疯狂重启</strong>：启动即崩的程序会不停刷日志，光看 <code>status</code> 一时半会看不出来，要注意结合 <code>RestartSec</code> 和 <code>StartLimitIntervalSec/StartLimitBurst</code> 限制重启次数，同时去 journal 里看崩溃原因——这就是下一篇日志排查的内容。</li></ol>]]>
    </content>
    <id>https://www.lumindream.site/2023/04/19/systemd%E6%9C%8D%E5%8A%A1%E7%AE%A1%E7%90%86%E5%AE%9E%E6%88%98/</id>
    <link href="https://www.lumindream.site/2023/04/19/systemd%E6%9C%8D%E5%8A%A1%E7%AE%A1%E7%90%86%E5%AE%9E%E6%88%98/"/>
    <published>2023-04-19T02:00:00.000Z</published>
    <summary>手写 .service 文件落地服务的完整过程：Unit/Service/Install 三段式参数详解、Java 应用与 MySQL 的两种真实案例、systemd 常用运维命令与排障思路。</summary>
    <title>Systemd 服务管理实战：从 Unit 编写到日常运维</title>
    <updated>2023-04-19T02:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>LuminDream</name>
    </author>
    <category term="计算机运维" scheme="https://www.lumindream.site/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%BF%90%E7%BB%B4/"/>
    <category term="Linux" scheme="https://www.lumindream.site/tags/Linux/"/>
    <category term="系统初始化" scheme="https://www.lumindream.site/tags/%E7%B3%BB%E7%BB%9F%E5%88%9D%E5%A7%8B%E5%8C%96/"/>
    <content>
      <![CDATA[<h1 id="Linux-发行版选型与系统初始化实践"><a href="#Linux-发行版选型与系统初始化实践" class="headerlink" title="Linux 发行版选型与系统初始化实践"></a>Linux 发行版选型与系统初始化实践</h1><p>新项目立项时，第一个要拍板的技术决策往往不是中间件，而是<strong>服务器操作系统选什么</strong>。这个选择会影响后面两三年里所有服务的部署方式、排障手段和团队的知识积累。分享一下我这边沉淀下来的选型逻辑和初始化流程。</p><h2 id="一、发行版选型：先看业务形态"><a href="#一、发行版选型：先看业务形态" class="headerlink" title="一、发行版选型：先看业务形态"></a>一、发行版选型：先看业务形态</h2><p>Linux 发行版分两大主流派系，国内生产环境基本只在这两系里选：</p><table><thead><tr><th>派系</th><th>代表发行版</th><th>包管理</th><th>典型场景</th></tr></thead><tbody><tr><td>RedHat 系</td><td>RHEL、CentOS、Rocky Linux、AlmaLinux</td><td><code>rpm</code> + <code>yum/dnf</code></td><td>金融、运营商、政企等传统企业，占比最高</td></tr><tr><td>Debian 系</td><td>Debian、Ubuntu Server</td><td><code>deb</code> + <code>apt</code></td><td>互联网公司、云原生&#x2F;K8s 生态</td></tr></tbody></table><p>选型上我的判断标准有两条：</p><ol><li><strong>团队熟悉度优先</strong>。维护成本里最贵的不是软件授权，是团队踩坑经验的积累。上一套系统工程师熟的发行版，比”据说更好”的陌生发行版值钱得多。</li><li><strong>看未来的支持周期</strong>。CentOS 8 提前停服、CentOS 7 也在 2024 年走到尽头后，新项目我会优先 Rocky Linux &#x2F; AlmaLinux（RHEL 的二进制兼容替代），存量机器逐步规划迁移；云上新建的容器化集群则倾向 Ubuntu Server，K8s 生态对 Debian 系的适配更积极。</li></ol><p>实际对比中容易踩的差异点记一下：</p><table><thead><tr><th>对比项</th><th>RedHat 系</th><th>Debian 系</th></tr></thead><tbody><tr><td>装软件</td><td><code>yum install nginx</code></td><td><code>apt install nginx</code></td></tr><tr><td>服务管理</td><td><code>systemctl</code></td><td><code>systemctl</code></td></tr><tr><td>网络配置</td><td><code>/etc/sysconfig/network-scripts/</code></td><td><code>/etc/netplan/</code></td></tr><tr><td>防火墙</td><td><code>firewalld</code></td><td><code>ufw</code></td></tr><tr><td>SELinux</td><td>默认开启（坑多，要主动处理）</td><td>默认 AppArmor</td></tr></tbody></table><p>国产化环境（政企信创）还会遇到 openEuler、银河麒麟、统信 UOS、龙蜥等，基本都是基于上述两系衍生，包管理习惯可以平移，主要是要提前确认依赖软件的兼容性。</p><h2 id="二、装完系统先做这几件事"><a href="#二、装完系统先做这几件事" class="headerlink" title="二、装完系统先做这几件事"></a>二、装完系统先做这几件事</h2><p>新机器到手，我按“四件套”顺序初始化：<strong>主机名 → 时间 → 源 → 加固</strong>。</p><h3 id="1-主机名规范"><a href="#1-主机名规范" class="headerlink" title="1. 主机名规范"></a>1. 主机名规范</h3><p>主机名不是随便起的，要让人一眼看懂这台机器是干什么的。我这边用的规范是 <code>业务-环境-编号</code>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 示例：商品服务生产第 3 台 / MySQL 测试库第 1 台</span></span><br><span class="line">goods-prod-03</span><br><span class="line">mysql-test-01</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看/修改主机名</span></span><br><span class="line">hostname                        <span class="comment"># 查看当前主机名</span></span><br><span class="line">hostnamectl set-hostname mysql-test-01   <span class="comment"># 永久修改（写入 /etc/hostname）</span></span><br></pre></td></tr></table></figure><h3 id="2-时间同步"><a href="#2-时间同步" class="headerlink" title="2. 时间同步"></a>2. 时间同步</h3><p>时间不同步是生产事故的高发元凶——日志对不上、证书校验失败、分布式事务错乱都跟它有关。初始化时直接用 chrony 指向国内 NTP 源：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">timedatectl set-timezone Asia/Shanghai   <span class="comment"># 时区必须设对</span></span><br><span class="line">hwclock -w                               <span class="comment"># 系统时间同步给硬件时间</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 确认时间同步状态</span></span><br><span class="line">timedatectl</span><br></pre></td></tr></table></figure><p>顺手养成记录时间戳的习惯，备份文件的命名里带时间，恢复时才知道用哪份：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">TS=$(<span class="built_in">date</span> +%Y%m%d_%H%M%S)</span><br><span class="line"><span class="built_in">cp</span> /etc/nginx/nginx.conf /backup/nginx.conf_<span class="variable">$&#123;TS&#125;</span></span><br></pre></td></tr></table></figure><h3 id="3-更换软件源"><a href="#3-更换软件源" class="headerlink" title="3. 更换软件源"></a>3. 更换软件源</h3><p>海外官方源在国内拉包又慢又容易超时，装机后第一件事就是把源切到国内镜像。以阿里云为例，RedHat 系：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> /etc/yum.repos.d/bak</span><br><span class="line"><span class="built_in">mv</span> /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/bak/</span><br><span class="line">curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo</span><br><span class="line">yum clean all &amp;&amp; yum makecache</span><br></pre></td></tr></table></figure><p>Debian 系（Ubuntu 22.04 举例）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cp</span> /etc/apt/sources.list /etc/apt/sources.list.bak</span><br><span class="line">sed -i <span class="string">&#x27;s|http://archive.ubuntu.com|http://mirrors.aliyun.com|g&#x27;</span> /etc/apt/sources.list</span><br><span class="line">sed -i <span class="string">&#x27;s|http://security.ubuntu.com|http://mirrors.aliyun.com|g&#x27;</span> /etc/apt/sources.list</span><br><span class="line">apt update</span><br></pre></td></tr></table></figure><h3 id="4-内核-版本确认"><a href="#4-内核-版本确认" class="headerlink" title="4. 内核&#x2F;版本确认"></a>4. 内核&#x2F;版本确认</h3><p>接手存量机器时第一件事永远是确认系统版本，判断后续命令兼容性：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">uname</span> -r                 <span class="comment"># 当前运行内核（看 el7/el8 后缀判断系）</span></span><br><span class="line"><span class="built_in">cat</span> /etc/redhat-release  <span class="comment"># 发行版版本</span></span><br><span class="line">rpm -qa | grep kernel    <span class="comment"># 装了几个内核（升级后清理旧内核用）</span></span><br></pre></td></tr></table></figure><h2 id="三、初始化检查清单（贴机房-贴云主机都适用）"><a href="#三、初始化检查清单（贴机房-贴云主机都适用）" class="headerlink" title="三、初始化检查清单（贴机房&#x2F;贴云主机都适用）"></a>三、初始化检查清单（贴机房&#x2F;贴云主机都适用）</h2><p>这套清单我每次装机都会过一遍，既是操作记录也是交接文档：</p><ul><li><input disabled="" type="checkbox"> 主机名符合 <code>业务-环境-编号</code> 规范</li><li><input disabled="" type="checkbox"> 时区 <code>Asia/Shanghai</code>、时间同步正常（<code>timedatectl</code> 确认）</li><li><input disabled="" type="checkbox"> 软件源已切换国内镜像、<code>makecache</code> 通过</li><li><input disabled="" type="checkbox"> SSH 已加固（密钥登录、禁 root 直登、改端口）——详见网络加固那篇</li><li><input disabled="" type="checkbox"> 防火墙按业务最小放行</li><li><input disabled="" type="checkbox"> 常规目录已按规范预建（<code>/data</code>、<code>/backup</code> 等）</li></ul><h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>发行版选型没有绝对最优，只有“团队能长期维护”和“生命周期内不踩停服坑”这两个硬条件；初始化流程固定成清单后，新机器从到手到可交付基本控制在半小时内，也为后面所有的故障排查打好了基线。</p>]]>
    </content>
    <id>https://www.lumindream.site/2023/04/12/linux%E5%8F%91%E8%A1%8C%E7%89%88%E9%80%89%E5%9E%8B%E4%B8%8E%E7%B3%BB%E7%BB%9F%E5%88%9D%E5%A7%8B%E5%8C%96%E5%AE%9E%E8%B7%B5/</id>
    <link href="https://www.lumindream.site/2023/04/12/linux%E5%8F%91%E8%A1%8C%E7%89%88%E9%80%89%E5%9E%8B%E4%B8%8E%E7%B3%BB%E7%BB%9F%E5%88%9D%E5%A7%8B%E5%8C%96%E5%AE%9E%E8%B7%B5/"/>
    <published>2023-04-12T02:00:00.000Z</published>
    <summary>从发行版选型到装机初始化的一整套落地实践：RedHat/Debian 两系怎么选、内核版本怎么查、主机名/时间/换源怎么做，附生产检查清单。</summary>
    <title>Linux 发行版选型与系统初始化实践</title>
    <updated>2023-04-12T02:00:00.000Z</updated>
  </entry>
</feed>
