Linux 运维必会:这些命令不会,排障效率至少慢一半
一、问题背景
线上出问题,最怕的不是问题本身,是"不知道从哪儿下手"。同样拿到一份"系统卡顿"的工单,老鸟 10 分钟出根因,新人可能要花半天,原因往往就是一套排查命令不够熟。
Linux 命令本身不少(GNU coreutils + util-linux + procps + iproute + … 加起来几百个),但真正高频、能在生产环境直接复用的就那么几十个。这几十个都不熟:
-
高峰期 CPU 100% 报警,不知道是哪个进程占的。 -
业务反馈"慢",但 top看 CPU 不高、内存也不高,无从下手。 -
磁盘突然写满, du半天查不到大文件在哪。 -
进程启动失败, systemctl status一行红字,愣是没看懂到底卡在哪。 -
网络不通, ping能通但curl不通,netstat看不懂。 -
日志滚得飞快,眼睛跟不上。 -
诡异问题,重启就消失,没法复现。
这背后其实是"Linux 排障的基本盘"不扎实。“基本盘"是什么?是对 CPU / Memory / Disk IO / Network / Process / File / Log / 启动流程 / 系统调用 / 资源控制 这一套内核概念有一个清楚直觉,再把对应的"信息源”(/proc、/sys、strace、lsof、ss、perf)和"命令入口"(top、ps、pidstat、iostat、vmstat、sar、mpstat)掌握到位。
本文围绕"CPU / 内存 / 磁盘 IO / 网络 / 进程与文件 / 搜索与日志 / 启动与服务"八个维度,把一线真正有用、并且教科书里也会点到的命令整理成"目的-命令-预期-判断-下一步"五段式清单。读完后,应该能做到:
-
拿到一个工单,能在 5 分钟内把信息从内核层面摘出来。 -
能根据现象推测"该看哪个命令",而不是乱枪试。 -
知道破坏性命令的边界,能避免在生产误删。
需要说明的是,本文以 RHEL/CentOS 7+ / Ubuntu 18.04+ / Debian 10+ 为主流目标系统。perf、turbostat 等工具在某些发行版默认没装,会标注。iproute2 系列(ss、ip)已经取代大部分 net-tools 系列(netstat、ifconfig),本文以 iproute2 为主。
二、适用场景
下列场景,都是本文会深入讨论的:
-
CPU 满载,需要定位是哪个进程或哪段代码。 -
CPU 看似不高,但业务反映"慢"。 -
内存使用率高,想知道是不是 leak。 -
大量 swap 命中,性能塌方。 -
磁盘 IO 突增,写延迟飙升。 -
磁盘写满,找不到大文件。 -
网络不通,能 ping 通但连不上服务。 -
服务连接数打满。 -
进程启动失败,看不懂报错。 -
日志被刷屏。 -
进程僵死 / 僵尸进程。 -
端口冲突,listen 不上。 -
文件被谁占用,无法删除。 -
服务 Down 后想秒级定位是开机没起来还是运行中挂了。 -
系统启动卡住 / 启动失败。 -
内核日志告警( dmesg里都是红色)。
不在本文范围:
-
不展开 KVM 虚拟化层、容器化层( cgroup、namespace等)的深入;只在相关命令处顺势提一下。 -
不写 shell 编程技巧、不写网络协议栈源码解析。
三、核心知识点
下面这些是后面命令的"地基"。理解之后再读命令表会很顺。
1. CPU 三大块
- user
:用户态进程(非内核代码)。 - sys
:内核态 CPU。 - iowait
:CPU 在等 IO 完成。 - nice / irq / softirq / steal
:优先级、硬中断、软中断、被 hypervisor 偷走的时间。
关键观察:
-
user 高 + load 高 → 应用占 CPU(计算密集)。 -
sys 高 → 内核态吃 CPU(系统调用多、IO 调度、锁竞争)。 -
iowait 高 + load 高 + sys 不高 → IO 设备跟不上。
2. 内存与缓存
free命令看到的buffers/cached都是 Page Cache,本质是"已用但可回收"。系统内存吃紧时,这部分会先释放。 available是真正可用:约等于 free + buffers + cached - 不可回收部分。swap命中不一定是有压力:可以被动换出。 /proc/vmstat中pswpin/pswpout是更严格的 swap 流量指标。- OOM
:被 OOM Killer 杀掉的进程在 dmesg | grep -i 'killed process'。
3. 磁盘 IO 指标
iostat -xz 1输出里: r/s、 w/s:每秒读写次数。rkB/s、 wkB/s:每秒读写字节。await:单次 IO 平均等待(毫秒)。 %util:设备利用率(注意不直接等于负载,IO 队列深度也会影响)。 - NVMe 与 SSD
: %util经常 100%,但await仍很小,是因为并发度高;要看aqu-sz(平均队列)和await。 - 写延迟 / 读延迟
: await是平均值;如果业务对延迟敏感,应看 P99,需要 sar 或更专业的工具。
4. 网络
ss -ntp看 TCP 连接, -p列出进程(需要 root)。ip -s link看网卡统计(丢包、错误、队列)。 - TCP TIME_WAIT
:客户端主动关闭后留 30~60s 的"时间等待",正常,但量太大会占端口。 - Listen backlog
:内核 somaxconn与 backlog 联合决定。listen()不带backlog默认 5。 - DNS 慢
: getent hosts/getent ahosts/dig排查。 net.ipv4.tcp_tw_reuse=1:开启后可重用 TIME_WAIT;生产慎用 --reuseport,留量需要的场景才开。
5. 进程 / 文件 / 文件描述符
每个进程:
/proc/<pid>/status:状态、UID、线程数、内存等。 /proc/<pid>/fd/:当前打开的文件描述符(符号链接)。 /proc/<pid>/fdinfo/:每个 fd 的具体信息。 /proc/<pid>/io:进程 IO 累计。 /proc/<pid>/cmdline:启动命令。 /proc/<pid>/cwd:当前工作目录。 /proc/<pid>/environ:环境变量。 /proc/<pid>/maps:内存映射。 /proc/<pid>/stack:内核栈(3.10+ 有;很多信息需要 root)。 文件描述符上限:默认 1024(
ulimit -n)。高并发服务必须改大。socket 文件:
unix:域的进程间通信 socket。
6. 启动与服务
- systemd
取代 SysVinit + Upstart: systemctl status nginx:看到 active (running)/failed/inactive。systemctl list-units --type=service:所有 unit。 journalctl -u nginx -n 100:服务日志。 journalctl -u nginx -f:实时跟踪。 systemctl daemon-reload:改了 unit 文件后。
7. 日志
/var/log/messages(RHEL)/ /var/log/syslog(Debian/Ubuntu):系统日志。journalctl:systemd journal,二进制索引过,查询快。 dmesg:内核环形缓冲,关机前所有"硬件相关"都会留这里。 /var/log/audit/audit.log:SELinux、pam_faillock 等。
8. 加载和加载平均
uptime/ top头上的load average是 1/5/15 分钟的可运行 + 不可中断进程数的滑动平均。- 单 CPU 机器
上 load=1是满载;多 CPU 上要除以核数。
四、整体排查或实施思路
按"现象 → 看哪一块 → 用什么命令"的顺序给一张主路径。
- 接收现象
:“慢 / 卡 / 报错 / 服务挂”。明确是某个服务还是整台机;是稳定复现还是突发。 - 入口检查
: uptime、top -b -n 1、free -h、df -h、ss -s、dmesg | tail -20。粗略判断 CPU / 内存 / 磁盘 / 网络 / 内核消息。 - 资源定位
:CPU 满 → pidstat/ps;内存高 →pmap或/proc/<pid>/status;IO 高 →iostat+iotop;网络连接满 →ss。 - 进程定位
:拿到 PID 后 /proc/<pid>/取细节。 - 链路定位
:网络问题走七层模型:物理层 ethtool→ MACip link→ IPip addr、ip route→ TCPss、tcpdump→ 应用curl/http。 - 日志定位
:业务日志、内核日志、服务日志、journal。 - 处置
:调参数 / 杀进程 / 重启服务 / 修改配置 → 验证。 - 复盘
:记录现象、命令、参数、结论,沉淀到 wiki。
注意:以上每一步都先观察再下手。先看后杀 是基本准则。
五、实战步骤
下面这十几个步骤能覆盖 80% 的常见线上故障。
步骤 1:系统入口快照
目的:拿到当前机器的全局状态快照。
命令:
uptime
top -b -n 1 | head -20
free -h
df -h
ss -s
dmesg | tail -20
预期输出(示意):
uptime:14:32:11 up 30 days, 12:03, 1 user, load average: 0.40, 0.35, 0.30
top:Cpu(s): 12.0%us, 3.0%sy, 0.0%ni, 80.5%id, 3.0%wa, ...
free:16G total, 12G used, 1G free, 3G buff/cache
df:/ 50G 40G 8G 84% /
ss:TCP: 200 (estab 150, closed 30, orphaned 0, timewait 20)
dmesg:最后几条无报错
异常表现:
load高(> CPU 核数)、 us+sy高 → CPU 饱和。load高但 CPU idle 高、 wa高 → IO 等死。free几乎为 0 但 available还有 → 多数是 Page Cache,正常。dmesg出现 Out of memory: Killed process→ 历史 OOM。
判断逻辑:
-
锁定是哪一块吃资源(CPU / 内存 / IO / 网络)。 -
锁定是"持续发生"还是"刚发生"。
下一步动作:进入对应分支。
步骤 2:CPU 高定位
命令(看哪个进程最忙):
ps -eo pid,ppid,user,pcpu,pmem,comm --sort=-pcpu | head -20
命令(看每个进程的 CPU 时间片):
pidstat -p <pid> 1 5
命令(采样看 CPU 上跑哪些符号/函数):
perf top
perf在 RHEL 用yum install perf;Debian 用apt install linux-tools-common linux-tools-generic;容器环境看不到 perf。
预期输出:CPU 高的进程名、PID、占的 CPU 占比。
异常表现:
pcpu高 + 进程名是 kworker/ksoftirqd→ 内核态饱和,可能是 IO 中断或锁竞争。pcpu高 + 进程名是某业务进程 → 取 CPU 使用详情。
下一步动作:用 top -c / pidstat -p <pid> -w 看哪个线程占 CPU;用 perf top 看热点符号(MySQL、Java 这类也能看到热点函数)。
步骤 3:内存高定位
命令:
ps -eo pid,ppid,user,pcpu,pmem,rss,comm --sort=-rss | head -20
free -h
cat /proc/meminfo
命令(应用内存细看):看到 PID 后:
cat /proc/<pid>/status | grep -E 'VmRSS|VmSize|VmPeak'
cat /proc/<pid>/smaps_rollup
pmap -x <pid> | sort -nr | head
预期输出:
VmRSS:常驻内存。 VmPeak:进程历史最高占用。 VmSwap:被换出的内存。
异常表现:
VmRSS持续上涨 → 内存泄漏嫌疑。 -
大进程在 java -Xmx已经设置,但 RSS 远超 -Xmx → 共享库/线程栈。 -
RSS 不高但机器内存吃紧 → 内核 slab / page cache 太多, slabtop。
下一步动作:进入性能采样,看 vmstat 1 10。
步骤 4:swap 与 slab
命令:
vmstat 1 10
slabtop
vmstat 输出解读:
si/ so列:每秒换入 / 换出。bi/ bo:每秒块设备读 / 写。cs:上下文切换次数。
异常表现:
si/so持续非零 → 内存吃紧,已经在用 swap。 cs高(> 100k/s)→ 进程创建/退出频繁或线程调度抖动。
步骤 5:磁盘 IO 突增
命令:
iostat -xz 1 5
iotop
解读:
r/s、 w/s上升。await上升(> 5ms 关注,> 30ms 严重)。 aqu-sz(平均队列)上升。 %util高但 await 低:并发度高。
异常表现:
await高 + %util高 → 单设备 IO 饱和。-
某个磁盘高 → 该盘的 iostat -xz 1,看是不是有进程在疯狂 IO。
下一步动作:
-
用 iotop找到 IO 高的进程 ID。 -
用 pidstat -d 1 5看该进程 IO 详情。
步骤 6:磁盘占用 100% / 找不到大文件
命令:
df -h
df -i # inode
du -sh /* 2>/dev/null | sort -hr | head -10
异常表现:
Use%100% → 进入"找大文件"分支。 Use%不高但 IUse%100% → inode 用完(典型场景:大量小文件)。
下一步动作:
find / -type f -size +1G -exec ls -lh {} \;(按需)。 -
注意 find的耗时;可以du看每个一级目录占比,再递归。
命令:
du -sh /var/* 2>/dev/null | sort -hr
du -sh /var/log/* 2>/dev/null | sort -hr
find /var/log -type f -size +100M -ls | head
风险提醒:
find / -delete是不建议使用的格式。删除前先 -ls看清单。du -sh /*在 root 下耗时,可以用 du -hd 1限定。-
清理日志一定要让 Nginx / rsyslog 重新打开文件( kill -USR1或重启服务)。
步骤 7:网络连通性排查
命令:
ping -c 4 <host>
traceroute -n <host> # 或 tracepath
mtr -n <host> # 持续追踪丢包
预期输出:每个 hop 的 RTT / Loss%。
异常表现:
Loss%高 → 节点丢包。 Loss%主要在最后一跳 → 服务端不稳。
下一步动作:用 curl -v 拿完整请求/响应;用 tcpdump 抓包。
步骤 8:端口监听与连接
命令:
ss -tunlp
ss -s
ss -tan | awk 'NR>1 {c[$4]++} END {for (k in c) print c[k], k}' | sort -nr
解读:
LISTEN:监听中。 ESTAB:已建立。 TIME-WAIT、 CLOSE-WAIT大量 → 关闭策略/代码 bug。
异常表现:
-
服务正常但 ss看不到LISTEN→ 启动失败,进 service 日志。 CLOSE-WAIT多 → 代码没 close socket,应用 bug。
下一步动作:抓 tcpdump 抓一段时间,按需 tcpdump -ni eth0 host 1.2.3.4 and port 80 保存 pcap。
步骤 9:服务启动失败
命令:
systemctl status <service> -l --no-pager
journalctl -u <service> -n 100 --no-pager
journalctl -u <service> --since "5 min ago"
预期输出:
-
报错行 Failed with result ...、status=1/FAILURE。 -
末尾 Active: failed (Result: ...)。
异常表现:
Address already in use→ 端口被占; ss -tunlp | grep 80。Permission denied/ bind: ...→ SELinux、防火墙、用户、文件权限。No such file or directory→ 配置或路径错误。
下一步动作:拿具体报错去搜;对端口冲突解 PID 或改端口;对 SELinux 用 ausearch -m AVC。
步骤 10:进程僵死 / 僵尸
命令:
ps -eo pid,ppid,stat,comm | awk '$3~/Z/' # 找 Z 状态
top -b -n 1 | awk 'NR>7 && $8~/Z/'
异常表现:
Z(僵尸):进程退出但父进程没收尸;列父进程,重启父进程或 kill -CHLD <ppid>让父进程收尸。D(不可中断睡眠):通常是 IO 锁着,杀不死,只能解根因(拔盘、解除 mount)。
下一步动作:拿进程详情 cat /proc/<pid>/status、cat /proc/<pid>/wchan 看在哪阻塞。
步骤 11:文件被谁占用,无法删除
命令:
lsof /path/to/file
fuser -vm /path/to/file
fuser -km /path/to/file # 杀掉占用进程,慎用
lsof +D /path/to/dir | head
异常表现:
fuser -k会直接发 SIGKILL;生产慎用,先看 -v输出。
下一步动作:通知占用进程方,或者等业务侧关闭。
步骤 12:端口 / 进程关联
命令:
ss -tunlp | grep ':80' # 拿到 PID
ls -l /proc/<pid>/exe # 哪个二进制
cat /proc/<pid>/cmdline | tr '\0' ' '
异常表现:
ss不显示 PID:可能是 ss -p没 root;或者 socket 在别的 network namespace(容器场景常见)。
步骤 13:抓包
命令:
tcpdump -ni eth0 -w /tmp/cap.pcap tcp port 80
tcpdump -ni any host 1.2.3.4
tcpdump -ni any -s 0 -w /tmp/full.pcap
预期输出:pcap 文件。
下一步动作:拿到本地用 Wireshark / tshark 分析;也可以 tcpdump -A 直接打印数据,但注意敏感信息。
风险:
tcpdump -w /tmp/cap.pcap不要把 pcap 留在原机器太久;带敏感数据。
步骤 14:内核消息
命令:
dmesg -T | tail -50
journalctl -k --since "15 min ago"
异常表现:
Out of memory: Killed process→ 历史 OOM,定位被杀的进程。 I/O error, dev sda, sector ...→ 磁盘坏道,备份优先。 TCP: out of memory -- consider tuning tcp_mem→ TCP 缓冲不足。
下一步动作:定位具体硬件问题,请相应团队上硬盘 / 检查存储。
六、常用命令
把上面的命令整合成速查表。每个命令都明确给出目的、关键参数、典型用法,便于回头查阅。
1. CPU 相关
|
|
|
|
|---|---|---|
top |
|
-b -n 1
-p <pid>:只看一个
|
htop |
|
|
ps |
|
-eo
-L 看线程;--sort=-pcpu 倒序
|
pidstat |
|
-p <pid>
-u、-d、-w、-r、-t
|
mpstat |
|
mpstat -P ALL 1 |
sar |
|
sar -u 1 5
sar -P ALL 1 5
|
perf top |
|
|
turbostat |
|
|
uptime |
|
|
2. 内存相关
|
|
|
|
|---|---|---|
free |
|
-h
-s 1 持续输出
|
vmstat |
|
vmstat 1 10
|
pmap |
|
pmap -x <pid>
|
smem |
|
smem -u -k -r |
slabtop |
|
|
/proc/meminfo |
|
|
cat /proc/<pid>/status |
|
|
sar -r |
|
|
3. 磁盘相关
|
|
|
|
|---|---|---|
df |
|
-h
-i(inode)
|
du |
|
-sh
--max-depth
|
iostat |
|
-xz 1
|
iotop |
|
|
pidstat -d |
|
-p <pid> -d 1 |
lsblk |
|
|
blkid |
|
|
mount |
|
mount | column -t |
findmnt |
|
findmnt /xxx |
smartctl |
|
|
fsck |
|
|
4. 网络相关
|
|
|
|
|---|---|---|
ip |
|
ip addr
ip route、ip -s link
|
ifconfig |
|
|
ss |
|
-t
-u UDP、-n 数值、-p 进程、-l LISTEN
|
netstat |
|
netstat -tunlp |
tcpdump |
|
-ni eth0 -w file.pcap |
mtr |
|
mtr -n <host> |
traceroute |
|
traceroute -n |
curl |
|
-v
-I head、-k 不验证书、--resolve
|
wget |
|
-O -
|
dig
nslookup
|
|
dig +trace example.com |
ethtool |
|
ethtool eth0
-S 统计
|
sar -n DEV |
|
|
conntrack |
|
conntrack -L |
tc |
|
tc qdisc show dev eth0 |
5. 进程 / 文件 / 文件描述符
|
|
|
|
|---|---|---|
lsof |
|
-p <pid>
-i :80、+D /path/
|
fuser |
|
-v -m /path/
-k 杀进程慎
|
pidof |
|
|
pgrep |
|
pkill
|
pstree |
|
-aps <pid> |
ps |
|
-ef
-eo 自定义
|
kill |
|
-9
-TERM
|
pkill |
|
-HUP <pattern> |
strace |
|
-p <pid> -o strace.log |
ltrace |
|
|
gdb |
|
|
ulimit |
|
ulimit -n |
/proc/<pid>/fd/ |
|
ls -la
|
6. 搜索 / 文本
|
|
|
|
|---|---|---|
find |
|
-name
-mtime、-size、-user
|
grep |
|
-r
-E 扩展正则、-i 忽略大小写
|
egrep |
grep -E
|
|
xargs |
|
-n 1
-I{} 替换
|
awk |
|
awk '条件{动作}' |
sed |
|
-i
s/old/new/g
|
cut |
|
-d ':'
-f1
|
tr |
|
|
sort / uniq |
|
sort -nr
uniq -c
|
wc |
|
-l
-c
|
head / tail |
|
tail -F
|
7. 启动 / 服务 / 日志
|
|
|
|
|---|---|---|
systemctl |
|
status
start、stop、restart、reload、enable、disable、mask
|
journalctl |
|
-u <srv>
-n、-f、--since
|
service |
|
service nginx status |
chkconfig |
|
|
dmesg |
|
-T
|
tail -F |
|
tail -F /var/log/... |
less /F |
|
/keyword
|
lnav |
|
|
loginctl |
|
|
hostnamectl |
|
|
timedatectl |
|
timedatectl status |
localectl |
|
|
老命令(netstat/ifconfig/service/chkconfig)在新发行版可能未装。建议直接用新命令。
8. 进程与资源(cgroup / namespace)
|
|
|
|
|---|---|---|
systemd-cgtop |
|
|
systemd-cgls |
|
|
cat /proc/self/cgroup |
|
|
ls /proc/<pid>/ns |
|
|
cat /sys/fs/cgroup/.../<path>/cpu.stat |
|
|
prlimit |
|
prlimit --pid <pid> |
cat /proc/<pid>/limits |
|
|
9. 时间 / 硬件 / 系统信息
|
|
|
|
|---|---|---|
date |
|
date "+%F %T" |
chronyc |
|
chronyc sources
chronyc tracking
|
ntpq |
|
|
timedatectl |
|
|
lscpu |
|
|
dmidecode |
|
|
lspci |
|
|
lsusb |
|
|
ethtool -i eth0 |
|
|
numastat |
|
|
biosdecode / dmidecode -t bios |
|
|
cat /proc/version |
|
|
uname -a |
|
|
uptime |
|
|
10. 容器 / 虚拟化(按需)
|
|
|
|
|---|---|---|
docker ps / logs / exec |
|
|
crictl ps / logs |
|
|
ctr -n k8s.io containers ls |
|
|
podman |
|
|
virsh |
|
virsh list |
ip netns |
|
ip netns exec <ns> ss -tunlp |
lsns |
|
|
七、配置示例
下面这些配置示例并不直接出现在排障命令里,但理解它们能避免"排障时把生产改崩"。
1. 内核参数 /etc/sysctl.conf
生产环境常用的几条,关注 net.core.somaxconn、net.ipv4.tcp_*、vm.swappiness:
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_slow_start_after_idle = 0
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
fs.file-max = 2097152
fs.nr_open = 1048576
风险:
tcp_tw_reuse=1与tcp_tw_recycle=1不一样,后者早已被废弃,开启会出怪问题,本文不写tcp_tw_recycle。vm.swappiness设为 10 是常见做法,倾向减少 swap;但实际要按业务调。
生效:
sysctl -p /etc/sysctl.conf
sysctl -w net.core.somaxconn=65535
2. 资源限制 /etc/security/limits.conf
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 65535
* hard nproc 65535
* soft core unlimited
* hard core unlimited
root soft nofile 1048576
root hard nofile 1048576
注:systemd 启动的服务要看 /etc/systemd/system/<srv>.service.d/override.conf 中的 LimitNOFILE。
3. nproc / cgroup
如果是 cgroup 限制(容器、systemd unit),配置在对应位置:
systemctl set-property nginx.service LimitNOFILE=1048576
4. logrotate 通用模板 /etc/logrotate.d/generic
/var/log/myapp/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 root adm
sharedscripts
postrotate
/usr/bin/systemctl reload myapp >/dev/null 2>&1 || true
endscript
}
注:自定义应用要按服务类型决定 postrotate 是发信号还是 reload。
5. sshd 基础加固 /etc/ssh/sshd_config
列出只为口径,和排障时用
ssh -vvv抓错能看懂。
Port 2222
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
MaxSessions 10
ClientAliveInterval 300
ClientAliveCountMax 0
AllowUsers ops
生效:
sshd -t
systemctl reload sshd
6. sysstat 采集 /etc/cron.d/sysstat
*/10 * * * * root /usr/lib64/sa/sa1 1 1
53 23 * * * root /usr/lib64/sa/sa2 -A
改完 crontab 后
systemctl restart crond。
7. 自定义 alias
/root/.bashrc 中加:
alias ll='ls -lh --color=auto'
alias la='ls -alh --color=auto'
alias du1='du -hd 1 | sort -hr'
alias psmem='ps -eo pid,user,pcpu,pmem,rss,comm --sort=-rss | head'
alias pscpu='ps -eo pid,user,pcpu,pmem,comm --sort=-pcpu | head'
alias ports='ss -tunlp'
alias ip4='ip -4 addr | grep inet'
八、日志或指标观察方法
下面这套观察方法需要"指标体系"的支撑。
1. 主机级指标
- CPU
:用户态/内核态/IOwait/软硬中断。 - 内存
:可用、已用、cached、swap in/out。 - 磁盘
:read/write TPS、带宽、await、util、inode。 - 网络
:收/发 PPS、丢包、错包、TCP 重传。 - 进程
:CPU、内存、IO、文件描述符、线程数。
采集工具:node_exporter(Prometheus) / Telegraf / 阿里云 / 腾讯云的云监控。
2. 关键指标观察点
- CPU sys 高 + 软中断高
:网络栈瓶颈或锁竞争,配合 mpstat -P ALL 1看分布。 - iowait 高 + await 高 + %util 高
:磁盘瓶颈。 - available 持续下行 + 主动换出
: vmstat 1持续看si/so。 - TCP 重传
: netstat -s或ss -s。 - TIME_WAIT 持续上万
:客户端每请求都新连接,复用率低;改 keep-alive / 升 HTTP/2。
3. sar 历史回放
yum install sysstat
systemctl enable sysstat
systemctl start sysstat
sar -u 1 5
sar -r 1 5
sar -n DEV 1 5
sar -P ALL 1 5
sa1 1 5 # 手动采
sadf -d /var/log/sa/sa$(date +%d) -- -n DEV # 取当天数据输出 CSV
4. Prometheus 视角
核心指标(拿 node_exporter 即可):
node_cpu_seconds_total{mode} ratenode_memory_MemAvailable_bytes / node_memory_MemTotal_bytesnode_disk_io_nownode_network_receive_bytes_total rate / node_network_transmit_bytes_total ratenode_filefd_allocated / node_filefd_maximum
告警阈值按业务基线调整。常见做法:
-
CPU 用户态 > 80% 持续 5 分钟。 -
available 内存 < 10% 持续 5 分钟。 -
disk space 使用率 > 90%。 -
await > 30ms。
5. 日志巡检
-
检查 /var/log/messages、/var/log/syslog中 OOM、IO error、kernel panic 字样。 -
检查 journalctl -p err中 err 及以上级别。 -
业务日志各服务抽取"异常关键字"( exception、failed、timeout、killed)做计数。
九、排查路径
下面给出十几个常见异常的"决策树"。
路径 1:CPU 100%
uptime load 高 → top 看 us / sy / wa
├── us 高 → ps -eo pcpu | head → 找到进程 → strace -p <pid>
│ → 看系统调用;perf top 看热点
├── sy 高 → mpstat -P ALL 1 → 某个核上 iowait / softirq 高
│ → 中断分布 / 软中断优化
└── wa 高 → iostat -xz 1 → 找磁盘瓶颈 → iotop 找进程
路径 2:进程不存在但端口被占
ss -tunlp | grep :80
└── 没看到 PID → 进程可能已经死了,内核里有 lingering socket
└── fuser -k 80/tcp 杀掉,然后 wait 30s 内核回收
路径 3:服务起不来 Address already in use
journalctl -u <srv> --since "5 min ago"
└── ss -tunlp | grep :80
├── 没有进程占用 → 内核 SO_REUSEADDR 与 TIME_WAIT 残留,重启几秒可恢复
└── 有进程占用 → 拿到 PID → ps -fp <pid> 看是谁
路径 4:磁盘突然 100%
df -h
├── Use 100% → du -sh /var/* 找大目录
│ → 找到具体目录,find -size +1G -ls
├── Use 不高但 IUse 100% → inode 满
│ → find / -type d -size +1M -exec sh -c 'echo $(ls "$1" | wc -l) $1' _ {} \; | sort -nr | head
└── df 看 mount 选项 → mount 上 `ro`?
路径 5:慢查询 / 服务响应慢
curl -w "%{time_total}\n" -s -o /dev/null http://localhost/api
├── time_total < 50ms → 大概率是客户端问题
├── time_total 50ms~1s → 看应用日志 / 监控慢 SQL / GC
├── time_total > 1s → 链路问题
│ ├── 客户端到 Nginx → mtr / ping / DNS
│ ├── Nginx → 上游 → log_format 加 $request_time / $upstream_response_time
│ └── 上游 → 数据库 → slow log / EXPLAIN
路径 6:OOM Killer 出场
dmesg | grep -i 'killed process'
└── 找被杀的进程 PID、名字、时间
├── 内存泄漏 → 看 commit_history,常见于 Java/Node 长寿命对象
└── 总内存不够 → 升配 / 限流 / 调代码
路径 7:内网 DNS 解析失败
dig example.com @10.0.0.1
├── timeout → 53 端口 / iptables / nscd / systemd-resolved
└── 成功但解析到错误 IP → /etc/hosts / 视图问题
路径 8:TCP 连接数爆满
ss -s
├── ESTAB 很高且稳定 → 业务并发量真的上来了
├── TIME-WAIT 很高 → 复用率低或短连接过多
└── CLOSE-WAIT 很高 → 业务没 close,应用 bug
路径 9:磁盘 IO 抖动大
iostat -xz 1 10
├── await 抖动大 → 排查是不是有 GC / swap / 备份任务
├── 突发 write → 找进程;iotop
└── 不可解释 → 看 /sys/block/<dev>/stat 健康度、smartctl -a
路径 10:某个服务一直重启
systemctl list-units --type=service | grep failed
journalctl -u <srv> -n 200 --no-pager
└── 启动脚本问题 → 把 ExecStart 改成手工跑
├── 手工跑通 → unit 文件改成 nohup 路径不对
└── 手工跑挂 → 进 strace
路径 11:CPU 高但 iostat 显示空载
mpstat -P ALL 1 5
└── 单核 100% 但其他空闲 → 单线程程序 → 应用层优化
└── 单核 100% 但 us+sy 平均低 → 短时尖刺 → 看具体线程
└── ps -L -p <pid> -o pcpu,comm | sort -nr | head
路径 12:业务请求耗时长,但服务端 TPS 不低
curl -w "time_namelookup:%{time_namelookup}\ntime_connect:%{time_connect}\ntime_appconnect:%{time_appconnect}\ntime_pretransfer:%{time_pretransfer}\ntime_redirect:%{time_redirect}\ntime_starttransfer:%{time_starttransfer}\ntime_total:%{time_total}\n" -s -o /dev/null http://example/api
├── time_namelookup 长 → DNS 慢 → 配 DNS 缓存 / 调 host
├── time_connect 长 → TCP RTT 大 → mtr 看哪一跳
├── time_appconnect 长 → TLS 握手慢 → 是否启用了 OCSP stapling
└── time_starttransfer 长 → 服务端响应慢 → 看后端
路径 13:内核日志刷屏 net_ratelimit 被截断
dmesg
└── 'net_ratelimit: N callbacks suppressed'
├── 流量过大 / 内核在频发刷日志
└── 调 net.core.message_burst / net.core.message_cost
或者升级内核 + 调整驱动
路径 14:磁盘日志无权限写
tail: cannot open '/var/log/app.log' for reading: Permission denied
└── ls -la /var/log/app.log
├── 归属用户/组不对 → chown appuser:appgroup
└── 父目录权限不够 → chmod o+x /var/log
└── 同时仍是 root-only 写 → 想办法不被 sudo 改覆盖
路径 15:误改 sshd 配置导致无法登录
sshd -t
journalctl -u sshd -n 50
└── 立即再开一个 ssh 会话;不要断开当前
└── 当前会话保命的做法:echo '...' > /etc/ssh/sshd_config.d/...d ; sshd -t ; kill -HUP
└── 如果改了 system-auth / PAM → 严重情况下可能要 VNC/IPMI 进 console 修复
路径 16:磁盘掉线 / 多路径
lsblk
ls /sys/class/scsi_device/
dmesg | grep -i 'scsi\|sd '
└── 某盘消失 → 多路径软件 multipath / device-mapper 是否接管
└── multipath -ll
└── 软链路故障 → 检查线缆 / HBA 卡 / 光纤交换机
路径 17:内核软死锁 / hard lockup
dmesg | grep -E 'soft lockup|hard lockup|NMI'
└── 关闭 NMI 看门狗:echo 0 > /proc/sys/kernel/nmi_watchdog
└── 看是单核还是所有核:mpstat -P ALL 1
└── 锁在哪 → kernel debugger (crash) 或 perf
路径 18:systemd 启动卡住某个服务
systemctl list-jobs
systemctl status
└── 看到 'start' 持续 → 该 unit 卡住
└── systemctl mask 掉试试(实际不推荐);先看 status 输出卡在哪一步
└── ExecStartPre 阶段 → 解析脚本
└── ExecStart 阶段 → 应用启动慢 → strace
└── ExecStartPost → 启动后健康检查卡住(如 curl 阻塞)
路径 19:网络带宽看起来很低
sar -n DEV 1 5
ip -s link
ethtool eth0
├── 协商速率 100M 而不是 1G → 网线 / 交换机口
├── rx_dropped / tx_dropped 高 → 缓冲区打满,调 net.core.rmem_max
└── 链路没问题但应用慢 → 看应用层是不是限流了
路径 20:内存足够但 OOM 杀进程
dmesg | grep -i 'killed process'
└── 启动参数中 cgroup memory.limit 较小 → 实际机器内存看不到
└── 容器视角下 cgroup 内存限额太小 → 调整 spec.resources.limits.memory
└── 调整后验证 cgroupfs / sys/fs/cgroup/...
路径 21:TCP 重传率突增
ss -ti dst 1.2.3.4
netstat -s | grep -i retransmit
sar -n EDEV 1
└── 链路不稳 / 拥塞
└── 网络抖动 → mtr 找丢包
└── 客户端调整拥塞窗口:sysctl net.ipv4.tcp_congestion_control
路径 22:日积月累崩溃 / 进程自杀
journalctl -p err --since "30 days ago"
crash / var/crash/ 系统是否启用 kdump
└── 启用 kdump:systemctl enable kdump → 拍下下次崩溃 core
└── crash 工具分析 vmlinux + vmcore
路径 23:用户态 CPU 高但 top 不显示
top 按 H 显示线程
ps -eo pid,tid,pcpu,comm --sort=-pcpu | head
└── 线程耗 CPU 主线程不显眼 → perf top / pstree -p
路径 24:磁盘顺序写慢但随机 IO 正常
iostat -xz 1
└── 顺序写实质上对 SSD 是好的,机械盘要注意 noatime、I/O 调度器
└── cfq / deadline / noop → 对比测试
└── echo cfq > /sys/block/sda/queue/scheduler(重启失效)
路径 25:进程占用内存与 RSS 差距大
smem -p -k
└── RSS 减 shared ≈ PSS(proportional set size)
└── 容器视角下 cgroup RSS 计 PSS,会看到远小于 RSS 的大进程
十、风险提醒
下面这些操作只要出现踩过一次就够记一辈子。
1. rm
-
风险:不进回收站,删了就删了。 -
替代:先 ls -la确认;mv到/tmp或独立回收目录;脚本里至少一遍-print+cat。
2. find -delete
-
风险:漏路径或正则错,可能删错。 -
替代:先 find ... -ls | head看路径,再find ... -print | head,最后-delete。
3. truncate
-
风险:清空当前 inode 大文件,进程 fd 仍指向原 inode,可能导致文件空洞或写错位置。 -
替代:用 logrotate + 信号让服务重开文件。
4. KILL
-
风险: kill -9不给进程清理机会,会丢事务、不刷盘、文件描述符泄露。数据库、上游业务千万不要kill -9。 -
替代:先 kill -TERM,给 30s 缓冲;再不响应才-9。
5. 批量脚本
-
风险:写 for i in $(cat list)错把\n拼接错,导致一行跑成 N 段。 -
替代:明确 while read line,或者xargs -n1一行一命令。
6. 修改内核参数 / 防火墙 / 数据库参数
-
风险:错误参数可能让机器拒绝所有网络或磁盘 IO。 -
替代:先在测试机试;用 sysctl -w临时改,验证后再写进sysctl.conf。
7. 重启服务
-
风险:很多服务有缓存,重启会引发缓存击穿打挂下游。需要走灰度或预热。 -
替代:优先 reload;确实需要重启先确认是否有探活、是否有备用节点摘流。
8. 修改生产配置
-
风险:配置文件改错直接报错启动失败。 -
替代:始终 nginx -t、apachectl -t、httpd -t、mvn validate类。
9. 主从切换(数据库)
-
风险:错方向切换、数据丢失、从库脱节。 -
替代:先 show slave status\G看Seconds_Behind_Master、Relay_Log_File、Exec_Master_Log_Pos,确认无延迟再切。
10. 磁盘 / 文件 / 系统盘清理
-
风险:清理日志时不重开文件不会释放磁盘;清理 socket 路径可能破坏进程。 -
替代:日志清理走 logrotate 流程;socket 清理让进程自己删。
十一、验证方式
每次处理完都要验证,否则可能"看起来好其实没好"。
1. CPU 恢复
top -b -n 1 | head -5
ps -eo pid,pcpu --sort=-pcpu | head
预期:CPU 占用降回基线。
2. 内存回收
free -h
cat /proc/<pid>/status | grep VmRSS
预期:available 回升;进程 RSS 不再持续上涨。
3. 磁盘释放
df -h
du -sh /path/
预期:Use% 回到安全水位。
4. 网络恢复
ss -s
mtr -n <host>
curl -I http://...
预期:网络包建立正常,curl 返回 200/301/302 而不是 timeout。
5. 服务恢复
systemctl status <srv>
journalctl -u <srv> -n 50 --no-pager
ss -tunlp | grep <port>
预期:active (running)、监听端口恢复。
6. 配置生效
nginx -T | grep ...
httpd -t
mysqld --verbose --help | grep -i <option>
redis-cli config get <key>
预期:拿到预期配置。
7. 内核参数生效
sysctl net.core.somaxconn
sysctl -p
预期:值与配置文件匹配。
8. 限速 / 配额
ulimit -n
cat /proc/<pid>/limits
预期:与配置一致。
十二、回滚方案
下面对"高风险操作"给出最小可行的回滚思路。
1. 内核参数变更
-
修改前: sysctl -w net.core.somaxconn=65535记录当前值,或者读/etc/sysctl.conf备份。 -
回滚: sysctl -w net.core.somaxconn=ORIG、或cp sysctl.conf.bak sysctl.conf && sysctl -p。
2. 防火墙规则
-
修改前: iptables-save > /etc/iptables.backup或对应 firewall 导出。 -
回滚: iptables-restore < /etc/iptables.backup。
3. 服务配置
-
修改前: cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak。 -
回滚: cp回来 +nginx -t && nginx -s reload。
4. 数据库参数
-
修改前: SELECT @@xxx、SHOW VARIABLES LIKE 'xxx'记录。 -
回滚: SET GLOBAL xxx = 'old'。
5. 资源限制
-
修改前: ulimit -n当前值记录。 -
回滚:登录新 session 重设;或重启服务;或在 /etc/security/limits.conf改回。
6. 日志清理
-
删除前:分类、按业务决定保留天数。 -
回滚:从 OSS/S3 备份拉回来。
7. 文件误删
-
如果是 lvm + snapshot:回挂 snapshot 取回。 -
如果有备份:恢复。 -
如果都没有:磁盘数据恢复工具 extundelete / testdisk(成功率看文件系统活动)。 -
教训:上文件恢复只能取证式恢复,不保证完整。
8. 错误创建的 crontab
-
修改前: crontab -l > /root/cron.bak。 -
回滚: crontab /root/cron.bak。
9. 错误执行的 systemctl 命令
-
误禁用/启用: systemctl disable/enable撤销。 -
误 mask: systemctl unmask。
十三、生产环境注意事项
下面这些是"为什么专业运维和业余运维看起来在做相同事情,但稳定性差很多"的本质原因。
1. 所有变更都要走变更窗口
- 加白名单 / 修改防火墙 / 数据库参数 / 资源限制
:都需要灰度、值班、检查单、确认步骤。 - reload / restart
:要让观察者随时在场,关注错误率上升、关注告警。
2. 配置变更走"先 t 后 reload"
bash nginx -t && nginx -s reload
加 && 是为了让前者失败时不执行后者。这是工程纪律问题。
3. 编辑器选择
vi/ vim是默认选择。-
改完文件 nginx -t、apachectl -t、mysqld --verbose --help类似的校验不能省。
4. 拆解操作步骤
-
不在生产机器上跑没审过的 shell 片段;先在测试机 / 容器跑通。 -
复杂操作逐步执行,每步验证。
5. 执行窗口
-
高峰、变更窗口慎重;批处理、定时任务选低峰跑。 -
大批量任务(清理日志、 find -delete)要分批执行,并监控负载。
6. 权限 / 凭据
-
不让脚本明文保存密码,用 ~/.netrc、/etc/<svc>/<config>.cnf(权限 600)、环境变量、密钥管理系统。 -
用 ssh -i而不是把私钥写到配置里。
7. 时间一致
-
多机时间偏差大,日志/告警/调度无法对齐。 -
安装并启用 chronyd、或云厂商 NTP 服务。
8. 资源规划
/var/log、 /tmp、/var/cache各自独立分区或挂载,避免日志写满根盘。inode也要监控,电商促销等场景会生成大量小文件。
9. 内核升级 / 系统升级
-
升级内核要走灰度,尤其 ext4 / xfs / 网络栈 / cgroup 的行为在不同内核版本上不一样。 -
升级 glibc同理。
10. 与团队沟通
-
任何"看起来正常但我不确定"的操作,先和团队负责人对齐。 -
留书面记录(PR、工单、变更单)。
11. 调试痕迹不要长期驻留
strace输出文件、 perf数据、tcpdumppcap 都有敏感数据,跑完即删。
12. 备份与回滚
-
关键目录( /etc、/var/spool/cron、/var/lib/mysql、nginx vhost)都要有定期备份。 -
重要配置修改前后做 diff: diff -u before.conf after.conf | less。
13. 进程退出码
-
脚本 set -euo pipefail。 -
关键命令做 || exit 1显式失败。 -
日志统一格式,便于 ELK 分析。
14. 备机与降级
-
关键服务要有备机 / 多副本,保证单台挂了不影响整体 SLA。 -
故障期间适当降级(关不重要的非核心功能),先把核心稳住。
15. 知识沉淀
-
把每次线上问题的现象、命令、根因、修复、回滚写到团队 wiki。 -
沉淀为内部 runbook,下次同样的问题直接走 runbook 第一段。
十四、总结
Linux 运维基本盘,是把 资源维度(CPU / 内存 / 磁盘 / 网络)× 信息源(/proc、/sys、strace、日志、journal)× 命令入口(top/ps/pidstat/iostat/vmstat/ss/lsof/strace/journaltl) 这套三维网络打通。
一口气掌握的命令不需要几十个,需要的是 “有现象时,能在 60 秒内决定去看哪个文件、跑哪个命令”,并能 90% 覆盖常见问题。
一定要避免的几个反模式:
-
在生产直接 rm、find -delete。 -
高峰期重启服务。 -
改内核参数但没看清原来是什么。 -
看到 load高就重启机器。 -
看到 iowait高就上 SSD(要先确认确实是磁盘 IO 瓶颈)。 -
给服务器装 iperf3这类压测工具但忘了禁公网。
熟练度是练出来的。每天复盘一次当天的告警,对照命令与现象记录到 runbook;下次再遇到,三步之内命中。
把这套命令练熟,“Linux 排障"就真的能从"凭感觉"变成"凭证据”。

