Linux 运维这个词听起来很大,落到日常其实就是三件事:把机器管住、把服务跑稳、把重复工作交给脚本。很多人第一次接触 Linux 运维,是拿到一台云主机或者虚拟机,照着教程敲了几条命令,cd、ls、vim 都会了,然后卡住——不知道该练什么,也不知道学到哪一步算能用。这篇内容按一条从零基础到实战的完整体系来拆:先在虚拟机上把环境跑起来,再把命令按任务分组练熟,然后写能交给别人执行的 Shell 脚本,接着把服务从“手动起一个进程”变成“systemd 托管 + 反向代理 + 日志可查”,最后用定时任务和批量执行把重复劳动压下去。
适合两类人看:一是完全没碰过 Linux、想系统补一遍基础的;二是用过一点命令、但服务部署和排查总是靠搜的人。最关键的一点先说在前面——命令不是背出来的,是围绕具体任务练出来的,脱离场景背手册,两周就忘干净。
下面按实际学习顺序拆,每一段都给出可执行的步骤和判断标准,不用等到“学完”才动手。
1. 先把学习路线定下来,别一上来就背命令
1.1 零基础学 Linux 运维最容易走偏的三个方向
第一个坑是把命令当单词背。ls 有二三十个参数,全背下来没有意义,因为真实场景里高频出现的就那么几个组合:ls -lh 看大小、ls -lt 按时间排、ls -la 看隐藏文件。真正需要记牢的是“什么现象该用哪个命令去看”,而不是参数表。
第二个坑是跳过网络和权限,直接上手服务部署。nginx 起不来的时候,大多数时间不是花在配置文件上,而是花在端口有没有被占用、防火墙放没放行、SELinux 或 AppArmor 拦没拦、监听地址绑的是 127.0.0.1 还是 0.0.0.0。这些问题全部属于网络和权限范畴,前面不补,后面每一步都在还债。
第三个坑是一直在图形界面上练。桌面版 Linux 当然能学,但生产环境里你只有一条 SSH 连接,改配置靠 vim,看日志靠 less 和 journalctl,传文件靠 scp 或 rsync。早点切到纯命令行,后面会省很多适应成本。
1.2 一条能验收的分阶段路线
学习路线最好带验收标准,否则很容易陷入“看了很多、说不出会什么”的状态。我一般按下面六个阶段推,每个阶段都对应一个能独立完成的小目标。
| 阶段 | 主要练什么 | 验收标准 |
|---|---|---|
| 一、环境与基础操作 | 装系统、SSH 登录、目录结构、软件包管理 | 能独立装好一台机器并用普通用户 + sudo 登录 |
| 二、命令与排错 | 文件权限、进程资源、网络端口、日志定位 | 给定一个“服务不通”的场景,能按顺序定位到原因 |
| 三、Shell 脚本 | 变量、判断、循环、函数、参数、日志 | 能写出带参数校验和日志输出的运维脚本 |
| 四、服务部署 | Web 服务、systemd 托管、反向代理、日志轮转 | 能把一个服务部署成开机自启、外部可访问 |
| 五、自动化 | 定时任务、批量执行、配置管理工具 | 能把每天手动做的事变成一条命令或一个任务 |
| 六、稳定性与基线 | 备份、监控、用户权限收敛、变更记录 | 能说清一台机器上的账号、端口、定时任务都是干什么的 |
顺序不能随便调。阶段二没打牢,阶段四的部署就是在赌运气;阶段三没写过脚本,阶段五的自动化就变成抄别人的 Playbook,出问题完全看不懂。
这里有个判断标准值得记住:如果你不能在断网的情况下,凭记忆把一台机器的网络、时间、软件源配好,就说明阶段一还没过。 这不是要求背命令,而是要求你知道该改哪个文件、改完怎么验证。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境先搭好,后面一半的坑会自动消失
2.1 虚拟机、云主机、容器,三条路各练什么
练 Linux 运维不一定非要买服务器,但这三种环境练的东西不一样,选错了会走弯路。
| 方式 | 成本 | 适合阶段 | 优势 | 局限 |
|---|---|---|---|---|
| 本地虚拟机 | 免费,占本机内存 | 一、二、三阶段 | 可以随便折腾,能打快照回滚 | 网络是 NAT 或桥接,和真实机房有差异 |
| 云主机 | 有费用,按量可控 | 四、五阶段 | 有公网 IP、安全组、快照,接近真实场景 | 误操作可能产生费用,要留意计费项 |
| 容器 | 免费,启动快 | 三、四阶段验证 | 起停快,适合反复试配置 | 没有完整的 init 系统,systemd 相关练习受限 |
我建议的组合是:本地虚拟机打基础,云主机跑部署。容器可以留到后面做快速验证,因为它天然不适合练 systemd、开机自启、内核参数这些内容。
虚拟机配置不用太高,但有两个参数别省:内存至少给到 2G,否则装完系统再跑个数据库或 Java 服务会很卡;磁盘至少 20G,日志、软件包缓存、镜像很快就吃掉空间。CPU 核心数影响不大,单核也能练。
2.2 系统装完先做六项确认
很多人装完系统就直接开始敲命令,结果后面各种奇怪问题。系统装好之后,先花二十分钟把这六件事确认一遍,能省下后面几小时。
第一,网络和 DNS。 先看网卡有没有拿到地址,再看能不能解析域名。顺序是:ip addr 看本地地址,ip route 看默认网关,cat /etc/resolv.conf 看 DNS,最后 ping 一个域名验证。很多人直接 ping 域名,不通就开始改配置,其实可能只是网卡没起来。
bash复制ip addr
ip route
cat /etc/resolv.conf
ping -c 3 example.com
第二,时间同步。 时间不准会连累日志排序、证书校验、定时任务,甚至让集群节点之间认证失败。确认系统时间服务的状态,看它是不是 active,再看当前时间偏差。
bash复制timedatectl
第三,软件源。 这一步最容易忽略。默认源可能在你的网络环境下速度很慢,装个软件等半天。先更新一次索引,确认能正常拉取,再决定要不要换源。判断标准很简单:apt update 或 dnf makecache 能不能在合理时间内完成,有没有报错。
第四,SSH 与密钥登录。 密码登录在练习环境里够用,但你要顺手把密钥登录配一遍,因为后面做批量执行、自动化部署都绕不开它。配完先别关密码登录,等确认密钥能登进去再关,否则很容易把自己锁在外面。
第五,普通用户加 sudo。 一直用 root 操作是坏习惯,练的时候就要养成普通用户登录、需要时提权的习惯。这样做还有个好处:能提前暴露权限问题,而不是等到部署时才发现服务用户没有写目录的权限。
第六,打快照。 虚拟机或云主机都支持快照。在做任何“改网络配置”“改 SSH 配置”“动防火墙”的操作之前,先打一个快照。这个动作看着笨,但它是你敢于试错的底气。
注意:改网络和 SSH 配置前一定先打快照,并且保留一个已登录的会话不要断开,用新开窗口去验证。这样即使配置写错,原会话还能改回来。
3. 命令按任务分组练,比按字母顺序背有效十倍
3.1 文件、权限、属主:先搞清 rwx 到底管谁
权限这块,新手最容易混淆的是“r、w、x 对目录和对文件含义不一样”。对文件来说,r 是读内容,w 是改内容,x 是能执行;对目录来说,r 是能列出里面有什么,w 是能在里面增删文件,x 是能进入这个目录并访问里面已知路径的文件。
这解释了一个常见现象:某个目录权限是 rw-r--r--,你能看到目录名,但进不去,因为缺 x。反过来,只有 x 没有 r 的目录,你进得去、能访问已知文件,但 ls 列不出内容。
练习时按这个顺序走:
bash复制# 1. 看权限和属主
ls -l /opt
# 2. 改权限(数字法和符号法都练一遍)
chmod 750 /opt/demo
chmod u+x,g-w /opt/demo/run.sh
# 3. 改属主和属组
chown deploy:deploy /opt/demo
chown -R deploy:deploy /opt/demo/data
# 4. 特殊权限位,知道有这回事
chmod g+s /opt/demo/share
chmod +t /tmp
chmod 777 是很多人解决问题的第一反应,但在真实环境里这是给自己埋雷。正确的思路是:先确认服务以哪个用户运行,再给那个用户刚刚够的权限。如果服务跑不起来,先看日志里的报错是“权限不够”还是“文件不存在”,这两个原因的处理方式完全不同。
3.2 进程与资源:卡了、慢了先看哪三个视角
服务出问题,第一步不是重启,是看状态。三个视角按顺序看:进程在不在、资源够不够、日志说了什么。
bash复制ps -ef | grep -v grep | grep nginx
top -bn1 | head -20
df -h
free -m
ps 看进程是否存在、启动参数对不对、运行用户是谁。top 看 CPU 和内存谁在吃,重点看 load average 和 %wa(IO 等待)。df 和 free 看磁盘和内存余量。
这里有个经验判断:CPU 高不一定有问题,IO 等待高基本都有问题。 如果 %wa 长期偏高,多半是磁盘读写在排队,这时候去看 iostat 或 vmstat,比盯着 CPU 有用。
还有一个常被忽略的点:进程状态里的 Z(僵尸)和 D(不可中断睡眠)。D 状态的进程用 kill -9 是杀不掉的,因为它卡在内核的 IO 上,这时候要做的是查磁盘和挂载,不是反复 kill。
3.3 网络与端口:连通性排查有固定顺序
网络排查最忌讳乱试。固定一个由近到远的顺序,会快很多:
- 服务自己有没有在监听:
ss -lntp - 本机能不能连上:
curl -v http://127.0.0.1:端口/ - 本机网卡地址能不能连上:
curl -v http://本机内网IP:端口/ - 外部能不能连上:从另一台机器测,或用
telnet、nc - 域名解析对不对:
dig或nslookup
bash复制ss -lntp
curl -sv http://127.0.0.1:8080/health
每一步失败对应的原因范围都在收窄。如果第 1 步就没有监听,后面全都不用测,问题在服务本身或者启动参数;如果第 1 步有监听但绑的是 127.0.0.1,第 4 步必然失败,这是很多“服务起来了但外网访问不了”的真实原因。
还有两个常被误判的点:防火墙和云平台安全组是两层,本地防火墙放行了不代表安全组放行,反之亦然;端口通不代表应用正常,nc -z 只能说明 TCP 握手成功,HTTP 层返回 502 还是会连上。
3.4 文本处理与日志:把 grep、awk、sed、journalctl 用成一套
日志分析是运维日常里占比很高的一块。最基础的是 grep 加时间过滤,进阶一点是 awk 做统计。
bash复制# 找出最近 200 行里的错误
tail -n 200 /var/log/app/app.log | grep -i error
# 统计每个 IP 的访问次数,取前 10
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# 用 journalctl 看某个服务的日志
journalctl -u demo.service --since "1 hour ago" -n 100 --no-pager
journalctl 值得单独练,因为 systemd 托管的服务日志都归它管。-u 指定服务,--since 限定时间,-f 实时跟踪,-p err 只看错误级别。这三个参数组合起来,比翻文件快得多。
sed 主要用于批量替换,练的时候一定要加备份后缀或者先 -n 预览:
bash复制sed -n '1,5p' /etc/nginx/nginx.conf
sed -i.bak 's/8080/9090/g' /opt/demo/config.ini
加 .bak 这个习惯看着小,但救过很多人。改配置文件之前先备份,出问题能一条命令回滚。
4. Shell 脚本写到“能交给别人跑”才算过
4.1 从一条能用的命令到一个能重复跑的脚本
很多人写脚本的起点是“这条命令我每天都要敲一遍”。这没错,但从“命令”到“脚本”中间有几件事必须补上,否则脚本只能自己用,别人一跑就出事。
第一步是加解释器和严格模式:
bash复制#!/usr/bin/env bash
set -euo pipefail
set -e 让命令失败时脚本退出,-u 让使用未定义变量时报错,-o pipefail 让管道中任意一段失败都能被捕获。这三行不是形式主义,它们能把“脚本跑完了但结果是错的”这种情况变成“脚本明确报错退出”,后者好排查得多。
第二步是把硬编码的路径提出来变成变量,第三步是加一个 main 函数把逻辑收拢,第四步是加日志。改造完之后的结构大致是这样:
bash复制#!/usr/bin/env bash
set -euo pipefail
LOG_FILE="${LOG_FILE:-/tmp/cleanup.log}"
TARGET_DIR="${1:-/tmp/demo}"
log() {
echo "[$(date '+%F %T')] $*" | tee -a "$LOG_FILE"
}
main() {
if [[ ! -d "$TARGET_DIR" ]]; then
log "目录不存在,退出:$TARGET_DIR"
exit 2
fi
find "$TARGET_DIR" -type f -name '*.log' -mtime +7 -print -delete >> "$LOG_FILE" 2>&1
log "清理完成:$TARGET_DIR"
}
main "$@"
这段脚本里,参数有默认值、目录不存在会明确退出、删了哪些文件有记录。判断一个脚本能不能交给别人跑,看三点:别人不知道背景也能看懂参数含义、失败时有明确退出码、执行过程有日志可查。
4.2 参数、日志、退出码、幂等,这四件事决定脚本能不能上生产
参数这块,建议统一用“位置参数加默认值”的方式,不要搞太复杂。如果参数超过三个,就改用 getopts 或者干脆改成配置文件。
日志的关键是带时间戳并且统一格式。logger 命令可以把日志写进系统日志,适合脚本被定时任务调用时追踪。
退出码要区分开:0 成功,1 一般错误,2 参数或前置条件错误。定时任务里这个区别很有用,能快速判断是脚本逻辑问题还是环境问题。
幂等是这四个里最容易被忽略的。所谓幂等,就是同一个脚本连续跑两次,结果应该一样。判断方法很简单:把脚本连跑两遍,看第二次有没有报“文件已存在”“目录已存在”这类错误。常见的处理方式是加判断:
bash复制[[ -d "$TARGET_DIR" ]] || mkdir -p "$TARGET_DIR"
而不是直接 mkdir "$TARGET_DIR"。
注意:脚本里删除类操作一定要先加
-delete。find ... -delete如果路径变量为空或者匹配过宽,后果很难收拾。
5. 服务部署:从“手动起进程”到“能被外部访问”
5.1 先手动跑通,再谈托管
部署服务有个原则:先在命令行里手动跑通,再交给 systemd。 因为手动跑的时候,报错直接打在终端上,一眼能看到;一旦变成后台服务,报错就散落在日志里,排查成本高很多。
以最常见的 Web 服务为例,手动验证的步骤是:
bash复制# 1. 确认端口没被占用
ss -lntp | grep 8080
# 2. 前台启动,观察输出
cd /opt/demo && python3 -m http.server 8080
# 3. 另开一个窗口验证
curl -sv http://127.0.0.1:8080/
第三步一定要做,而且要分两个地址测:127.0.0.1 和本机内网 IP。前者通后者不通,说明服务只监听了本地回环,改监听地址即可,不用去查防火墙。
手动跑通之后,把启动命令、工作目录、运行用户、环境变量这几项记下来,它们就是下一步写 systemd 配置的原材料。
5.2 systemd 托管:开机自启、崩溃重启、日志归口
systemd 的价值不只是“后台运行”,它解决的是三件事:开机自启、进程崩溃后自动拉起、日志统一进 journald。
ini复制[Unit]
Description=Demo Web Service
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/opt/demo
ExecStart=/usr/bin/python3 -m http.server 8080
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
几个参数值得解释一下。User 决定服务以谁的身份运行,这个用户必须对工作目录有读权限,否则会一直重启。ExecStart 里必须用绝对路径,systemd 不读你的 shell 环境变量。Restart=on-failure 表示非正常退出才重启,如果配置成 always,一个启动就报错的服务会无限重启,反而把日志刷爆。
写完配置之后的固定动作是:
bash复制systemctl daemon-reload
systemctl start demo.service
systemctl status demo.service
systemctl enable demo.service
journalctl -u demo.service -n 50 --no-pager
顺序不能反。很多人跳过 daemon-reload 直接 restart,结果改了配置没生效,白白排查半天。
5.3 Nginx 反向代理与配置分层
服务跑在 8080 上,对外通常是 80 或 443,中间用 Nginx 做反向代理。这样做的好处是:证书、静态文件、访问日志、限流这些通用能力集中在一层处理,后面的应用服务只管业务。
nginx复制server {
listen 80;
server_name _;
access_log /var/log/nginx/demo.access.log;
error_log /var/log/nginx/demo.error.log;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
改完配置先做语法检查再 reload,这个习惯要养成:
bash复制nginx -t
systemctl reload nginx
nginx -t 失败的时候,错误信息会指明行号,照着改就行。别在语法不过的情况下去 restart,容易把正在跑的服务停掉。
配置分层的意思是:主配置只管全局项,站点配置放到 conf.d 或 sites-enabled 目录下,一个站点一个文件。这样加站点不用改主配置,删站点直接删文件,回滚也简单。
6. 自动化运维:先干掉重复劳动,再谈平台化
6.1 crontab 和批量执行,先把重复的事交出去
自动化的起点不是上工具,而是把“每天手动做一次”的事写成一个任务。定时任务是最低成本的方式:
bash复制# 每天凌晨 3:10 执行清理脚本,输出重定向到独立日志
10 3 * * * /opt/scripts/cleanup.sh /data/logs >> /var/log/cleanup.cron.log 2>&1
写 crontab 有几个坑必须知道。第一,cron 的环境变量和你登录时不一样,PATH 更短,所以脚本里要用绝对路径。第二,输出一定要重定向,否则 cron 会尝试发邮件,某些环境下会堆积。第三,% 在 crontab 里有特殊含义,命令里如果有日期格式化,需要转义。第四,*/5 是每 5 分钟,5 * * * * 是每小时的第 5 分钟,这两个写混了很常见。
批量执行在机器少的时候用循环就够了:
bash复制for host in 10.0.0.11 10.0.0.12 10.0.0.13; do
echo "===== $host ====="
ssh -o ConnectTimeout=5 "deploy@$host" 'systemctl is-active demo.service' || echo "连接或检查失败:$host"
done
关键在 ConnectTimeout 和失败处理。不加超时,一台机器网络不通,整个循环就卡住;不加 || echo,中间一台失败之后你分不清哪些跑过了。批量操作的稳定性,比速度重要得多。
6.2 配置管理与流水线的最小可用组合
机器超过五六台之后,手工循环就开始出问题:配置漂移、执行结果不一致、没人知道哪台机器被改过。这时候才需要引入配置管理工具。
判断要不要上的标准很实际:看同一份配置,你是不是在三个以上地方手改过;看同一次发布,你是不是超过两次因为漏改机器而回滚。 如果答案都是肯定的,就该上工具了。
最小可用的组合通常是这几块:
- 一份可版本管理的配置仓库,所有变更走提交,不走手改
- 一个批量执行入口,负责把配置推到目标机器
- 一个执行结果记录,谁在什么时候改了什么,出问题能追溯
- 一个回滚方案,改坏了能在几分钟内恢复
这四块里,最容易被跳过的是回滚方案。很多人把力气全花在“怎么推下去”,没想过“推错了怎么办”。真实情况是,配置管理的价值一半在推送效率,一半在出错时能不能快速止血。
还有一点要提醒:自动化工具不会让错误的操作变正确,只会让错误操作执行得更快、影响面更大。所以在把一条命令交给批量执行之前,先在一台机器上手动跑一遍,确认结果符合预期。
7. 出问题时按层级排查,比记命令更重要
7.1 五层排查法:从现象到根因的固定顺序
排查最怕的是“想到哪查到哪”。建议固定成五层,从外到内逐层收窄:
| 层级 | 看什么 | 常用手段 | 典型结论 |
|---|---|---|---|
| 现象层 | 报什么错、什么时候开始、影响范围 | 用户反馈、监控告警、访问日志 | 是全部失败还是部分失败 |
| 服务层 | 进程在不在、端口监听没有、服务状态 | systemctl status、ss -lntp、ps |
服务没起来或反复重启 |
| 配置层 | 配置语法、监听地址、路径、环境变量 | nginx -t、配置文件 diff、启动日志 |
配置写错或改了没 reload |
| 系统层 | CPU、内存、磁盘、文件句柄、时间 | top、df -h、free -m、ulimit -n |
资源耗尽或磁盘写满 |
| 依赖层 | 数据库、下游接口、DNS、证书 | curl、dig、证书有效期检查 |
外部依赖不可用 |
这个顺序的价值在于:它强迫你先确认“问题在哪一层”,再决定查什么。跳过现象层直接看代码,是新手最常见的低效路径。
还有一个原则:先看日志,再改参数。 日志里通常已经写了原因,改参数属于猜测。猜对了是运气,猜错了会把现场破坏掉,后面更难查。
7.2 两个高频现场:服务起不来、磁盘被写满
服务起不来,按这个顺序走:先 systemctl status 看状态和最近几行日志,重点看退出码;再 journalctl -u 服务名 -n 100 看完整报错;然后 ss -lntp | grep 端口 确认端口是否被占;接着看运行用户对工作目录有没有权限;最后看配置文件语法。
这里有个高频误判:看到 status 里显示 activating (auto-restart),以为是 systemd 有问题,实际上是服务自己启动就失败,systemd 在不停地拉。真正的原因在 journalctl 里,不在 status 里。
磁盘被写满,分三步。第一步确认是哪块分区满了:df -h。第二步找大目录,从根开始逐层缩小:
bash复制du -xh --max-depth=1 / 2>/dev/null | sort -rh | head -10
-x 表示不跨文件系统,避免统计到挂载的其他盘。第三步确认是哪种“满”:df -i 看 inode 使用率,如果 inode 满了但空间还有,说明是小文件太多,通常是缓存目录或者 session 文件。
清理的时候优先处理日志和缓存,别急着删业务数据。日志清理要考虑服务是否还在写,直接 rm 一个正在被写入的文件,空间不会立刻释放,因为文件句柄还开着。正确的做法是清空内容或者用日志轮转:
bash复制# 清空而不是删除,句柄还在也能释放空间
: > /var/log/app/app.log
真要长期解决,还是配日志轮转,按大小和时间双重条件切分,保留若干份。这件事应该在部署阶段就做,而不是等磁盘满了再补。
8. 把练习变成习惯,比刷完教程更有用
学 Linux 运维最容易出现的状态是:教程看完,命令认识,真给一台机器还是不知道从哪下手。破局的办法不是再看一遍,而是给自己定几个固定的小任务,反复做。
比如每周做一次“从零到可用”的完整流程:开一台新机器,配网络、配时间、建普通用户、配密钥登录、装一个 Web 服务、用 systemd 托管、加 Nginx 反代、配日志轮转、写一个定时清理脚本。全程掐表,第一次可能要两三个小时,做到第五次基本能在四十分钟内完成。这个过程练的不是记忆,是流程的熟练度和对每一步“为什么这么做”的理解。
再比如给自己制造故障:手动改错一个配置看报错长什么样,把服务用户改成一个没权限的账号看会发生什么,把磁盘填满看哪些命令会变慢。见过的故障越多,排查时越不慌。 这比背一百条命令有用。
最后提醒一句:所有涉及改配置、改网络、改权限的操作,先打快照或者先备份文件。练手环境里翻车的成本很低,但养成这个习惯之后,到了真实环境里就是保命的。工具和命令会随着发行版更新换代,排查问题的顺序和“先看日志再动手”的原则,十年都不会变。
