1. 快速定位哪个层次出问题
当服务异常或告警时,我第一步不是直接重启,而是把系统"目前的样子"抓下来,命令很短但信息密度高:
bash
# 进程与负载
uptime
top -b -n 1 | head -n 20
# 内存/交换
free -h
vmstat 1 5
# 磁盘空间与 inode
df -hT
df -i
# I/O 与等待
iostat -xz 1 3 # 需要 sysstat 包
iotop -o # 需要 iotop
# 网络侦测
ss -tulpn
ip a
ip route
这些输出能马上告诉我:CPU 被某进程吃满了?内存耗尽?磁盘满了导致写失败?还是网络端口没有监听?我会把这些命令输出复制到一个临时文件,作为后续分析的证据。
2. 进程层面精查
如果 top 显示某个 PID 占用异常,我会用以下步骤确认进程行为,不轻易 kill:
bash
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%cpu | head -n 20
# 查看进程打开的网络/文件
lsof -p <PID>
ss -p | grep <PID>
# 跟踪系统调用(短时间内观察)
strace -p <PID> -s 200 -o /tmp/strace.<PID>.log
# 或只抓取阻塞的 syscall
strace -p <PID> -e trace=network,file -s 200 -o /tmp/strace.net.log
我用 strace 并不是长期跟踪,而是想知道程序卡在做 I/O、等待网络,还是在无限循环。如果 strace 显示 blocked on write 或 blocked on futex,那我就知道这不是 CPU 算力问题,而是 I/O 或锁竞争。
如果是内存问题,用 pmap -x <PID> 或 smem 看内存分布;如果是频繁创建子进程导致 load 高,用 pstree -p <PID> 看父子关系。
3. 先读不改,再动手
磁盘满、inode 用尽、文件系统错乱是我遇到最多的停服来源。关键原则:能读就备份。
查磁盘占用时,我不直接用 du /(太慢),而是分级定位:
bash
# 大目录一览,快速找到"胖目录"
du -xsh /var/* | sort -rh | head -n 20
# 定位单个目录下的大文件
find /var/log -xdev -type f -size +100M -exec ls -lh {} \;
# 查 inode 使用
df -i
磁盘满了能短期救急的做法我会先用:清理旧日志(但保留备份),压缩归档冷数据,或把某个目录临时挂到另一个磁盘上(mount --bind)。只有在确认没有其他办法时才删除文件,并把删除清单记录下来。
若遇到 filesystem corruption,我会先用 fsck.ext4 -n /dev/sdX 做只读检查,然后做镜像 dd if=/dev/sdX of=/backup/sdX.img bs=4M status=progress(如果盘还能读),再在镜像上尝试修复,这样把风险降到最低。
4. 我如何快速从日志里抓问题
我经常用 journalctl 和 tail -F 联合抓取服务日志。journalctl 的时间过滤很有用:
bash
# 系统 journal
journalctl -xe --no-pager
# 某个服务最近 200 行并持续跟踪
journalctl -u myservice -n 200 -f
# grep 关键词(注意 journalctl 自带过滤)
journalctl -u myservice --since "2026-01-25 10:00" --until "2026-01-25 11:00" | grep -i error
我一般不会一次读全日志,而是先定位时间窗口(报警触发时刻前后 5 分钟),然后向外扩展。很多时候根因就在那短短几行堆栈或错误代码里。
5. 验证链路、端口、DNS、路由
网络故障常有三种表现:本机无法访问、端口未监听、远程不通。我常做的顺序是:
ip a看地址;2.ss -tulpn确认服务在监听;3.curl -I http://127.0.0.1:端口验证本机服务;4.tcpdump -i <if> host <peer>抓包看流量。
举个我常用的抓包命令:我想看与远端 10.1.2.3 的连接:
bash
sudo tcpdump -i eth0 host 10.1.2.3 -nn -s0 -w /tmp/cap.pcap
抓完我会用 Wireshark/tcpdump -r 本地查看是否有三次握手,是否有 RST,或者是否只是应用层超时。
6. 服务管理与快速恢复的套路
我始终坚持"先恢复服务,再做根因分析"。这通常意味着快速重启 service 或切换到备实例,而不是盲目调参。常用命令:
bash
systemctl status myservice
systemctl restart myservice
systemctl stop myservice
journalctl -u myservice -n 200 -f
如果重启后问题消失,我不会当场把系统升级或改配置;我会把恢复步骤记录,标注为"临时恢复",并在事后低峰时段做深入排查。
7. 备份与恢复
我偏好 rsync 做文件/目录级备份,因为它简单且可增量。示例我常用的命令:
bash
rsync -aHAX --delete --info=progress2 /data/ /backup/data/
# 说明:-aHAX 保持权限/硬链接/ACL/扩展属性;--delete 保证目标镜像源;--info 显示进度
对于更复杂的版本化备份,我会用 rsync --link-dest 做硬链接增量,或者长期使用 restic / borg 做去重和加密备份,这里我个人偏好 restic 的简单性。
重要的是:每次备份后都做恢复演练。备份不验证 = 没有备份。
8. 升级、打补丁与变更管理
在我看来,升级是风险管理而不是例行操作。原则上我在三层环境跑升级:
- 本地开发机(快速验证)
- 灰度或测试环境(业务场景覆盖)
- 生产(低峰窗口,先备份)
如果是关键组件(内核、数据库、容器 runtime),我会先拍快照或备份数据,并准备回滚计划。很多故障来自"版本跳太大",所以分阶段、每次改一个维度,是我不出意外的保命法则。
9. "救命"命令
下面这些命令我把它们背在手上,关键时刻能救场(每个命令前后的语境我都会先确认):
- 找占空间的文件:
bash
du -xsh /var/* | sort -rh | head -n 20
- 找大于 100MB 的文件:
bash
find / -xdev -type f -size +100M -exec ls -lh {} \; | sort -k5 -h
- 快速查看某端口谁在占用:
bash
ss -tulpn | grep :80
- 把某个服务日志流式保存并 grep 错误:
bash
journalctl -u myservice -f |& tee /tmp/myservice.log | grep -i error
- 临时增加 swap(短期救内存不足):
bash
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
这些命令看起来简单,但用了就知道:在紧急情况下,速度和证据比完美的步骤更重要。
10. 我的小习惯
我把这些习惯放在最后,因为它们往往比一堆命令更能降低事故率:
- 每次变更写变更日志,记录时间、操作人和回滚步骤。
- 把常用的排错步骤写成脚本或 playbook(Ansible),避免"手工失误"。
- 定期演练恢复,从 1 次变更开始建立信心链。
- 对生产机器做最小权限配置,避免运维误操作造成级联故障。
- 对关键盘做 SMART 定期检测并预警(
smartctl -H /dev/sdX)。