// 安全研究 · 2026-09-19

Linux 运维经验手册:从系统初始化到规模化管理的实战指南

适用读者:Linux运维工程师、SRE、DevOps从业者、IT基础设施管理者 核心原则:先标准化,后自动化;先保稳定,再求效率;先建体系,再谈工具。


第一章 系统初始化:一切从“锁死”开始

1.1 为什么必须锁定系统版本与内核

在生产环境中,最忌讳的一句话是“这台机器好像和别的机器不太一样”。当100台服务器中混入了不同的发行版、不同的内核小版本,故障排查的复杂度会呈指数级上升。内核参数在不同版本间的行为差异、驱动兼容性问题、甚至系统调用返回值的变化,都可能让你在深夜排障时欲哭无泪。

锁定系统版本和内核的核心目的只有一个:消除环境变量,让所有机器的行为可预期。

1.2 主流发行版内核锁定实操

RHEL/CentOS/Rocky Linux

以RHEL 8/9系为例,使用dnf versionlock插件锁定内核相关包。对于RHEL 8:

dnf versionlock add kernel kernel-core kernel-modules kernel-tools kernel-tools-libs kernel-headers kernel-devel

对于RHEL 9,包名略有不同,需要额外包含kernel-modules-core和kernel-uki-vir:

dnf versionlock add kernel kernel-core kernel-modules-core kernel-modules kernel-uki-vir kernel-tools kernel-tools-libs kernel-headers kernel-devel

执行完成后,通过dnf versionlock list验证锁定状态。如果看到kernel-1:6.1.155-176.282.*这样的条目,说明锁定已生效。

Ubuntu/Debian

使用apt-mark进行包锁定。首先确认当前运行的内核:

uname -r
# 输出示例:6.8.0-57-generic

删除多余内核后锁定目标版本:

sudo apt-mark hold linux-image-6.8.0-57-generic

验证:apt-mark showhold会列出所有被标记为hold的包。

国产化系统适配

在信创环境下,银河麒麟(Kylin Server)V10/V11、统信UOS Server V20等系统的初始化脚本已有开源实现。这些脚本覆盖了网卡命名修改(如改为传统eth0命名)、IP地址配置、SWAP禁用等关键操作,可直接用于标准化部署。

1.3 系统初始化的“第一道工序”清单

新机器到手后,在安装任何业务软件之前,应完成以下标准化操作:

1. 主机名规范化

采用“地区-环境-业务-角色-序号”的命名规则,例如bj-prod-shop-nginx-01。使用hostnamectl set-hostname批量执行。统一的命名规则不仅便于识别,更是自动化工具分组管理的基础。

2. 时间同步

配置Chrony而非NTP,指向内网NTP Server。百台机器同时访问公网时间源可能被防火墙拦截或触发限流,导致同步失败。Chrony在虚拟化和不稳定的网络环境下表现更优。

3. 文件描述符限制

在/etc/security/limits.conf中添加:

* soft nofile 65535
* hard nofile 65535

防止业务跑起来后报“Too many open files”。注意:此配置需要重新登录才能生效。

4. 基础工具包安装

vim、lrzsz、wget、curl、net-tools、sysstat(提供iostat、mpstat、sar)、tcpdump、telnet、nc。排障时没有这些工具,等于上战场没带枪。

5. 软件源替换

替换为内网Repo或国内镜像源(阿里云、清华源)。速度就是生命线,尤其是在批量部署时。

6. 防火墙与SELinux策略确认

根据企业安全规范确认防火墙规则。对于Oracle JD Edwards等企业级应用,官方文档明确建议禁用SELinux并配置特定端口开放。但这一决策必须由安全团队审批,不可擅自执行。

第二章 运维体系与流程:从“人治”到“法治”

2.1 运维体系的四大支柱

根据国家标准GB/T28827.1的要求,运维体系应包含运维职责、运维内容、运维流程、运维评估与提升四个核心模块。这不是官僚主义的形式要求,而是运维从“个人英雄主义”走向“组织能力”的必由之路。

运维体系建设应包括计划、执行、检查和优化四个循环过程。没有体系的运维团队,故障处理靠运气,知识沉淀靠离职交接。

2.2 运维流程的标准化

例行巡检是运维的“日常功课”。应根据运维对象的不同属性,制定详细的巡检计划,执行后提交巡检报告,对发现的问题提交维修申请。

运维受理应有统一入口。通过热线电话、电子邮件、网络平台等接收请求,明确服务内容,形成运维任务并传达至实施层。

服务台机制是用户与运维部门之间的单一联系点。所有服务请求必须通过服务台,实现请求的集中受理、优先级划分和进展跟踪。当服务台无法在SLA内解决时,转交二线或三线支持。

2.3 运维值班与交接

运维值班管理要求包括:建立值班管理制度、指定值班负责人(应有主备岗,且主备岗不应同时离岗)、制定值班安排表、严格执行交接班流程并留存记录、保持值班电话畅通。

关键原则:值班期间不得擅离岗位。这听起来是常识,但在实际操作中,很多团队因为人手紧张而对此打折扣,最终付出代价。

2.4 运维文档与知识沉淀

维护资料应专人保管、专柜集中存放、定期整理。设备变更后相关资料要及时更新,实现资料记录与实物相符。

重大故障记录应长期保存。这些记录是团队最宝贵的知识资产。建议建立“故障复盘库”,将每次故障的排查过程、根因分析、解决方案固化为可检索的文档。

2.5 运维评估与持续改进

应每季度组织开展内部检查并形成检查报告,每年审计工作中应包含运维管理审计项目。检查范围包括:制度和流程的合理性与完整性、执行情况、文档与配置的有效性、整体安全状况、运维人员履职能力等。

持续改进的机制:根据检查结果采取纠正性和预防性措施,形成“发现问题-分析原因-制定措施-跟踪验证”的闭环。

第三章 自动化运维:从“手艺人”到“工厂厂长”

3.1 为什么是 Ansible

管理10台机器时,你可以用Xshell的“发送键输入到所有会话”功能。管理100台时,继续这么做就是在玩火——网络抖动、某台机器卡顿,都会导致命令执行错乱。

Ansible的核心优势在于无Agent架构:只要SSH通,它就能干活。相比之下,SaltStack需要在每台机器上维护Minion进程,100台机器就是100个Agent的生命周期管理负担。对于中小规模到中等规模的Linux集群,Ansible是性价比最高的选择。

3.2 Ansible 核心概念

Inventory(主机清单) :定义要管理哪些机器及分组。支持INI和YAML格式。

Playbook(剧本) :以YAML格式定义的“任务排序清单”,描述系统应达到的状态。

Module(模块) :Ansible推送至目标节点执行的小程序,如yum、service、copy、file。

Role(角色) :预定义的目录结构,将变量、任务、模板、文件按约定组织,实现复用。

3.3 第一个可用的 Playbook

---
- name: 初始化 Web 节点
  hosts: web
  become: yes
  tasks:
    - name: 安装 Nginx
      ansible.builtin.package:
        name: nginx
        state: present

    - name: 确保 Nginx 运行并开机自启
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: yes

这个示例体现了Ansible的核心哲学:声明式。你不需要告诉Ansible“如果没安装就yum install”,你只需要说“nginx应该是present状态”。

3.4 性能优化要点

当被管理节点达到100台量级,默认配置会成为瓶颈。在ansible.cfg中:

[defaults]
forks = 50
host_key_checking = False
pipelining = True

[ssh_connection]
control_master = auto
control_persist = 60s

forks默认5,调至50可显著提升批量执行速度。control_persist复用SSH连接,避免每次任务重新握手。同时确保/etc/ssh/sshd_config中UseDNS no,否则每次SSH连接都会尝试反向DNS解析。

3.5 自动化运维的“灵魂八问”

自动化运维不是“会写Playbook”就够了。赵班长的《运维知识体系》提出了值得每个自动化实践者思考的问题:

  1. 自动化的边界在哪里?(什么该自动化,什么不该)
  2. 如何保证自动化操作的安全性?(误操作如何防止)
  3. 自动化工具本身的高可用如何保障?
  4. 如何处理“部分成功、部分失败”的中间状态?
  5. 自动化操作的可审计性如何实现?
  6. 如何管理自动化工具自身的版本和配置?
  7. 自动化与人工干预的切换机制是什么?
  8. 如何量化自动化的收益?

这些问题没有标准答案,但思考过这些问题的团队,自动化实践会走得更稳。

第四章 监控体系:看见才能掌控

4.1 带内监控的致命盲区

某金融机构数据中心曾发生过一次典型故障:核心系统交易超时,但监控平台显示所有指标“正常”。Agent持续上报CPU、内存数据,直到业务层告警才被动发现问题。事后复盘发现:操作系统已经崩溃,但Agent也随之停止工作。监控平台看到的是“最后一次上报正常”,然后长时间没有新数据,却不会自动判定设备故障。更迷惑的是,网卡和IP协议栈可能仍在工作,Ping测试畅通,监控平台据此判断“设备在线”。

这个案例揭示了带内监控的本质局限:Agent依赖操作系统,而操作系统恰恰是故障对象本身。

4.2 带外监控:给服务器装一个“永不掉线”的眼睛

带外监控通过BMC(基板管理控制器)独立运行,不依赖操作系统。核心能力包括:

  • 独立存活检测:即使操作系统崩溃,BMC仍可上报“硬件在线但OS无响应”
  • 远程控制台(SOL) :通过串行重定向查看服务器控制台输出,判断是内核崩溃还是启动卡住
  • 远程电源操作:通过IPMI执行硬重启

对于核心业务服务器,带外监控不是“锦上添花”,而是“雪中送炭”。

4.3 指标基线:知道“正常”长什么样

调优和排障的前提是建立性能基线。没有基线,你无法判断当前状态是否异常。SRE需要关注的四大资源维度:

维度 关键指标 健康阈值参考
CPU %user, %sys, %iowait, 负载值 长期>70%需关注,>90%告警
内存 可用内存、Swap使用率、缺页中断 Swap使用率>0需警惕
磁盘IO await(平均服务时间), %util await>10ms可能成为瓶颈
网络 重传率、丢包率、连接数 重传率>1%表示网络不稳定

黄金法则:用百分位数(P50/P95/P99)衡量延迟,而非平均值。接口响应时间P99>200ms即可视为SLI违约。

4.4 可观测性的三层架构

现代运维的可观测性已从单一监控演进为监控告警、日志采集、链路追踪三位一体:

  • 指标(Metrics) :Prometheus + Grafana,关注趋势和阈值
  • 日志(Logs) :ELK或Loki,关注细节和事件
  • 链路(Traces) :Jaeger或SkyWalking,关注请求的端到端流转

三者的关联关系比单个数据源更有价值。当一个请求变慢时,通过Trace ID串联指标和日志,能快速定位是哪个服务、哪个SQL、哪个中间件调用出了问题。

4.5 日常巡检命令速查

系统资源层:

# CPU与负载
top -bn1 | head -20
uptime

# 内存
free -h

# 磁盘空间
df -h

# 磁盘IO
iostat -x 1 3

# 网络连接
ss -s
ss -tlnp

服务与日志层:

# 服务状态
systemctl status nginx mysql redis

# 实时日志
tail -f /var/log/messages
journalctl -u nginx --since "10 min ago"

# 筛选错误
grep -iE "error|warn|exception" /var/log/app.log | tail -50

第五章 故障排查实战手册

5.1 排查的“第一刀”:是个例还是全体

网站出问题时,最没用的动作就是重启服务器。重启完好了,原因没人知道,下次照挂。排查有章法,按层往里走,五分钟能定位的事,靠瞎猜能折腾一整晚。

第一步永远是判断影响范围:

  • 个例(只有一个人打不开):问题多半在用户侧。清DNS缓存、换手机流量、检查hosts文件,服务器不用动。
  • 全体(所有人都打不开):问题在服务器侧。从安全组、Nginx、程序、数据库一层层往里查,别跳步。

判断方法:手机关掉WiFi用流量试;让另一个城市的朋友帮忙打开;用在线拨测工具从多个节点访问。

5.2 状态码的方向性判断

页面报错时,先看状态码第一位是4还是5:

  • 4开头:请求本身的问题,服务器好端端的,它在告诉你“你搞错了”。但例外:404经常是Nginx路径规则没写对或程序没部署,先自己curl一遍。
  • 5开头:服务器这边的麻烦。

5.3 慢请求的“时间拆解”

“网站有点卡”比“网站挂了”更难查。挂了是明确的,卡是说不清的。把一次请求的时间拆开看:

浏览器按F12打开开发者工具,网络面板,点击任意请求看“时序”栏,DNS解析、建立连接、等待响应、下载内容各多少毫秒,全列好了。

服务器侧的耗时要靠程序日志或慢查询日志。某次慢请求总耗时3.2秒,数据库查询占2.4秒。这时候去优化Nginx配置、加带宽,钱花了,一点用没有——瓶颈在SQL上。

5.4 从浏览器到数据库的排查链

# 1. 域名解析到哪了,服务器有没有回应
curl -I https://你的域名

# 2. 端口通不通
nc -zv 你的公网IP 443

# 3. 本地服务是否监听
ss -tlnp | grep 443

# 4. Nginx 错误日志
tail -f /var/log/nginx/error.log

# 5. 应用日志
journalctl -u your-app --since "5 min ago"

# 6. 数据库慢查询
tail -f /var/log/mysql/slow.log

5.5 磁盘空间不足的应急与根治

现象:服务无法写入日志,数据库报错“No space left on device”。

应急步骤:

df -h                          # 确认哪个分区满了
du -sh /* 2>/dev/null | sort -rh | head -10    # 定位大目录
find / -type f -size +1G 2>/dev/null -exec ls -lh {} \;   # 定位大文件

常见元凶:

  • 日志文件:配置logrotate是根治方案
  • 已删除但未释放的文件:lsof | grep deleted,重启对应进程释放空间
  • Docker日志:/var/lib/docker/containers/下的*-json.log可能巨大。在/etc/docker/daemon.json中配置log-opts限制大小

5.6 内存泄漏的识别与应对

识别信号:可用内存持续下降无回升、Swap使用率上升、dmesg | grep -i "oom\|kill"出现OOM日志。

定位泄漏源:

ps aux --sort=-%mem | head -10          # 按内存排序
pidstat -r -p <pid> 1 10                 # 监控特定进程内存增长趋势
jmap -histo:live <pid>                   # Java 对象统计

5.7 网络问题的分层排查

Layer 1-2:链路与IP

ip link show           # 网卡状态
ip addr show           # IP 配置
ping <gateway>         # 网关可达性

Layer 3-4:路由与端口

traceroute <target>    # 路由路径
telnet <host> <port>   # TCP 端口连通性
ss -tlnp | grep <port> # 本地监听状态

Layer 7:应用层

curl -v http://<host>:<port>/health
tcpdump -i eth0 port <port> -w /tmp/capture.pcap

5.8 交换机层面的典型故障

广播风暴是内网运维的头号杀手。现象:无征兆全网断网,交换机端口指示灯疯狂同步闪烁,重启短暂恢复但一两天内复发。

排查步骤:逐台断开接入交换机上联口定位故障网段 → show spanning-tree查看是否存在二层环路 → 端口镜像抓包定位攻击源MAC → 配置风暴控制和BPDU防护。

MAC地址表溢出:早上网络流畅,下午越来越卡。虚拟机、Docker、监控摄像头生成的虚拟MAC会快速占满表项。解决方案:show mac address-table count查看占用,网络分段(监控、IoT单独VLAN),更换大容量交换机。

IP地址冲突:电脑时而能上网时而断网,重启单台没用。arp -a查看同一IP是否对应多个MAC,display arp定位冲突设备。

5.9 硬件故障的“最小化测试法”

当无法定位具体故障时,通过能开机的最小化配置逐步添加部件来判断故障范围:只保留单颗CPU、单根内存、一个PSU,用短接开关针脚方式开机,再依次替换部件排查。

CPU故障排查要点:查看BMC log定位CPU位置 → 检查接触和散热器 → 单CPU测试或交叉更换 → 最小化测试排除其他部件。

第六章 性能调优:向内核要性能

6.1 内核参数调优的安全边界

网络栈优化(/etc/sysctl.conf) :

net.ipv4.tcp_tw_reuse = 1          # TIME_WAIT 端口复用(仅客户端场景)
net.ipv4.tcp_fin_timeout = 30      # FIN_WAIT2 超时缩短
net.ipv4.tcp_max_syn_backlog = 8192
net.core.somaxconn = 65535         # listen 队列大小
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3

注意:net.ipv4.tcp_tw_recycle在NAT环境下会导致连接异常,已在较新内核中废弃,不建议开启。

数据库场景专项优化:

vm.swappiness = 1                  # 减少 Swap 倾向
vm.dirty_ratio = 60                # 脏页比例
vm.dirty_background_ratio = 10
vm.overcommit_memory = 2           # 内存过量分配策略

数据库专用服务器建议关闭透明大页(THP) ,THP的动态内存合并会导致不可预测的延迟尖刺。

6.2 从真实故障看“资源释放”的重要性

某消息服务上线后CPU周期性飙升至94%。排查发现:代码调用第三方SDK发送邮件时,每次创建client连接后未执行close操作。未关闭的连接导致内存泄漏,GC无法回收,内存逐渐打满触发频繁Full GC,而Full GC是Stop-The-World的,直接抢占CPU资源。

教训:第三方SDK的链接管理必须显式关闭;重启能缓解的问题往往不是问题的终结;上线新服务时保留切换开关。

第七章 数据备份与容灾

7.1 备份策略的“三个指标”

RPO(恢复点目标) :数据最新副本有多新,取决于副本制作频率。RTO(恢复时间目标) :恢复数据需要多长时间。

核心系统的RPO可能要求15分钟以内,意味着数据库需要增量备份每15分钟一次。重要系统可能RPO为1天,每日全量备份即可。

7.2 备份的“组合拳”

快照 + 备份 + 复制的组合策略最为可靠:

  • 快照:按计划创建的卷的时间点版本,RPO可短至1小时,恢复特定文件极快
  • 备份:独立的时间点副本,用于长期保留和灾难恢复,RPO从1天起
  • 复制:跨区域创建卷的最新数据副本,用于灾难恢复场景

建议:为每个卷保留至少两份每日备份。

7.3 恢复演练:备份不验证等于没有备份

恢复演练必须定期进行。以云环境为例:

  • 云服务器:选择备份副本创建镜像 → 使用镜像申请新服务器 → 对比数据一致性
  • 数据库:选择备份恢复到新实例 → 验证数据匹配
  • 文件系统:选择备份创建新文件系统 → 对比业务数据

核心原则:备份策略决定了“能恢复到什么程度”,恢复演练决定了“实际能恢复到什么程度”。两者缺一不可。

7.4 业务分级与备份策略

根据业务系统重要性分级制定备份策略:

  • 核心系统:支撑核心业务流程,中断造成重大影响。RPO最低,备份频率最高
  • 重要系统:支撑重要业务流程,中断造成严重影响。中等RPO
  • 一般系统:辅助性系统,中断影响可控。标准RPO

第八章 规模化管理的“偷懒”哲学

8.1 资产与标准化:100台机器的第一课

管理100台服务器的核心,不是“比管理10台更努力”,而是把非标准化的烂摊子变成流水线作业。

主机名规范是标准化的第一步。统一采用“地区-环境-业务-角色-序号”格式。批量修改:

while read ip hostname; do
    ssh $ip "hostnamectl set-hostname $hostname"
done < hostname_list.txt

配置管理基线:所有机器必须运行相同的OS版本、内核版本、基础工具集。差异是故障的温床。

8.2 从“人肉运维”到“GitOps”

将Ansible Inventory、Playbook、Role以及关键配置文件纳入Git仓库管理。

核心流程:本地修改 → 提交PR → 团队Review → 合并到main → CI/CD触发Ansible执行 → 结果归档。

这不仅是“自动化”,更是可审计、可回滚、可协作的运维方式。

8.3 运维知识体系的“主干与枝叶”

运维知识体系可以按HTTP请求流程从外到内组织:客户端层 → 外部层(CDN) → 网络层 → 接入层(负载均衡) → 应用服务层 → 存储层 → 基础服务层 → 容器层 → 操作系统层 → 基础设施层。

这个结构的价值在于:当故障发生时,你知道该按什么顺序查。客户端的问题不要上服务器查,网络层的问题不要翻应用日志。

8.4 运维技能树的“五层进阶”

从“会命令”到“能扛体系”的成长路径:

  • 第一层·系统基础:文件权限、进程管理、磁盘、日志。标志是能沿着进程、日志、资源三条线索独立定位
  • 第二层·服务与网络:Nginx、MySQL、Redis部署调优,IP规划、路由、防火墙
  • 第三层·自动化:Shell脚本 → Ansible,从“一台机器”到“一批机器”的思维转变
  • 第四层·容器与云原生:Docker、Kubernetes、云平台资源管理
  • 第五层·可观测性:监控告警、日志采集、链路追踪三位一体

两根枝干:文档与沉淀习惯(故障复盘、操作固化);软技能(沟通、压力管理)。

第九章 运维安全基线

9.1 SSH加固要点

# /etc/ssh/sshd_config
PermitRootLogin prohibit-password    # 禁止 root 密码登录
PasswordAuthentication no           # 禁用密码认证
PubkeyAuthentication yes            # 启用密钥认证
X11Forwarding no                    # 关闭 X11 转发
MaxAuthTries 3                      # 限制认证尝试次数
ClientAliveInterval 300             # 客户端存活检测
ClientAliveCountMax 2

修改后通过sshd -t测试语法,确认无误后重启服务。

9.2 最小权限原则

  • 数据库专用用户:严禁使用root运行数据库进程
  • 运维账号分离:日常操作使用普通账号,通过sudo提权
  • 文件权限:数据目录chmod 700,配置文件chmod 600,日志目录chmod 640

9.3 操作审计

日常操作应制定操作手册,业务系统的操作规程应至少包括操作的对象、时间、步骤、指令、操作要点、复核要点、操作人、复核人等基本要素。特殊操作、临时操作应经批准后方可双岗执行,操作过程记录留痕,保存时间不少于1年。

第十章 硬件与数据中心运维

10.1 服务器故障排查的“三板斧”

最小化测试法:当无法定位具体故障时,通过能开机的最小化配置逐步添加部件。只保留单颗CPU、单根内存、一个PSU,短接开关针脚开机,再依次替换。

替换法:当大概知道故障范围时,通过1-3个部件逐步替换来查找具体故障。先替换容易出故障的部件(硬盘、内存)。

交叉比较法:将疑似故障部件与正常运行部件交叉安装测试。如果故障现象随之转移,则该部件故障;如果现象不变,则非此部件问题。

10.2 数据中心网络故障的物理层排查

光模块/光纤故障:查看端口物理状态,检查收发光功率(典型值-1dBm ~ -9dBm),清洁光纤接头,查看CRC错误统计。

网线故障:查看协商速率(千兆口协商为百兆说明线缆有问题),用测线仪测试八芯通断,检查设备接地。

10.3 硬件更换的规范流程

以华为服务器为例,更换主板或整机的关键步骤包括:

  1. 从iBMC获取故障主机上的虚拟机名称和ID
  2. 对故障主机下电
  3. 拆卸线缆前做好标记
  4. 复用原有硬盘、插卡时保持槽位一致
  5. 新主机iBMC IP地址应与原主机相同
  6. 确认RAID卡配置,必要时导入RAID
  7. 上电后在iBMC查看主机状态
  8. 在FusionSphere OpenStack中确认主机状态正常

附录:常用命令速查

场景 命令
查看内核版本 uname -r
锁定内核(RHEL) dnf versionlock add kernel kernel-core ...
锁定内核(Ubuntu) apt-mark hold linux-image-<version>
查看进程CPU排名 ps aux --sort=-%cpu | head
查看磁盘IO iostat -x 1
查看网络连接 ss -tlnp
实时日志 tail -f /var/log/messages
查看被删除但未释放的文件 lsof | grep deleted
带外远程重启 ipmitool -I lanplus -H <bmc_ip> -U <user> -P <pass> power reset
Ansible 连通性测试 ansible -i inventory.ini all -m ping
批量执行命令 ansible -i inventory.ini web -m command -a "uptime"
查看交换机MAC表 show mac address-table count
查看生成树状态 show spanning-tree

结语:运维的核心不是“修机器”,而是“设计一个不需要频繁修的系统”。从锁定第一个内核版本开始,到建立监控基线、编写Ansible Playbook、沉淀故障排查话术、建立备份恢复演练机制,每一步都是在把“不确定性”转化为“确定性”。当系统足够标准化、自动化足够可靠、流程足够清晰时,“偷懒”就不再是奢望,而是运维工程师最优雅的工作方式。

原文 https://blog.csdn.net/2301_79518550/article/details/166015251