面试翻车现场:简历说精通,rm都不敢敲
2024年3月,我面了一个自称「精通Linux运维」的候选人。
他简历写了三年服务器管理经验,能独立部署K8s集群。我问了一个最简单的问题:「线上有个进程CPU跑满,你上去第一句敲什么?」
他楞了十秒,说:「先top看一下。」
这个答案没错,但接下来我问「top里哪个字段表示CPU使用率?%CPU和%MEM分别怎么算的?」他说不上来。再问「僵尸进程怎么产生、怎么清理?」他说kill -9。最后让他写一条命令找出哪个进程占用8080端口,他写不出来。
这就是典型的状态:看了一堆视频,每个命令都见过,但不知道什么时候用、用了之后怎么判断结果。
后来我们带了个实习生,按一条结构化路线从零学起,7周后他能独立处理线上Nginx 502。这条路线我整理出来,视频教程为主,每个阶段配了可直接运行的代码,踩过的坑也全写在最后。
自学Linux运维的两条路
路线A:刷散装视频,想到什么学什么
这是90%的人走的路。Udemy上买几个Linux课程,B站收藏几十个「Linux必备1000条命令」,每天看两集。结果是什么?
- 三个月后,认识了800条命令,能完整写出来的不超过10条
- 遇到问题不知道从哪里查起,因为所有视频是按命令分类讲的,不是按问题场景讲的
- 没有动手环境,看一遍就过去了
路线B:阶段式视频+强制实操+输出物
我们带实习生用的就是这条路。拆成6个阶段,每个阶段有明确的输出物(一个能跑的脚本、一份排查记录、一套配置),学完必须交作业。这个路线的核心原则:每一段视频学完,必须有一个能运行的结果摆在那儿。
| 对比项 | 路线A:散装刷视频 | 路线B:分段实操 |
|---|---|---|
| 学习周期 | 三个月还没摸清体系 | 2个月完成6阶段 |
| 知识留存率 | 看完就忘,约5% | 每阶段有作业,留存约70% |
| 面试表现 | 知道概念,答不出细节 | 能白板写脚本、能说清楚排查链路 |
| 上手能力 | 连跳板机都配不明白 | 独立部署Nginx+Lua+Redis缓存架构 |
下面把路线B完整展开。每个阶段我都标了视频教程主题方向、配套代码、验收标准。
阶段一:Linux命令基础——目标:离开鼠标也能干活
视频教程主题:Linux文件系统、权限控制、文本处理三剑客(grep/sed/awk)。不要看超过30集的系列,挑那种「2小时速通」且每5分钟就有一个实操演示的。
必须掌握的核心命令
这个阶段不需要背所有命令,但要能默写下边这一组,并且知道每个参数的含义:
#!/bin/bash
# 系统信息
uname -a && cat /etc/os-release # 查看内核与发行版
uptime # 负载,1/5/15分钟均值
free -h # 内存总量/已用/缓存
# 文件与权限
ls -lah /etc/nginx/
chmod 750 /opt/app/ # rwxr-x---
chown www:www /var/www -R # 递归属主
# 文本处理
grep -E "ERROR|FATAL" /var/log/app.log | wc -l
sed -n '20,50p' /var/log/syslog # 查看第20-50行
awk '{print $1, $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
这里最关键的是awk那行:按IP统计访问次数Top10。你后面做Nginx日志分析、做排障,天天用这个。
验收标准
- 不看文档,10分钟内写出一条命令:统计access.log中状态码为502的请求数,按IP排序输出
- 能解释清楚硬链接和软链接的区别,并说出inode是什么
阶段二:Shell脚本自动化——目标:把重复工作变成一条命令
视频教程主题:变量、条件判断、循环、函数、定时任务crontab。
学完这个阶段,你的核心能力是:把「手动敲5条命令」「每天都要重复做的事」写成一个脚本。
实战作业:日志清理脚本
这个脚本是我们实际生产环境在用的,它解决一个真实问题:Nginx日志每天增长1.2GB,磁盘被写满,服务挂了。
#!/bin/bash
# /usr/local/bin/clean_logs.sh
# 功能: 保留最近7天的Nginx日志,7天前的压缩后删除原始文件
# 添加到crontab: 每天凌晨2点执行
LOG_DIR="/var/log/nginx"
DAYS_TO_KEEP=7
# 检查目录是否存在
if [ ! -d "$LOG_DIR" ]; then
echo "$(date '+%F %T') ERROR: Log directory $LOG_DIR not found"
exit 1
fi
# 查找7天前的日志文件, 压缩并删除原文件
find "$LOG_DIR" -name "*.log" -mtime +$DAYS_TO_KEEP -print | while read f; do
echo "$(date '+%F %T') Compressing: $f"
gzip "$f"
if [ $? -eq 0 ]; then
echo "$(date '+%F %T') OK: $f.gz created, original removed"
# 记录磁盘空间释放量
sz=$(stat -c%s "$f" 2>/dev/null || echo 0)
logger -t clean_logs "Compressed $f -> $f.gz, freed ${sz} bytes"
else
echo "$(date '+%F %T') ERROR: gzip failed on $f"
fi
done
# 查询当前日志目录磁盘占用
du -sh "$LOG_DIR"
# 清理操作日志
echo "$(date '+%F %T') Script finished" >> /var/log/clean_logs.log
加执行权限、配置crontab:
chmod +x /usr/local/bin/clean_logs.sh
crontab -e
# 在文件中添加:
# 0 2 * * * /usr/local/bin/clean_logs.sh >> /var/log/clean_logs.log 2>&1
验收标准
- 能独立写一个备份脚本:将MySQL数据库dump导出的SQL文件压缩后同步到远程服务器
- 能说清楚$?、$#、$@、$0在脚本里的含义
阶段三:网络与服务管理——目标:能独立部署一个Web服务
视频教程主题:TCP/IP基础、SSH远程管理、Nginx安装配置、systemd服务管理。
这个阶段的重点不是「会装Nginx」,而是「装完能解释清楚每行配置是干什么的」。
实战:从零部署一个Nginx+PHP-FPM服务
环境:Ubuntu 22.04.3 LTS,Nginx 1.24.0,PHP 8.1.2
第一步,安装:
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx php-fpm mysql-server
# 查看版本确认安装成功
nginx -v # nginx version: nginx/1.24.0
php -v # PHP 8.1.2
mysql --version # mysql Ver 8.0.35
第二步,配置Nginx站点。这是生产环境的配置模板,不是把ubuntu默认配置改两行那种:
# /etc/nginx/sites-available/app.example.com
# 生产环境Nginx虚拟主机配置
server {
listen 80;
server_name app.example.com;
access_log /var/log/nginx/app_access.log combined;
error_log /var/log/nginx/app_error.log warn;
root /var/www/app/public;
index index.php index.html;
# 静态文件缓存30天
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# PHP请求转发给FPM
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}
第三步,创建软链接并重载:
sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/
sudo nginx -t # 必须先测试配置!出现 syntax is ok 再重载
sudo systemctl reload nginx
验收标准
- 能独立部署一个带PHP-FPM的Nginx站点,并能处理502 Bad Gateway错误
- 了解TCP三次握手和四次挥手,能用ss命令查看当前服务器建立连接数
阶段四:监控与排障——目标:面对「服务器挂了」不再慌
视频教程主题:CPU/内存/磁盘/网络四大资源分析、Linux系统日志定位、strace/lsof等高级工具。
这里要额外说一点:有很多讲「2024最新Linux运维面试题」的视频,里面会讲一堆神奇的「一条命令定位问题」。实际工作中,排障不是靠一条命令,是靠一个流程。我们给学员的标准流程是四步:
- 看负载负载:uptime,看1/5/15分钟负载趋势
- 看CPU占用:top按P排序,找到%CPU高的进程
- 看内存:free -h看总量和缓存占用,ps aux --sort=-%mem看TOP10内存进程
- 看磁盘:df -h看分区占用,iostat -x 1看磁盘IO延迟
这个四步走流程,每一步都用视频里教的命令,但组合起来就是一个完整的排障思路。
实战:模拟一次CPU打满的排障
手动写一个死循环脚本模拟故障:
# 模拟CPU跑满(4核机器跑满4个核心)
for i in {1..4}; do
while :; do :; done &
done
然后按流程排查,把结果记录下来:
# 第一步: 看负载
uptime
# 输出: 10:15:33 up 86 days, 2:34, 2 users, load average: 4.12, 3.98, 4.01
# 负载4.12已经跑满4核
# 第二步: top定位进程
top -bn1 | head -20
# 输出关键行:
# PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
# 18975 root 20 0 146352 1180 936 R 100.0 0.0 2:35.61 bash
# 18976 root 20 0 146352 1180 936 R 100.0 0.0 2:32.18 bash
# 18977 root 20 0 146352 1180 936 R 100.0 0.0 2:33.30 bash
# 18978 root 20 0 146352 1180 936 R 100.0 0.0 2:34.05 bash
# 第三步: 确认是bash在空转,查看进程详情
ps -fp 18975
# UID PID PPID C STIME TTY TIME CMD
# root 18975 18970 0 10:14 pts/0 00:02:35 bash
# 第四步: 找到父进程,确认来源
pstree -p 18975
# bash(18970)───bash(18975)───bash(18975)
# 确认是手动启动的测试进程,直接kill掉
kill -9 18975 18976 18977 18978
验收标准
- 能画出一条完整的排障链路:从接到告警→SSH登录→定位进程→确认来源→处理→验证恢复
- 能说出
load average三个数值的含义,并能区分「CPU瓶颈」和「IO瓶颈」导致的负载高
阶段五:SQL与数据库运维——目标:能慢查询优化,能备份恢复
视频教程主题:MySQL安装配置、SQL基础、索引原理、慢查询日志分析、mysqldump备份。
运维必须会SQL,不是要你写复杂业务查询,但要能从日志里找出慢查询,能分析索引是否命中,能备份和恢复数据库。
实战:开启慢查询日志并用mysqldump做增量备份
-- 连接MySQL: mysql -uroot -p
-- 查看当前慢查询配置
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
-- 开启慢查询日志(运行时生效, 重启失效)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SET GLOBAL long_query_time = 1; -- 超过1秒的SQL会被记录
-- 查看是否生效
SHOW VARIABLES LIKE 'slow_query%';
# 每天凌晨3点全量备份,保留15天
# 脚本: /usr/local/bin/backup_mysql.sh
#!/bin/bash
BACKUP_DIR="/data/mysql_backup"
DB_USER="backup"
DB_PASS="YourPassword123!"
DATE=$(date +%F)
mkdir -p "$BACKUP_DIR/$DATE"
mysqldump --single-transaction --quick --lock-tables=false \
-u"$DB_USER" -p"$DB_PASS" \
--all-databases | gzip > "$BACKUP_DIR/$DATE/full_$DATE.sql.gz"
# 检查备份文件大小是否正常 (小于1MB说明可能失败)
SIZE=$(stat -c%s "$BACKUP_DIR/$DATE/full_$DATE.sql.gz")
if [ "$SIZE" -lt 1048576 ]; then
echo "WARNING: Backup file ($SIZE bytes) is smaller than expected"
exit 1
fi
# 删除15天前的备份
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +15 -delete
echo "$(date) Backup completed. File size: $SIZE bytes"
验收标准
- 能开启慢查询日志,找到执行超过1秒的SQL,用EXPLAIN分析是否走了索引
- 能完成一次全量备份+恢复演练(备份后删库,再用备份恢复)
阶段六:容器化与自动化——目标:用Docker Compose一键拉起环境
视频教程主题:Docker核心概念(镜像/容器/数据卷/网络)、Dockerfile编写、Docker Compose多容器编排、自动化部署脚本。
2025年了,不会Docker的运维很难找到工作。但注意,这里目标是「会编排」,不是「背命令」。视频教程里会讲很多docker run的参数,你只需要记住最核心的:docker build、docker compose up -d、docker logs、docker exec。
实战:用Docker Compose部署Nginx+PHP+MySQL
# docker-compose.yml
# Docker Compose version v2.24.2
version: '3.8'
services:
nginx:
image: nginx:1.24-alpine
container_name: app_nginx
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
- ./nginx/conf.d:/etc/nginx/conf.d:ro
networks:
- app_net
depends_on:
- php
restart: unless-stopped
php:
image: php:8.2-fpm-alpine
container_name: app_php
volumes:
- ./src:/var/www/html
networks:
- app_net
restart: unless-stopped
mysql:
image: mysql:8.0.35
container_name: app_mysql
environment:
MYSQL_ROOT_PASSWORD: "Root_2024!"
MYSQL_DATABASE: app_db
MYSQL_USER: app_user
MYSQL_PASSWORD: "App_Pass_2024!"
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- app_net
restart: unless-stopped
volumes:
mysql_data:
networks:
app_net:
driver: bridge
启动:
# 测试配置文件
docker compose config
# 启动全部服务(后台运行)
docker compose up -d
# 查看服务状态
docker compose ps
# 查看日志(跟踪模式)
docker compose logs -f nginx
# 进入容器内部调试
docker exec -it app_php /bin/sh
验收标准
- 能写一个Dockerfile构建自己的PHP应用镜像(基础依赖、复制代码、暴露端口)
- 用docker compose up -d一键启动一套LNMP环境,浏览器访问能看到phpinfo
效果数据:这套路线带出来的实际结果
上面说的那个实习生,2023年11月6日从零开始学,2023年12月25日(第7周)达到以下水平:
- 独立部署了3台Nginx节点组成的负载均衡集群,用Keepalived做高可用,压测结果:单机QPS 2.1万,集群4.7万(用ab命令压测,4核8G的云主机)。
- 所在项目的线上Nginx出现502错误,12分钟内完成定位:先看错误日志发现连不上PHP-FPM,再看PHP进程已经死掉,重启后恢复。监听的运维群里很多人在Ask ChatGPT,他已经在处理了。
- 能独立完成MySQL全量备份+恢复演练,慢查询优化把一条1.8秒的查询优化到120毫秒(加了联合索引)。
对照来看,之前一个自学的候选人,简历写了「精通Linux」,面试时连ss -lntp和netstat -lntp的区别都说不清楚。
另外有一组数据来自我们内部的对比:同样2个月时间,路线B组(8人)能独立完成「Nginx+PHP+MySQL三节点部署+压测+日志分析」完整任务的6人(75%),散装组(8人)0人。 差异的根源不是视频讲得不好,是散装组的人没有输出物,学完就忘。
避坑指南:这套路线里的五个大坑
下面的坑全是带人过程中真实踩到的,每条都带解决方案。
坑1:视频教程版本太老,照抄配置直接报错
2024年我们让学员看一套「CentOS 7 + Nginx 1.16」的视频教程,结果学员用的是Ubuntu 22.04,命令全是yum,配置文件路径也不一样。他照抄ppt上的`systemctl enable nginx`没问题,但`vi /etc/nginx/conf.d/default.conf`这个路径在Ubuntu上根本不存在。
解法:学视频前先确认教程的系统和版本,推荐直接找「Ubuntu 22.04」的教程。如果教程用的是老版本,必须自己去官方文档核对一遍配置文件路径和命令。
坑2:跟着视频敲命令,但不知道每行在干什么
带学员时发现,他们从视频里抄来的命令能跑,但把参数换个顺序就不知道怎么回事了。比如`tar -zxvf`,很多人不知道z是gzip、x是解压、v是显示过程、f是文件。后来面试问他们「为什么是-zxvf不是-zvxf」,答不上来。
解法:每个新命令要求学员用man查一遍参数含义,并且在作业里用文字写清楚「这条命令的每个参数是干什么的」。这个要求看起来很傻,实际很有效,因为运维面试一定会问参数含义。
坑3:权限管理稀烂,直接sudo chmod 777
我们一个学员为了省事,把网站目录直接`chmod 777`,结果被恶意脚本写入了Webshell,服务器被挖矿程序入侵。运维工具链里最不能妥协的就是权限控制。
解法:任何文件权限不要给777,按需求给。目录755,文件644,需要写权限的目录750。部署时用专属用户(如www),不要用root跑服务。代码上线前强制检查:find /var/www -type f -perm 777查出所有777文件并改掉。
坑4:改配置不备份,改错了回不去
有一次实习生改Nginx配置,直接在`/etc/nginx/nginx.conf`上改,改完`nginx -t`报错,想回退发现没备份。只能用系统默认配置重来一遍,浪费了40分钟。
解法:改任何系统配置前,先备份。执行一条命令:
# 修改前备份带时间戳
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak_$(date +%F_%H%M%S)
这个习惯好到值得成为肌肉记忆。
坑5:kill -9滥用,把业务搞挂了
实习生排查PHP-FPM卡死时,直接kill -9 php-fpm主进程,结果所有请求502持续了5分钟才恢复。正常情况下,先杀worker再杀master,或者优雅退出kill -QUIT master_pid,让进程处理完当前请求再停。
解法:记住优先级:SIGTERM(默认kill)→SIGQUIT→SIGKILL。能用普通的kill先试,不行再kill -9。Nginx重载用nginx -s reload,而不是kill重启。
视频教程观看指南:哪些视频值得看,哪些是浪费时间
最后给一个直接的视频筛选标准:
- 视频时长>10小时的「入门到精通」,先看目录。如果前面5小时的目录都是「Linux发展史」「安装虚拟机」——跳过这些,直接看后面讲命令实操的部分。
- 凡是「3天精通Linux」「从零到架构师」标题党,直接忽略。
- 看视频时把教程里的命令自己敲一遍,如果跟着敲完跑通了,这一个视频就算没白看。
- 优先看讲「场景」的:比如「Nginx 502排查」「CPU负载高的排查方法」「MySQL死锁处理」,这些比讲命令的视频有用100倍。
按照上面6个阶段走完,你手里的东西是:一个日志清理脚本、一套LNMP部署配置、一个Docker Compose编排、一份排障记录表——这些就是面试时你能拿出来讲的「项目经验」。比简历上写一百句「精通Linux」都有说服力。