Linux 运维这个方向,每年都有人问“现在学还来不来得及”,也每年都有人卡在同一个地方:命令背了一堆,真给一台服务器却不知道从哪下手。这套 2026 年更新的《Linux 运维从入门到精通》体系,本质上解决的就是这个断层问题——它把内容拆成“命令基础、脚本能力、服务部署、自动化运维”四层,前面两层保证你能独立操作机器,后面两层保证你能管住一批机器。这篇文章不复述课程目录,而是把这套体系里真正决定你能不能上手的关键环节拆开讲:怎么搭实验环境、哪些命令必须形成肌肉记忆、Shell 脚本怎么写才不至于变成一次性垃圾、Nginx/MySQL/Docker 这类服务怎么部署才算“上线级”、Ansible 和监控怎么做才不是摆设。
先给结论:Linux 运维的门槛不在智力,而在环境。绝大多数人学不下去,是因为一开始就用了错误的姿势——要么在 Windows 上装个 WSL 点点点,要么买了云服务器却只用来跑 ls。真正有效的路径是:本地虚拟机 + 一台可随意重装的云主机 + 一套固定目录规范,把“敢删敢重装”变成常态。这篇文章会按这个思路,把从零基础到能独立维护中小规模服务的完整链路走一遍,每一步都给出可复制的命令和验证方法。
适合阅读的人群很明确:应届生想进运维岗、后端开发想补齐部署能力、测试/实施想自己能搭环境、以及工作两三年但一直停留在“会敲几个命令”阶段的同学。如果你已经有三年以上 K8s 生产经验,这篇里的基础部分可以直接跳过,看第 8 章之后的自动化与排障思路即可。
1. Linux 运维学习体系的核心能力速览
先把这套体系的能力边界摊开看清楚。运维不是“会 Linux 命令”这么简单,它是一条从单机到集群、从手动到自动的完整链条。下表把这条链条上的关键能力项、对应的技术栈和验证标准列出来,你可以用它给自己做一次体检——哪一格填不上,就从哪一格开始补。
| 能力层级 | 核心技术栈 | 关键技能点 | 验证标准 |
|---|---|---|---|
| 系统基础 | 发行版安装、分区、SSH、用户与权限 | 能独立完成最小化安装并远程登录 | 重装三次不改笔记也能装完 |
| 命令体系 | 文件、文本处理、进程、网络、包管理 | 不用搜索引擎排查 80% 常规问题 | 给定故障现象能列出排查命令 |
| Shell 脚本 | Bash 语法、变量、判断、循环、函数 | 写出可复用、有日志、有返回码的脚本 | 脚本被第二个人接手能看懂 |
| 服务部署 | Nginx、MySQL、Redis、Docker | 完成一个 Web 服务的完整上线 | 能从零部署并通过压测 |
| 自动化 | Ansible、批量执行、配置管理 | 一次操作十台以上机器 | 新增机器 10 分钟内纳入管理 |
| 监控告警 | Prometheus、Node Exporter、Grafana | 能定位“什么时候开始变慢” | 故障前有告警,故障后有曲线 |
| 安全加固 | 防火墙、SELinux、SSH 加固、密钥管理 | 服务器暴露公网不被打穿 | 扫描报告无高危项 |
| 故障排查 | 日志、性能分析、网络抓包 | 从现象推导到根因 | 平均定位时间可控 |
这张表里最容易被低估的是第二层“命令体系”。很多人以为命令就是背参数,实际上运维的命令能力体现在“组合”上——awk 加 sort 加 uniq 能从日志里统计出访问量 Top10 的 IP,ss 加 grep 加 ps 能在三十秒内定位端口被谁占用。这种组合能力没法靠背文档获得,只能靠在真实环境里反复练。
另一个常见误区是把“自动化运维”等同于“学 Ansible”。Ansible 只是工具,自动化的核心是“把重复操作抽象成可重复执行的流程”,这个能力用 Bash 加定时任务同样能练出来。所以这套体系把脚本放在自动化之前,顺序是对的:先能写对一个脚本,再去谈批量。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 适用场景与学习边界
2.1 这套体系能解决什么问题
从实际工作场景看,学完这套内容能覆盖的需求大致有这么几类。第一类是中小企业的服务器维护,几十台机器、几个对外服务、一套监控,这是运维岗最常见的形态,也是这套体系最直接的落点。第二类是开发同学的自我支撑能力,很多时候项目上线卡在“不会配 Nginx 反向代理”“不会看 Java 进程为什么 OOM”,这部分能力补上之后,联调效率会有明显变化。
第三类是环境搭建与交付,比如实施岗需要到客户现场部署一套系统,涉及操作系统初始化、依赖安装、服务注册、开机自启、日志路径规划,这些全是运维基本功。第四类是故障响应,线上出问题时能第一时间判断是应用问题、数据库问题还是系统资源问题,这个判断能力比会修更重要,因为判断错了修得越快错得越远。
2.2 不适合什么场景
需要说清楚边界,避免预期错位。这套体系不教你写业务代码,也不深入内核源码和驱动开发,如果你想走的是 Linux 内核、嵌入式或者存储研发路线,需要另外补 C 语言、内核机制和硬件知识。它也不覆盖大规模容器编排的深度内容,K8s 的 Operator 开发、Service Mesh、多集群联邦这些属于另一个量级的话题,本文只在服务部署章节涉及 Docker 的基础用法。
另外,任何涉及生产环境变更的操作,本文给出的命令都必须在测试环境先验证。运维这个工种的特殊性在于,一条 rm -rf 的代价可能是几天的数据恢复,所以“先在实验环境跑通”不是谨慎,是职业习惯。
2.3 安全与合规边界
运维岗位天然接触服务器权限、用户数据、日志内容,这里必须强调几条底线。第一,所有渗透测试、漏洞扫描、压力测试只能在自己拥有授权的环境里做,未经授权对任何线上系统发起扫描都可能触犯法律。第二,日志和数据库里可能包含个人信息,导出、传输、留存都要遵循所在组织的合规要求,不能随手丢到公网网盘。第三,SSH 密钥、数据库密码、云厂商 AccessKey 这类凭据不允许硬编码在脚本或代码仓库里,应当使用环境变量或密钥管理服务。第四,使用第三方镜像、开源软件包时要确认来源可信,避免引入被篡改的组件。
这几条不是套话。实际工作中因为把 .env 提交到 Git 仓库导致数据库被拖库的案例,每年都有。
3. 实验环境准备与前置条件
3.1 硬件与虚拟化条件
练习 Linux 最省事的方式是虚拟机,对宿主机的要求不高。按经验值给个参考:8GB 内存的笔记本可以同时跑一到两台 2GB 内存的虚拟机,16GB 内存可以跑到三到四台,如果你想练 Ansible 的批量管理,至少需要三台目标机,这时候 16GB 内存是舒适线,32GB 更从容。磁盘方面每台虚拟机给 20GB 到 40GB 动态分配即可,CPU 分配 2 核足够,注意不要在虚拟机里再套虚拟化。
虚拟化软件的选择上,VMware Workstation、VirtualBox、以及 Windows 自带的 Hyper-V 都可以,也可以直接用支持嵌套虚拟化的云主机。宿主机需要在 BIOS 里开启 VT-x 或 AMD-V,否则虚拟机性能会非常差。Windows 用户如果开了 Hyper-V,VMware 的某些版本会与其冲突,需要按官方文档处理兼容性设置。
如果你的机器配置实在吃紧,还有一个折中方案:本地只装一台虚拟机做实验,批量管理部分用云厂商按量付费的轻量服务器临时开三台,练完即销毁。这个方式成本可控,而且更接近真实生产环境。
3.2 发行版选择建议
初学者最容易在发行版上纠结半天,其实没必要。当前时间点下,比较稳妥的选择是 Ubuntu 22.04 LTS 或 Rocky Linux 9,前者社区资料多、软件包新,后者与 RHEL 生态兼容,企业环境更常见。CentOS 7 已经停止维护,不建议作为新环境的选择,但如果你的目标公司还在用,了解一下 yum 和 firewalld 的用法仍然有价值。
我的建议是两个都碰一下,主用其中一 个。原因是面试和工作里你大概率会遇到另一套,包管理命令 apt 和 dnf、防火墙 ufw 和 firewalld、服务目录 /etc/init.d 和 systemd 的差异,早点建立映射关系比临时查文档强。学习阶段不必追求“精通所有发行版”,能把一套用透,迁移成本就很低。
3.3 必装工具清单
宿主机上建议准备这几个工具,后面会反复用到。SSH 客户端用系统自带的终端即可,Windows 可以用 Windows Terminal 配合 OpenSSH。文件传输用 scp 或 sftp,图形化工具可选 WinSCP 或 FileZilla,但建议优先练命令行的方式,因为生产环境不一定能装图形工具。
文本编辑器在服务器上至少要会一个,vim 是必须的,不需要会写插件,但 i、Esc、:wq、dd、/搜索、:%s/old/new/g 这几个要熟练。另外建议本地装一个 VS Code,配合 Remote-SSH 插件直接编辑远程文件,效率比在终端里改高很多。
bash复制# 宿主机生成密钥对,后续所有实验机都用密钥登录
ssh-keygen -t ed25519 -C "lab@local" -f ~/.ssh/lab_key
# 将公钥推送到实验机(首次需要输密码)
ssh-copy-id -i ~/.ssh/lab_key.pub root@192.168.56.101
# 配置免密后验证
ssh -i ~/.ssh/lab_key root@192.168.56.101 "hostname && uname -r"
这里用 ed25519 而不是 rsa,是因为前者密钥更短、性能更好,现代 OpenSSH 都支持。如果你的环境里还有很老的设备,可能需要退回 rsa 并指定 4096 位长度。
4. 系统安装与首次登录配置
4.1 安装过程中的关键选择
虚拟机安装 Linux 有几个选项会直接影响后续体验,值得单独说。分区方案上,学习环境建议用 LVM,方便后续扩容练习;/ 给 15GB 到 20GB,/home 给剩余空间,swap 给内存的 1 到 2 倍或者干脆不给(内存足够时)。如果你要练磁盘扩容,把根分区放在 LVM 上,后面用 lvextend 加 resize2fs 或 xfs_growfs 就能扩展,这个操作在生产环境里非常常见。
软件选择上,一定要选“最小化安装”,不要选带图形界面的版本。图形界面会占用大量内存,而且会让你养成用鼠标操作的习惯,这对学运维是负分。最小化安装之后你会遇到“连 vim 都没有”的情况,这恰恰是好事,逼着你练包管理。
网络配置上,虚拟机建议用 NAT 或者仅主机模式,避免和宿主机网段冲突。如果你要练 Ansible 批量管理,需要保证几台机器在同一个网段内可以互相访问,这时候用仅主机模式的固定 IP 更可控。
4.2 首次登录后必做的八件事
刚装好的系统是“裸”的,直接开始练命令会遇到很多干扰。建议按下面的顺序做一次初始化,这套流程在生产环境新机器上线时同样适用。
bash复制# 1. 确认系统版本与内核
cat /etc/os-release
uname -r
# 2. 更新软件源并升级(Ubuntu)
apt update && apt -y upgrade
# 3. 安装常用工具
apt -y install vim curl wget net-tools lsof tree htop unzip git
# 4. 设置时区为东八区
timedatectl set-timezone Asia/Shanghai
timedatectl status
# 5. 修改主机名,多机实验时务必做
hostnamectl set-hostname node01
echo "192.168.56.101 node01" >> /etc/hosts
# 6. 关闭 swap(如果要练 Kubernetes,这步必须做)
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab
# 7. 配置防火墙规则
ufw allow 22/tcp
ufw enable
# 8. 创建普通用户并授权 sudo
useradd -m -s /bin/bash deploy
usermod -aG sudo deploy
这八步里,第五步的 /etc/hosts 配置是很多人忽略的。多机实验时如果只用 IP 互相访问,后面写 Ansible 清单、配集群会非常痛苦,早点把主机名映射建立起来,能省下大量时间。第七步的防火墙规则要特别注意,ufw enable 之前必须先放行 22 端口,否则你会把自己锁在外面,只能进控制台救援。
第八步创建普通用户是安全习惯。日常操作不要用 root,sudo 会在日志里留下记录,出问题可追溯。生产环境里 root 通常禁止直接 SSH 登录,这个习惯从学习阶段就该养起来。
4.3 SSH 加固配置
实验环境也要做基础加固,因为这本身就是运维工作的一部分。修改 /etc/ssh/sshd_config,至少要调整三个参数:禁止 root 直接登录、禁止密码认证、修改默认端口。
bash复制# 备份配置文件,这是改任何系统配置前的第一反应
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
# 修改关键配置
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
# 检查语法后再重启,避免配置错误导致失联
sshd -t
systemctl restart sshd
systemctl status sshd --no-pager
sshd -t 这个语法检查动作非常重要,配置写错就重启的后果是彻底连不上机器。改完之后不要断开当前会话,另开一个终端验证新连接能通,再关掉旧会话。这个“保留逃生通道”的习惯,在做任何远程变更时都要遵守。
5. 命令体系:从文件操作到故障排查
5.1 文件与文本处理
文件操作命令是最基础的,但真正拉开差距的是文本处理三剑客 grep、sed、awk。日常运维中大量工作是从日志里提取信息,这三个工具的组合能力直接决定排查效率。
bash复制# 统计 Nginx 访问日志中请求量 Top 10 的 IP
awk '{print $1}' /var/log/nginx/access.log \
| sort \
| uniq -c \
| sort -rn \
| head -10
# 提取指定时间段的错误日志
sed -n '/2026-09-01 10:00/,/2026-09-01 11:00/p' /var/log/app/error.log
# 查找大于 100MB 的文件并按大小排序
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -hr | head -20
# 实时监控日志中的异常关键字
tail -f /var/log/app/app.log | grep --line-buffered -E "ERROR|Exception|Timeout"
第一条命令是面试高频题,也是真实工作里最常用的日志分析套路。理解它的关键在于管道:awk 取第一列(客户端 IP),sort 排序后相同 IP 相邻,uniq -c 统计连续重复行数,再按数字倒序排。这个套路可以套用到“统计访问最多的 URL”“统计出现最多的错误码”等各种场景。
第四条命令里的 --line-buffered 容易被忽略。不加这个参数时,grep 会按块缓冲输出,导致你用 tail -f 看不到实时结果,会误以为服务没日志。这个小坑在实际排查中浪费过很多人的时间。
5.2 权限与用户管理
权限体系是 Linux 的核心设计之一,也是新手最容易踩坑的地方。要彻底搞清楚 rwx 对文件和目录的不同含义:对文件来说 r 是读内容、w 是改内容、x 是执行;对目录来说 r 是列目录、w 是在目录内增删文件、x 是进入目录。很多“明明有权限却打不开”的问题,根源是目录缺少 x。
bash复制# 查看文件权限与属主
ls -l /var/www/html/index.html
stat /var/www/html/index.html
# 递归调整属主与权限(Web 目录常见操作)
chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
# 使用 ACL 给单个用户额外权限,不影响其他人
setfacl -m u:deploy:rwx /var/www/html/uploads
getfacl /var/www/html/uploads
第二组命令是 Web 部署的标配。目录给 755、文件给 644,这是经过验证的安全基线。不要图省事用 chmod -R 777,那等于把服务器门敞开——任何能上传文件的漏洞都会直接变成可执行权限。
第三组的 ACL 是很多人不知道的能力。当一个目录需要对特定用户开放写权限,但又不能改属组时,ACL 比反复改属主更合适。setfacl 加 getfacl 的组合在多用户协作环境里很实用。
5.3 进程与资源观察
进程排查是运维日常的核心动作。ps、top、htop 是入门,pidstat、iostat、vmstat 是进阶,strace、perf 是深水区。学习阶段至少要能回答三个问题:某个端口被谁占着、某个进程为什么 CPU 高、系统负载高到底是 CPU 还是 IO 导致的。
bash复制# 查找占用 8080 端口的进程
ss -lntp | grep 8080
lsof -i :8080
# 查看进程树,理解父子关系
ps -ef --forest | head -50
# 按内存占用排序前 10 的进程
ps aux --sort=-%mem | head -11
# 持续观察系统资源,每 2 秒一次共 5 次
vmstat 2 5
iostat -xz 2 5
# 查看某进程的系统调用(需要先安装 strace)
strace -p $(pgrep -f "java.*app.jar") -f -e trace=network
ss 比 netstat 更快,现代系统上都默认带 ss,netstat 需要额外安装 net-tools。两者的参数习惯接近,-l 监听、-n 数字显示、-t TCP、-p 显示进程,组合起来就是最常用的排查命令。
vmstat 输出里有个关键指标 r 和 b:r 是运行队列长度,长期大于 CPU 核数说明 CPU 不够;b 是阻塞进程数,大于 0 说明有进程在等 IO。另一个关键指标是 si 和 so,如果这两个值持续不为 0,说明内存不足已经开始用 swap,性能会断崖式下降。这些判断逻辑比记住命令本身更重要。
5.4 网络排查
网络问题的排查顺序建议固定下来:先看本机服务是否监听、再看本机防火墙、再看能否本机访问、然后看同网段其他机器能否访问、最后才怀疑网络链路和上游设备。这个由内到外的顺序能避免大量无效排查。
bash复制# 1. 确认服务监听状态
ss -lntp
# 2. 本机访问测试
curl -I http://127.0.0.1:8080/health
# 3. 检查防火墙规则
ufw status verbose
# 4. 从其他机器测试连通性
telnet 192.168.56.101 8080
# 或
nc -zv 192.168.56.101 8080
# 5. 链路追踪
traceroute -T -p 8080 192.168.56.101
# 6. 抓包分析(需要 root)
tcpdump -i any -nn port 8080 -w /tmp/8080.pcap
第六步的抓包是最后手段,但在排查“TCP 三次握手是否完成”“有没有 RST 包”“请求发出去了但没响应”这类问题时非常有效。抓完用 Wireshark 打开 .pcap 文件就能看到完整交互过程。注意抓包文件可能包含敏感数据,用完及时删除。
5.5 包管理与服务管理
包管理这块,apt 和 dnf 的常用操作建议做成对照记忆。服务管理现在基本统一到 systemd,systemctl 的用法在主流发行版上是一致的,这块投入产出比很高。
bash复制# Debian/Ubuntu 系
apt update
apt -y install nginx
apt list --installed | grep nginx
apt -y remove nginx
# RHEL/Rocky 系
dnf makecache
dnf -y install nginx
dnf list installed | grep nginx
dnf -y remove nginx
# systemd 通用操作
systemctl start nginx
systemctl enable nginx
systemctl status nginx --no-pager
systemctl restart nginx
systemctl reload nginx
journalctl -u nginx -n 100 --no-pager
journalctl -u nginx --since "2026-09-01 10:00" --until "2026-09-01 11:00"
这里要区分 restart 和 reload。reload 是平滑重载配置,不中断现有连接,改 Nginx 配置、改防火墙规则这类操作优先用它;restart 是停掉再启动,会短暂中断服务。生产环境变更时选错了,可能直接造成一个短时故障。
journalctl 的 --since 和 --until 参数在定位“几点几分出的问题”时特别有用,比翻日志文件快得多。配合 -f 可以实时跟踪,配合 -p err 只看错误级别,这几个用法值得形成习惯。
6. Shell 脚本与自动化入门
6.1 一个能用的脚本长什么样
Shell 脚本最容易出现的问题是“能跑一次,但别人接手就废”。判断一个脚本是否合格,看三点:有没有参数校验、有没有日志、有没有正确的退出码。下面这个备份脚本模板把这三件事都做了,可以直接改成自己的需求。
bash复制#!/usr/bin/env bash
set -euo pipefail
# ============ 配置区 ============
SRC_DIR="/data/app"
BACKUP_DIR="/data/backup"
RETENTION_DAYS=7
LOG_FILE="/var/log/backup.log"
# ============ 函数 ============
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "${LOG_FILE}"
}
cleanup() {
log "清理 ${RETENTION_DAYS} 天前的备份"
find "${BACKUP_DIR}" -name "app_*.tar.gz" -mtime +"${RETENTION_DAYS}" -delete
}
main() {
if [[ ! -d "${SRC_DIR}" ]]; then
log "ERROR: 源目录 ${SRC_DIR} 不存在"
exit 1
fi
mkdir -p "${BACKUP_DIR}"
local stamp
stamp=$(date '+%Y%m%d_%H%M%S')
local target="${BACKUP_DIR}/app_${stamp}.tar.gz"
log "开始备份 ${SRC_DIR} -> ${target}"
tar -czf "${target}" -C "$(dirname "${SRC_DIR}")" "$(basename "${SRC_DIR}")"
if [[ -s "${target}" ]]; then
log "备份成功,大小 $(du -h "${target}" | cut -f1)"
else
log "ERROR: 备份文件为空"
exit 2
fi
cleanup
}
main "$@"
这段脚本里有几个细节值得说明。set -euo pipefail 三件套的作用是:-e 命令失败即退出、-u 使用未定义变量报错、pipefail 管道中任一环节失败都算失败。这三个选项能让脚本在异常时立刻暴露问题,而不是带着错误继续跑下去。
log 函数用 tee -a 同时输出到屏幕和文件,调试时能看到实时输出,事后能查历史记录。main "$@" 的写法把所有逻辑收在函数里,方便后续扩展子命令。local 声明局部变量避免污染全局,这些细节在脚本变长之后价值会非常明显。
6.2 定时任务与日志轮转
脚本写完之后要靠定时任务跑起来。crontab 是最经典的方式,但有几个坑必须提前知道:环境变量和交互式 Shell 不同、工作目录默认是用户家目录、输出不重定向会堆积邮件或者丢失。
bash复制# 编辑当前用户的定时任务
crontab -e
# 每天凌晨 2 点执行备份,输出重定向到日志
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.cron.log 2>&1
# 每 5 分钟检查一次服务状态
*/5 * * * * /opt/scripts/check_service.sh >/dev/null 2>&1
# 查看当前用户的定时任务
crontab -l
# 查看 cron 执行日志
grep CRON /var/log/syslog | tail -20
第一个坑是执行环境。crontab 里的 PATH 通常只有 /usr/bin:/bin,脚本里调用的自定义命令很可能找不到。解决办法是在 crontab 顶部显式声明 PATH,或者在脚本里用绝对路径。第二个坑是时间格式,五个字段依次是分、时、日、月、周,*/5 表示每 5 个单位,这个记混了会导致任务在奇怪的时间点执行。
日志文件会一直增长,需要配置轮转。Ubuntu 系用 logrotate,配置文件放在 /etc/logrotate.d/ 下。
bash复制# /etc/logrotate.d/app-backup
/var/log/backup.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 root adm
}
rotate 14 表示保留 14 份,compress 开启压缩,delaycompress 让最近一份不压缩方便查看。配置完可以用 logrotate -d /etc/logrotate.d/app-backup 做 dry-run 查看执行计划,避免配置错误导致日志被误删。
6.3 脚本能力的进阶方向
Bash 能做的事情有上限,当你发现脚本里开始出现复杂的 JSON 解析、大量的字符串处理、或者需要并发执行时,就该考虑换工具了。Python 在运维场景里是很好的补充,subprocess 调命令、requests 调接口、paramiko 做 SSH,配合标准库足够应付大部分需求。Go 适合写需要分发的单文件工具,编译后没有运行时依赖,扔到任何机器上都能跑。
不建议一上来就上 Python 或 Go,Bash 的价值在于它是系统的“母语”,任何环境都有,不需要装运行时。用 Bash 能解决的问题就不要引入新语言,这是运维的实用主义。
7. 服务部署实战:Web 与数据库
7.1 Nginx 部署与反向代理配置
Nginx 是运维必练的服务,因为它同时涉及安装、配置、服务管理、日志、性能调优多个知识点。下面这套配置覆盖了反向代理、静态资源、日志格式、压缩,是一个中小型 Web 服务的最小可用配置。
nginx复制# /etc/nginx/conf.d/app.conf
upstream app_backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
keepalive 32;
}
server {
listen 80;
server_name app.example.com;
access_log /var/log/nginx/app_access.log main;
error_log /var/log/nginx/app_error.log warn;
client_max_body_size 20m;
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1024;
location /static/ {
alias /var/www/app/static/;
expires 7d;
add_header Cache-Control "public";
}
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
}
}
几个配置点值得解释。keepalive 32 让 Nginx 与后端保持长连接,能显著减少高并发下的 TIME_WAIT 数量。proxy_set_header X-Real-IP 和 X-Forwarded-For 是把真实客户端 IP 传给后端,否则后端日志里全是 Nginx 的 IP,排查问题时没法定位来源。client_max_body_size 默认只有 1MB,上传文件超过这个值会直接返回 413,这是新手最常遇到的坑之一。
配置写完后必须先做语法检查再重载,这个流程要形成肌肉记忆。
bash复制nginx -t
systemctl reload nginx
curl -I http://127.0.0.1/health
tail -f /var/log/nginx/app_error.log
7.2 数据库容器化部署
学习阶段用 Docker 跑 MySQL 和 Redis 是最省事的方式,避免了在宿主机上装一堆依赖、卸载不干净的问题。生产环境是否容器化要看团队情况,但作为练习手段,Docker 能让你在几分钟内拉起一套完整环境。
yaml复制# docker-compose.yml
services:
mysql:
image: mysql:8.0
container_name: lab-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: appdb
TZ: Asia/Shanghai
ports:
- "127.0.0.1:3306:3306"
volumes:
- ./data/mysql:/var/lib/mysql
- ./conf/mysql:/etc/mysql/conf.d
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: lab-redis
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"]
ports:
- "127.0.0.1:6379:6379"
volumes:
- ./data/redis:/data
bash复制# .env 文件,不要提交到 Git
MYSQL_ROOT_PASSWORD=ChangeMe_Local_Only
REDIS_PASSWORD=ChangeMe_Local_Only
# 启动与验证
docker compose up -d
docker compose ps
docker compose logs -f mysql
docker exec -it lab-mysql mysql -uroot -p -e "SHOW DATABASES;"
端口映射写 127.0.0.1:3306:3306 而不是 3306:3306,是为了只监听本机,避免数据库直接暴露到网络上。这个习惯非常重要,公网上被扫描爆破的 MySQL 大多数就是因为端口直接开放在 0.0.0.0。密码通过 .env 注入而不是写死在 compose 文件里,配合 .gitignore 排除,能避免凭据泄露。
healthcheck 配合 depends_on 可以控制启动顺序,但要注意 depends_on 默认只等容器启动,不等服务就绪,需要加条件才能等健康检查通过。这个细节在编排多服务时经常出问题。
7.3 部署后的验收清单
服务起来了不等于部署完成。每次部署后建议按固定清单验收,这套清单同样适用于生产变更。
| 验收项 | 检查命令 | 通过标准 |
|---|---|---|
| 进程存活 | systemctl status nginx |
active (running) |
| 端口监听 | ss -lntp | grep 80 |
有监听记录 |
| 本机访问 | curl -I 127.0.0.1 |
返回 200/301 |
| 外网访问 | 从另一台机器 curl |
能通 |
| 日志正常 | tail -100 error.log |
无持续报错 |
| 开机自启 | systemctl is-enabled nginx |
enabled |
| 资源占用 | ps aux | grep nginx |
内存无异常增长 |
| 配置备份 | 确认备份文件存在 | 有带日期的备份 |
第八项经常被跳过。改配置前不备份,出问题想回滚时只能凭记忆重写,这个教训几乎每个人都吃过。养成 cp config config.bak.$(date +%F_%H%M) 的习惯,成本极低。
8. 自动化运维与批量管理
8.1 Ansible 入门与清单管理
当机器数量超过三台,手工操作就开始出错了。Ansible 的优势是无 agent、走 SSH、用 YAML 描述任务,学习成本相对低。练手阶段建议先用三台虚拟机,把清单、模块、剧本、变量这四块跑通。
ini复制# inventory/hosts.ini
[web]
node01 ansible_host=192.168.56.101
node02 ansible_host=192.168.56.102
[db]
node03 ansible_host=192.168.56.103
[all:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/lab_key
ansible_python_interpreter=/usr/bin/python3
bash复制# 连通性测试,这是每次改完清单后的第一步
ansible all -i inventory/hosts.ini -m ping
# 批量执行命令
ansible web -i inventory/hosts.ini -m shell -a "uptime && df -h /"
# 批量安装软件包
ansible web -i inventory/hosts.ini -m apt -a "name=nginx state=present" --become
清单写完后必须先跑 ping 模块,确认 SSH 通了、Python 解释器路径正确,再执行实际操作。Ansible 报错信息有时候比较绕,问题往往出在 SSH 认证或者 Python 路径上,先排除这两项能省很多时间。
8.2 用 Playbook 固化流程
单条命令适合临时操作,可复用的东西要写成 Playbook。下面这个剧本完成了“装 Nginx、下发配置、启动服务、配置防火墙”的完整流程,可以直接改成自己的部署剧本。
yaml复制# playbooks/nginx.yml
- name: 部署 Nginx 服务
hosts: web
become: true
vars:
nginx_port: 80
tasks:
- name: 安装 Nginx
apt:
name: nginx
state: present
update_cache: true
- name: 下发站点配置
template:
src: templates/app.conf.j2
dest: /etc/nginx/conf.d/app.conf
owner: root
group: root
mode: "0644"
notify: reload nginx
- name: 放行 HTTP 端口
ufw:
rule: allow
port: "{{ nginx_port }}"
proto: tcp
- name: 确保服务启动并开机自启
systemd:
name: nginx
state: started
enabled: true
handlers:
- name: reload nginx
systemd:
name: nginx
state: reloaded
notify 配合 handlers 是 Ansible 的核心设计之一:只有配置文件真的发生变化时才触发重载,配置没变就不动服务。这个机制避免了每次执行都重启服务,在批量场景下价值很大。
执行时先用 --check 做演练,看看会改哪些东西,确认无误再实际执行。
bash复制ansible-playbook -i inventory/hosts.ini playbooks/nginx.yml --check
ansible-playbook -i inventory/hosts.ini playbooks/nginx.yml
8.3 监控与告警的最小方案
没有监控的运维是盲人摸象。学习阶段搭一套 Prometheus 加 Node Exporter 加 Grafana 就够用了,重点不是把大盘做得漂亮,而是理解“指标采集—存储—查询—告警”这条链路。
yaml复制# prometheus.yml 片段
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/rules/*.yml
scrape_configs:
- job_name: "node"
static_configs:
- targets:
- "192.168.56.101:9100"
- "192.168.56.102:9100"
- "192.168.56.103:9100"
yaml复制# /etc/prometheus/rules/node-alert.yml
groups:
- name: node-basic
rules:
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "实例 {{ $labels.instance }} 不可达"
- alert: HighCPU
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} CPU 使用率超过 85%"
- alert: DiskWillFull
expr: (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes) * 100 < 15
for: 10m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 磁盘剩余空间不足 15%"
告警规则里 for 参数很重要,它表示“持续满足条件多久才触发”。没有 for 的告警会被瞬时抖动频繁触发,很快就没人看了。for: 5m 意味着持续 5 分钟高负载才告警,能过滤掉大部分毛刺。
9. 资源观察与性能排查思路
9.1 建立观察习惯
性能问题的难点不在命令,而在判断。同样一条 top 输出,有经验的人能看出是 CPU 打满、内存泄漏还是 IO 等待。建议按“四象限”来组织观察:CPU、内存、磁盘、网络,每个象限先看总量再看单项,先看趋势再看瞬时值。
bash复制# 一屏看全系统状态
top -b -n 1 | head -20
# CPU 按核使用情况
mpstat -P ALL 2 3
# 内存详情,注意 available 而不是 free
free -h
cat /proc/meminfo | grep -E "MemTotal|MemAvailable|SwapUsed"
# 磁盘 IO 与空间
iostat -xz 2 3
df -h
df -i
# 网络流量
sar -n DEV 2 3
free -h 输出里 free 和 available 是两个概念。free 是完全没被使用的内存,available 是估算的可用内存(包含可回收的缓存)。看 free 很小就以为内存不够是常见误判,Linux 会用空闲内存做文件缓存,这部分随时可以回收。真正要警惕的是 available 很小、swap 大量使用。
df -i 检查 inode 使用率,这个指标容易被忽略但会导致很诡异的问题:磁盘还有空间,但创建不了新文件。小文件特别多的场景(比如大量日志、缓存、邮件队列)很容易把 inode 耗尽。
9.2 从现象到根因的推导路径
给一套固定思路:服务变慢时,先确认是全局问题还是单实例问题,uptime 看负载、top 看谁在吃资源;然后判断资源类型,CPU 高就看是用户态还是内核态,内存高就看是应用分配还是缓存,IO 高就看是读还是写;最后落到具体进程,pidstat -p <pid> 1 看线程级消耗,strace 看系统调用,jstack 或 py-spy 看应用栈。
这个顺序的价值在于它避免了“一上来就怀疑代码”的惯性。很多时候应用变慢的根因是磁盘写满、网卡打满、或者被同机的其他进程抢了资源,这些用系统命令几分钟就能排除,比翻代码快得多。
10. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| SSH 连接被拒绝 | 服务未启动、端口变更、防火墙拦截 | systemctl status sshd、ss -lntp、ufw status |
启动服务,放行端口,检查 sshd 配置 |
| 修改配置后服务起不来 | 配置语法错误 | nginx -t、sshd -t、visudo -c |
恢复备份配置,逐行比对 |
| 磁盘空间满但找不到大文件 | 已删除文件仍被进程占用 | lsof | grep deleted |
重启占用进程或清空对应句柄 |
| 磁盘有空间但无法写入 | inode 耗尽 | df -i |
清理小文件,调整 inode 策略 |
| 内存充足但进程被 OOM 杀 | 容器或 cgroup 限制 | dmesg -T | grep -i oom |
调整内存限制或排查内存泄漏 |
| 端口被占用 | 残留进程或未正常退出 | ss -lntp | grep <port> |
确认后 kill 或换端口 |
| 定时任务不执行 | PATH 缺失、权限不足、语法错误 | grep CRON /var/log/syslog |
用绝对路径,检查脚本执行权限 |
| 服务能本机访问但外部不通 | 防火墙、安全组、监听地址 | ss -lntp 看监听 IP,检查云安全组 |
改为监听 0.0.0.0 或放行规则 |
| 时间不对导致证书/日志异常 | 时区或 NTP 未配置 | timedatectl、chronyc sources |
设置时区并同步时间源 |
| Ansible 执行失败 | SSH 认证、Python 路径、sudo 权限 | ansible -m ping、加 -vvv |
配置密钥、指定解释器、配置免密 sudo |
| 数据库连接数打满 | 连接未释放或配置过小 | SHOW PROCESSLIST、看 max_connections |
修连接池配置,合理调整上限 |
| 系统负载高但 CPU 空闲 | IO 等待或不可中断进程 | vmstat 看 b 列、iostat -x 看 %util |
定位慢盘或异常进程,排查存储 |
这张表里的第三行值得单独讲。Linux 中删除一个被进程打开的文件,df 显示空间已释放但实际没有,因为文件句柄还活着。这个问题在日志场景里很常见:你 rm 了一个巨大的日志文件,磁盘空间却没回来。正确做法是让进程重新打开文件(重启服务或者 systemctl reload),或者用 > file.log 的方式清空而不是删除。
第四行的 inode 问题也经常让人困惑。df -h 显示还有几十 G,但写文件报 “No space left on device”。这时候 df -i 一看 inode 用到 100%。解决办法是找到小文件多的目录批量清理,长期方案是调整文件系统参数或者做小文件合并。
11. 最佳实践与进阶路线
11.1 值得从第一天就坚持的习惯
第一,所有操作前先备份配置。cp file file.bak.$(date +%F_%H%M) 这个动作花不了两秒,但能救命。第二,改配置先做语法检查,nginx -t、sshd -t、visudo -c、docker compose config 这些都是免费的保险。第三,远程操作保留逃生通道,改 SSH 配置时不要断当前会话,改防火墙时先放行新规则再启用。
第四,目录结构固定下来。建议统一成 /opt/scripts 放脚本、/data/app 放应用、/data/backup 放备份、/var/log/app 放日志。这套约定在换机器、交接、写文档时能省大量沟通成本。第五,所有脚本必须带日志和退出码,不要让“跑失败了但没有任何输出”这种情况发生。
第六,密码和密钥不进代码仓库。用 .env 配合 .gitignore,或者用配置中心、密钥管理服务。这个习惯越早建立越好,等到出事故再改就晚了。
11.2 从会用到会管的进阶路径
基础命令和脚本熟练之后,下一步建议按这个顺序走:先补监控和日志体系,因为这是“看见问题”的能力;再补自动化配置管理,这是“批量解决问题”的能力;然后补容器与编排,这是“标准化交付”的能力;最后补云原生与可观测性,这是“规模化运维”的能力。
每一层都不要只学工具。学 Prometheus 不只是学怎么装,而是理解指标类型、采样、聚合、告警抑制这些概念;学 Ansible 不只是学模块,而是理解幂等性、声明式配置、配置漂移这些思想。工具会换,思想不会。
11.3 学习路径的具体安排建议
如果按每周投入 10 到 15 小时来算,一个比较现实的节奏是:前两周专注系统安装、命令体系、权限管理,目标是能独立装好一台机器并配置好基础环境;第三到四周练 Shell 脚本和定时任务,目标是写出两个能实际用起来的脚本(比如日志清理和配置备份);第五到六周做服务部署,完整走一遍 Nginx 加后端应用加上数据库的上线流程;第七到八周上自动化和监控,把三台机器纳入统一管理。
这个节奏的关键是每一阶段都要有“产出物”,而不是“看完了”。产出物可以是脚本、可以是部署文档、可以是一份排障记录。运维这个岗位看重的是“你能不能把事情做成”,而不是“你学了多少”。
最后提一句容易被忽略的点:文档能力。把每次部署步骤、每个坑的解决方法、每套环境的配置差异记下来,形成自己的知识库。这件事短期内看不到收益,但一年之后回头看,它会是你最值钱的资产。
练习环境记得定期做快照,尤其是准备做危险操作之前。虚拟机快照是最便宜的后悔药,比任何恢复手段都直接。
