引言:为什么你需要一个高效命令工具箱
登录一台 Linux 服务器后,你做的第一个动作是什么?十有八九是敲 ll 或者 ls -l,看一眼当前目录有哪些文件。这是正常操作,但问题在于——看完之后,很多运维工程师就停在这里了。
接下来的场景很典型:机器负载高、进程异常、磁盘报警、服务不响应、端口冲突、网络访问慢……大多数人还是下意识地翻 top、查 ps、看 netstat,然后一头钻进 /var/log/messages 手动 grep。这些操作不能说错,但效率极低——一个本来 5 分钟能定位的问题,硬是花了半小时。
工具选对了,排查速度能差一个量级。本文整理了 10 个高频实用 Linux 命令,覆盖资源监控、日志分析、网络排查、磁盘定位、文件压缩等日常运维场景。每个命令都从问题背景→常用命令→排查思路→风险提醒→验证方式的闭环结构出发,让你能直接照着操作。
选命令的标准:在生产环境摸爬滚打中真正用得上的、能显著缩短排查时间的、语法经过验证的。不是为了炫技,而是为了快速解决问题。
命令1:htop / btop —— 替代 top,一眼看清系统全貌
问题背景
top 是 Linux 最基础的进程监控工具,但它的交互界面粗糙,默认排序列不可调整,不能用鼠标操作,颜色区分度差,很多工程师用了十几年还是只会看 load average 和 %CPU 两个数字。
当机器负载高的时候,top 的问题是:你一眼扫过去根本分不清哪个进程是正常的、哪个是异常的、哪个在吃 CPU、哪个在等 I/O。
适用场景
- 频繁需要排序:按 CPU、按内存、按 PID、按运行时间
常用命令
# 最基础的启动htop# 指定用户只看某个用户的进程htop -u www-data# 指定刷新间隔(默认3秒)htop -d 10# 显示特定 PID 的进程及其子树htop -p 1234,5678
交互操作(进入 htop 界面后)
| |
|---|
↑↓ | |
→← | |
P | |
M | |
T | |
k | |
l | |
s | |
t | |
F2 | |
F3 | |
F4 | |
F5 | |
F6 | |
F10 | |
Space | |
u | |
H | |
Shift + . | |
排查思路:从全局到个体
第一步:看总体负载
进入 htop 后不要急着找进程,先看最上面三行:
Mem: 32.0G used, 1.2G buffers, 8.4G cached [||||||||||||||||||| ] 78.4%Swap: 2.0G used, 14.0G free [|| ] 10.0%CPU: 4.5% user, 1.2% system, 0.3% irq, 0.0% softirq, 93.8% idleTasks: 245 total, 3 running, 242 sleepingLoad average: 2.34 1.89 1.56 (1 min / 5 min / 15 min)
重点看:
- CPU 行:如果
user 高说明是正常业务负载,system 高说明是系统调用频繁,iowait 高说明在等磁盘或网络 I/O,idle 接近 0 说明 CPU 打满 - Mem 行:如果 used 接近 total 说明内存紧张,结合 cached 一起看——Linux 会把空闲内存拿去做 cache,cache 在需要时可以回收,所以 used 不等于"不够用"
- Load average:如果 1 分钟均值远高于 15 分钟均值,说明负载在快速上升
第二步:排序定位
按 M 看内存占用排序,按 P 看 CPU 占用排序。重点关注:
- 排名第一的进程占用是否异常(正常业务进程的内存占用应该是稳定的)
- 同一个进程是否有多个实例在跑(配置文件出错导致启动多次)
- 进程状态是否为
R(running,正在消耗 CPU)
第三步:看进程树
按 t 或 F5 切换树形视图,可以看到父子进程关系。比如 httpd 进程下面挂着多个 worker,如果父进程挂了子进程还在,说明某个 worker 导致父进程异常退出。
第四步:追踪 system call
选中某个可疑进程,按 s 可以 strace 这个进程的系统调用。如果进程在频繁 open/close 文件说明在大量读写文件,如果在 connect 说明在发起网络连接。这个操作对生产进程有性能影响,适合在测试环境或者影响可控时使用。
安装方式
# CentOS / RHELsudo yum install htop -y# Ubuntu / Debiansudo apt install htop -y# macOSbrew install htop
如果 Linux 发行版默认仓库的 htop 版本太旧,可以从源码编译安装,支持更多列和功能。
btop:更现代的替代
btop 是 htop 的增强版,界面更美观,数据刷新更流畅,支持 GPU/网络/磁盘的实时可视化。但默认不在发行版仓库里,需要从 EPEL(CentOS)或第三方仓库安装:
# CentOS 8 / AlmaLinux 8(需要先启用 EPEL)sudo dnf install epel-release -ysudo dnf install btop -y# Ubuntu 22.04+sudo apt install btop -y
btop 和 htop 的使用方式几乎一样,快捷键也通用,学会一个切换到另一个几乎零成本。
风险提醒
- 不要轻易在生产环境按
k 杀掉不明进程。杀掉一个业务进程可能导致服务中断,先用 ps aux | grep 确认这个进程是什么、属主是谁、什么时候启动的、为什么占用高 - 不要在生产环境对不明进程使用
s(strace)。strace 会显著降低目标进程的性能,对高并发服务影响很大 - htop 显示的 CPU 百分比是多核总和还是单核。在多路 CPU 机器上,一个进程占满一个核心显示是 100%,而不是 100%/N。如果要看单核占用率,需要在 Setup 里配置
- 线程数统计。Java、Go、Python(GIL 外)等语言会启动大量线程,在 htop 里按
H 可以切换是否显示线程,避免被线程数干扰判断
验证方式
# 确认 htop 安装成功htop --version# 确认 btop 安装成功btop --version# 确认进程真实占用(对比 htop 读数)ps aux | head -1ps aux | awk '{print $2, $3, $4, $11}' | sort -k2 -rn | head -10# 确认内存总量free -hcat /proc/meminfo | grep -E "MemTotal|MemFree|MemAvailable"
命令2:glances —— 一条命令看完系统所有关键指标
问题背景
htop 适合深入看进程和资源,但有时候你需要一个更全面的健康状态概览——CPU、内存、磁盘、网络、进程、外挂传感器温度一个页面全展示,不需要切换多个标签页或多个窗口。glances 就是这个场景的答案。
glances 的另一个优势是支持远程监控:在一台管理机上起一个 glances 服务,所有服务器的监控数据通过 REST API 或 Web 界面汇聚过来,值班的时候不用一台台 ssh 上去敲命令。
适用场景
- 快速评估一台陌生服务器的健康状态(交接机器、故障机器)
常用命令
# 基础启动(默认每2秒刷新)glances# 指定刷新间隔glances -t 1# 启用 CPU 详细信息(按核心显示统计)glances --per-cpu# 隐藏特定模块glances --disable docker# 以 JSON 格式输出(供其他工具消费)glances -o JSON# 输出到文件glances -o HTML -f /var/www/html/glances.html# 远程模式:作为服务端glances -s# 远程模式:连接远程服务器glances -c @server_ip
界面布局解读
CPU [%] | user: 4.2 | system: 1.8 | idle: 93.8LOAD [1 min] | 0.34 | 5 min: 0.45 | 15 min: 0.52MEM [%] | total: 32.0G | used: 18.4G | free: 13.6GSWAP [%] | total: 8.0G | used: 2.1G | free: 5.9G PROCESSOR PID USER CPU% MEM% TIME IO_R IO_W NET_R NET_W COMMAND 1234 nginx 2.1 0.8 1:23:45 - - 1.2K 328B nginx: worker 5678 mysql 1.4 12.3 45:12:03 12K 124K - - /usr/sbin/mysqld NETWORK | eth0: 12.3K/s in | 4.5K/s out | errors: 0 DISK I/O | sda: 23.4M/s read | 8.2M/s write MOUNT | /: 45.2G/100G used | /data: 234G/500G used
重点监控指标
CPU 模块
user:用户态 CPU 占用,正常业务主要在这里system:内核态 CPU 占用,频繁系统调用在这里iowait:等待 I/O 的时间比例,如果这个值持续高于 20%,说明瓶颈在磁盘或网络
内存模块
- Linux 内存机制:used 数字高不等于不够用,要看
available 或 cached。Linux 会把空闲内存拿来当文件缓存(cache),cache 可以快速回收,所以真正危险的是 available 接近 0,而不是 used 接近 total swap 如果被大量使用(si/so 不为 0),说明物理内存已经不够用,性能会严重下降
磁盘 I/O 模块
- 如果没有专门装
iostat 或 iotop,glances 的 DISK I/O 是最快速的 I/O 观测窗口 IO_R 和 IO_W 分别显示读写速度,持续高读写说明磁盘是瓶颈
网络模块
NET_R 和 NET_W:实时入方向和出方向流量- 如果观察到异常大的入方向流量,可能是被攻击或被拉肉鸡
远程集中监控
在管理机上:
# 启动 glances 服务端(默认监听 61209)glances -s -B 0.0.0.0# 在客户端机器上连接glances -c <管理机IP>
或者用 Docker 跑一个 Web 界面:
docker run -d --rm \ --name glances \ -p 61208:61208 \ -p 61209:61209 \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ nicolargo/glances:latest \ glances -w 0.0.0.0
然后浏览器访问 http://管理机IP:61208 即可看到 Web 界面。
风险提醒
- **glances 的网络流量统计依赖
/proc/net/dev**,在容器内运行时,网络流量统计不完整(只能看到 docker0 或 eth0 的合计,看不到每个容器的详细流量) - 在极低配置机器上运行 glances 本身会消耗资源,
-t 1 的刷新频率会比默认的 2 秒更耗 CPU,低配置机器建议用默认刷新间隔 - 远程模式默认没有认证,
-s 暴露的 61209 端口不应该直接对公网开放,建议放在内网或用 SSH 隧道访问
验证方式
# 确认安装glances --version# 确认 Python 依赖完整(glances 依赖 psutil)python3 -c "import psutil; print(psutil.__version__)"# 确认 JSON 导出可用(用于监控接入)glances -o JSON -t 5# 确认 Web 模式可用glances --webserver
命令3:ncdu —— 替代 du -sh *,快速定位谁在吃磁盘
问题背景
磁盘满是生产环境最常见的故障之一。日志暴涨、备份文件积压、容器镜像占用、大量临时文件、某个业务写文件没做轮转——都是常见原因。du -sh * 能看到每个目录的大小,但交互不友好,无法排序,不支持层层深入,而且在大目录上执行非常慢。ncdu 的出现就是来解决这些问题的。
适用场景
常用命令
# 分析当前目录(最常用)ncdu# 分析指定目录ncdu /var/log# 分析时排除某些目录(减少扫描时间)ncdu / --exclude /proc --exclude /sys# 排除特定模式(排除所有 .log 文件)ncdu / --exclude '*.log'# 扫描时显示详细信息(包含子目录计数)ncdu /home -r# 导出结果供以后查看(不重复扫描)ncdu / -o /tmp/ncdu.txt# 然后用 ncdu -f /tmp/ncdu.txt 打开
交互操作
排查思路:先全局后局部
场景:收到磁盘报警,/ 分区使用率超过 90%
# 第一步:看全局分区占用df -h# 输出示例:# Filesystem Size Used Avail Use% Mounted on# /dev/sda1 100G 95G 5.0G 95% /# /dev/sdb1 500G 320G 180G 60% /data# tmpfs 16G 0 16G 0% /dev/shm# 第二步:用 ncdu 扫根分区(排除虚拟文件系统加快速度)ncdu / --exclude /proc --exclude /sys --exclude /dev/shm --exclude /run
进入 ncdu 后,按 s 确保按大小排序,从最大的那个目录开始层层深入:
97.4GiB [##########] /data 45.2GiB [#### ] /var 23.1GiB [## ] /opt 8.7GiB [ ] /usr 1.2GiB [ ] /home
按 → 进入 /var,继续按大小排序:
38.4GiB [######## ] /var/log 5.2GiB [ ] /var/lib 1.6GiB [ ] /var/cache
进入 /var/log,找到最大的日志文件:
28.4GiB [######## ] /var/log/nginx 8.7GiB [#### ] /var/log/mysql 1.3GiB [ ] /var/log/messages
这时候就清楚了:nginx 日志吃掉了 28G,mysql 慢查询日志 8.7G。按 n 切换到按名称排序,看哪些是正常日志、哪些是异常堆积的。然后按 d 删掉可以清理的文件。
日志清理的安全操作流程
风险提醒:删除文件之前必须确认三点
- 确认文件没有被进程正在写:
lsof +L1 查看是否有进程打开这个文件(引用计数为 1 的文件是已经删除但还没关闭的) - 确认日志还在不在写入:如果业务还在写这个日志文件,删掉之后磁盘空间不会立即释放(因为进程还持有文件描述符),需要重启进程或者
kill -HUP 触发日志轮转 - 确认有备份:重要日志清理前,建议先
cp 到备份目录
# 查看被删除但未关闭的文件(空间不释放的原因)lsof +L1 /var/log# 查看哪些进程正在写某个日志文件lsof | grep /var/log/nginx# 用 truncate 截断日志文件(比 rm 安全,不会影响正在写文件的进程)truncate -s 0 /var/log/nginx/access.log# 截断后通知 nginx 重新打开日志文件kill -USR1 $(cat /var/run/nginx.pid)
安装方式
# CentOS / RHEL(需要 EPEL)sudo dnf install ncdu -y# Ubuntu / Debiansudo apt install ncdu -y# macOSbrew install ncdu
风险提醒
- ncdu 扫描本身会消耗大量磁盘 I/O,在大规模文件系统上扫描可能需要较长时间,对正在跑高 I/O 业务的生产机有影响,建议在业务低峰期使用,或者用
--exclude 排除不需要扫描的目录 d 删除操作不经过回收站,删除即删除,确认工作要做好- 不要删除正在被使用的文件,即使截断也要先确认进程状态
- 网络文件系统(NFS、CIFS)扫描慢,如果
/data 是网络挂载的,ncdu 会非常慢,建议分开扫描本地文件系统和网络挂载点
验证方式
# 确认安装ncdu --version# 扫描前后对比磁盘使用df -h /# 查看删除后空间是否释放df -h /# 确认没有进程锁定重要文件lsof /var/log/* 2>/dev/null | grep -v "^COMMAND"
命令4:journalctl —— 替代手动 cat /var/log/,日志查询神器
问题背景
传统的日志分析方式是 tail -f /var/log/messages 或者 grep "error" /var/log/xxx,这种方式在小规模服务器上没有问题,但面对以下场景就非常低效:
- 只想看某个服务(nginx、mysql)的日志,不想看系统混合日志
- 服务是 systemd 管理的,但日志分布在多个文件里
- 想要按日志级别过滤:只看 error 和 critical,不想看 info 和 debug
journalctl 是 systemd 生态的日志查询工具,提供统一的日志查询接口,支持时间范围过滤、服务过滤、级别过滤、关键词搜索,效率远高于手动 grep。
适用场景
- 按日志级别过滤,只看 ERROR 和 CRITICAL
- 服务是 systemd 管理(
systemctl start nginx),日志用 journald 收集
常用命令
# 查看所有日志(默认分页输出)journalctl# 实时跟踪日志(类似 tail -f)journalctl -f# 查看指定时间之后的日志journalctl --since "2026-05-15 10:00:00"journalctl --since "1 hour ago"journalctl --since today# 查看某个时间段的日志journalctl --since "2026-05-15 10:00:00" --until "2026-05-15 11:00:00"# 查看指定服务的日志journalctl -u nginx# 查看多个服务的日志journalctl -u nginx -u mysql# 查看指定 PID 的日志journalctl _PID=1234# 查看指定用户的日志journalctl _UID=1000# 按日志级别过滤(emerg alert crit err warning notice info debug)journalctl -p errjournalctl -p err -p crit # err 和 crit# 只看内核日志journalctl -k# 只看本次启动以来的日志(不看历史)journalctl -b# 查看上一次启动的日志journalctl -b -1# 查看指定开机以来的日志(通过 boot ID)journalctl -b abc12345# 查看日志总占用空间journalctl --disk-usage# 清理旧日志(保留最近 500MB)journalctl --vacuum-size=500M# 保留最近 7 天的日志journalctl --vacuum-time=7d# 查看日志条数journalctl --no-pager | wc -l# 统计 ERROR 级别的日志条数journalctl -p err --no-pager | wc -l# 高亮关键词(结合 grep 使用)journalctl -u nginx | grep -i "error\|timeout\|500"
高级查询语法
journalctl 支持比较丰富的字段过滤,可以精确定位:
# 精确过滤:某个服务 + 某个级别 + 某个时间之后journalctl -u nginx -p err --since "1 hour ago"# 过滤某个可执行文件的所有进程日志journalctl /usr/sbin/nginx# 过滤某个目录下的所有进程的日志journalctl /var/log/nginx# 组合过滤:进程名 + 时间范围 + 级别journalctl -u mysqld -p err --since "30 minutes ago"# 查看某个 unit 的详细日志(包含 spawn 的子进程)journalctl -u nginx --all# 实时跟踪某个服务并高亮 errorjournalctl -u nginx -f | grep --color=auto -E "error|ERROR|warn|WARN"
实战:定位 Nginx 500 错误的完整日志链路
# 第一步:看 nginx 服务状态systemctl status nginx# 第二步:查看 nginx 的 error.log(优先看 error 级别)journalctl -u nginx -p err --since "30 minutes ago" --no-pager# 第三步:如果 error.log 没有详细信息,看 access.log 里 500 状态码的请求journalctl -u nginx --since "30 minutes ago" --no-pager | \ grep '" 500 ' | head -20# 第四步:找到具体请求后,看这段时间内 nginx 的 error 日志journalctl -u nginx --since "2026-05-15 14:30:00" --until "2026-05-15 14:35:00" | \ grep -i "error\|upstream\|connect\|timeout"# 第五步:如果 upstream 有问题,检查 upstream 后端服务状态systemctl status php-fpmsystemctl status gunicorn# 第六步:确认是后端响应慢导致的超时journalctl -u nginx --since "10 minutes ago" | \ grep "upstream timed out\|no live upstream"
systemd-journald 配置说明
日志数据存在 /var/log/journal/ 目录下(如果系统启用了 persistent 存储)。日志轮转由 systemd 自动管理,不需要手动配置 logrotate。
配置文件在 /etc/systemd/journald.conf:
# 常用配置项(/etc/systemd/journald.conf)[Journal]# 持久化存储(默认是 no,即只存内存)/var/run/logStorage=persistent# 单个日志文件最大 100MBSystemMaxUse=500M# 日志总占用空间上限SystemMaxFileSize=100M# 压缩存储Compress=yes
改完配置后 reload:
sudo systemctl reload systemd-journald
排查思路:日志分析的标准化流程
- 先定时间:先确认故障发生的大概时间范围,用
--since 缩小搜索窗口,不要一开始就看全量日志 - 按级别过滤:先用
-p err 看错误级别,确认没有 error 后再扩大范围 - 看上下文:grep 到关键报错行后,用
-B 5 -A 5 看前后几行,理解完整调用链 - 交叉验证:nginx 的 error log 说 upstream 超时,要去后端服务(php-fpm/gunicorn)的日志里验证是不是后端真的慢了
# 查看 nginx upstream 超时的上下文(前后各5行)journalctl -u nginx --since "10 minutes ago" --no-pager | \ grep -B5 -A5 "upstream timed out"
风险提醒
- 日志保留策略:
journald 默认是 Storage=auto,在 /var/log/ 有 systemd 链接文件时会写入持久化存储,否则只存内存(重启后丢失)。如果需要保留历史日志,一定要确认 Storage=persistent 配置 - 磁盘占用:如果
SystemMaxUse 设置过大,日志会吃掉大量磁盘空间,需要定期清理 --vacuum-time 会删除旧日志:这个操作不可逆,清理前确认这些日志已经导出备份- journalctl 默认分页:在脚本中使用必须加
--no-pager,否则脚本会卡住
验证方式
# 确认 journald 运行正常systemctl status systemd-journald# 确认日志持久化配置grep Storage /etc/systemd/journald.conf# 确认日志目录存在ls -la /var/log/journal/# 确认日志总大小journalctl --disk-usage# 确认可以查到最新日志journalctl --since "1 minute ago" --no-pager
命令5:ss —— 替代 netstat,网络连接排查利器
问题背景
netstat 是传统的网络状态查看工具,但它的致命问题是在高并发服务器上极慢。一个承载 10 万连接的 Nginx 服务器,netstat -tunp 可能要卡 10 秒以上,原因是 netstat 通过遍历 /proc/net/ 下的所有条目来获取信息,而 ss 直接从 netlink socket 获取,效率差几十倍。
另一个问题是 netstat 在某些发行版已经默认不安装了(被标记为废弃),而 ss 是 iproute2 工具集的核心组件,几乎所有 Linux 发行版都自带。
适用场景
常用命令
# 查看所有 TCP 连接(最常用)ss -tunap# 参数说明:# -t: TCP 连接# -u: UDP 连接# -n: 数字显示(不解析域名,速度快)# -a: 显示所有连接(包括 LISTEN)# -p: 显示进程信息# 查看监听中的端口ss -tlnpss -ulnp # UDP 监听# 查看某个端口的连接状态ss -tunap | grep :80ss -tunap | grep :3306# 查看所有 ESTABLISHED 连接ss -tnp state established# 查看 TIME_WAIT 连接数ss -tnp state time-wait | wc -l# 查看所有状态的连接数统计ss -s# 查看来自某个 IP 的连接ss -tnp dst 192.168.1.100# 查看连接到的目标端口ss -tnp dst :80# 查看进程名包含 nginx 的连接ss -tnp | grep nginx# 查看 sockets 内存使用ss -m
输出字段解读
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Processtcp ESTAB 0 0 10.0.0.5:22 192.168.1.50:65432 users:(("sshd",pid=1234,fd=3))tcp LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=5678,fd=6))tcp TIME-WAIT 0 0 10.0.0.5:443 192.168.1.60:54321
- State:连接状态(LISTEN、ESTABLISHED、TIME-WAIT、SYN-SENT、CLOSING 等)
- Recv-Q / Send-Q:接收/发送队列长度。LISTEN 状态下 Send-Q 是最大监听队列长度。如果 ESTABLISHED 状态下 Send-Q 持续不为 0,说明对端接收有问题(背压)
- Local Address:Port:本地 IP 和端口
- Peer Address:Port:远端 IP 和端口(TIME_WAIT 状态会显示对方地址)
- Process:进程信息(进程名、PID、文件描述符)
排查场景一:端口占用
# 查看 80 端口被谁占用ss -tlnp | grep :80# 输出示例:# LISTEN 0 128 *:80 *:* users:(("nginx",pid=1234,fd=6),("nginx",pid=1235,fd=6))# 如果想看 PID 1234 的详细信息ls -la /proc/1234/fd | grep socket# 查看端口被占用情况(查看所有 LISTEN 端口,快速找到冲突)ss -tlnp | awk '{print $5}' | grep -E ':(80|443|8080)$' | sort | uniq -c
排查场景二:TIME_WAIT 堆积
短连接频繁的服务器(调用方是 PHP、Python 脚本等)容易出现大量 TIME_WAIT,导致可用端口耗尽(Linux 默认端口范围是 32768~60999,约 2.8 万个端口)。
# 查看当前 TIME_WAIT 连接数ss -s# 输出:# Total: 345 (kernel 456)# TCP: 12345 (est 8900, timewait 3200)# 查看 TIME_WAIT 连接来自哪些 IPss -tnp state time-wait | awk '{print $4}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10# 查看连接对端分布ss -tnp state time-wait | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10
解决方案:
**服务端开启 tcp_tw_reuse**(允许将 TIME_WAIT 状态的端口重用到新的出站连接):
# 临时生效echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse# 永久生效(/etc/sysctl.conf)net.ipv4.tcp_tw_reuse = 1
加载 sysctl.conf 变更(永久生效后需要执行此命令)
sysctl -p
调整源端口范围:
# 临时echo"32768 60999" > /proc/sys/net/ipv4/ip_local_port_range# 永久echo"net.ipv4.ip_local_port_range = 32768 60999" >> /etc/sysctl.conf
客户端使用连接池:不要每次请求都新建连接,改为复用连接,大幅减少 TIME_WAIT
确认是否是正常业务流量:如果 TIME_WAIT 来自外部 IP(而不是内部服务互调),需要确认这些连接是正常用户请求还是异常的重试行为
排查场景三:ESTABLISHED 异常高
# 查看每个 IP 的 ESTABLISHED 连接数ss -tnp state established | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20# 查看某个 IP 的详细连接ss -tnp state established dst 203.0.113.50# 查看可疑的外部连接(连接数异常多的陌生 IP)ss -tnp state established | awk '{print $5}' | grep -v "10\." | grep -v "192\.168\." | grep -v "172\.(1[6-9]|2[0-9]|3[0-1])\."
如果发现大量来自陌生 IP 的 ESTABLISHED 连接,可能是:
排查场景四:连接队列溢出(ListenOverflow)
# 查看 listen 队列溢出的统计(ss 输出中有_overflows 字段)ss -tlnp# 如果看到后面有 (1), (2) 这样的数字,表示 accept 队列溢出# LISTEN 状态的 Recv-Q 如果长时间接近 Send-Q,说明监听队列满了# 常见原因:并发请求超过 listen backlog 配置
风险提醒
ss 本身是高精度工具,查看其他进程的网络连接需要读 /proc/net/ 和 /proc/{pid}/fd/,本身对系统压力不大,但 ss -s(汇总统计)在极高并发(>10万连接)时会短暂阻塞- 端口冲突:如果两个进程都想绑定同一个端口,后启动的会失败。
ss -tlnp | grep :端口号 可以快速定位 tcp_tw_reuse 只对出站连接生效,对入站监听端口无效,不能解决服务器作为服务端时的问题tcp_tw_reuse 在 NAT 环境下可能导致连接问题,部分网络设备对 TCP timestamp 有依赖,启用前确认网络环境
验证方式
# 确认 ss 来自 iproute2ss --version# 确认内核参数生效cat /proc/sys/net/ipv4/tcp_tw_reusecat /proc/sys/net/ipv4/ip_local_port_range# 确认 netstat(如果装了)和 ss 结果一致(netstat 慢,ss 快)time ss -tunp > /dev/null# time netstat -tunp > /dev/null # 会慢很多# 确认 TCP 状态分布合理ss -s
命令6:tree —— 替代 ls -R,目录结构一目了然
问题背景
ls -R 输出的目录列表是扁平的,没有层级缩进,看起来非常费劲。当你在一个陌生的服务器上接手一个 Java 应用,发现配置文件分布在多层目录里,ls -la 根本看不出结构。tree 用树形结构展示目录,一眼看穿所有层级关系。
适用场景
常用命令
# 基础用法(只看目录结构)tree /etc/nginx# 显示所有文件(包括隐藏文件)tree -a /data# 只显示目录(不显示文件)tree -d /opt# 限制层级深度(最多显示3层)tree -L 3 /var/log# 目录优先显示tree --dirsfirst /data# 排除特定目录(适合排除 node_modules、.git 等大目录)tree -I "node_modules|.git|__pycache__|target" /data# 排除特定模式(排除所有 .log 文件)tree -I "*.log" /data# 显示文件大小tree -h /data# 显示文件完整路径tree -f /data# 结合 grep 过滤(只显示包含 nginx 的行)tree /etc/nginx | grep nginx# 生成 JSON 格式输出tree -J /etc/nginx# 生成 HTML 格式输出tree -H /var/www -T "Document Root" -o /tmp/dir.html
常用组合
# 快速定位 nginx 配置文件位置tree /etc/nginx# /etc/nginx/# ├── conf.d/# │ ├── default.conf# │ └── api.example.com.conf# ├── nginx.conf# └── mime.types# 快速了解项目结构(排除构建产物)tree -L 3 -I "node_modules|target|dist|.git" ~/project# 看看日志目录结构(各级别日志是否做了分离)tree -L 2 /var/log# 查看代码目录结构tree -L 4 --dirsfirst /home/app/codebase
在脚本中输出带缩进的效果
# 只想看前两层目录tree -L 2 -d /opt# 输出示例# /opt/# ├── app/# ├── backup/# ├── config/# ├── data/# ├── logs/# └── tools/
安装方式
# CentOS / RHELsudo yum install tree -y# Ubuntu / Debiansudo apt install tree -y# macOS(默认已安装)
风险提醒
tree 默认不跟随符号链接(只显示链接本身),如果需要显示链接指向的内容,用 -L 配合 tree -L 时注意层级不要过深(会扫描整个子树)- 对大目录扫描很慢:
tree / 会扫描整个根分区,在生产环境禁止对 / 做大范围 tree,可以先 df -h 确认分区再用 tree -L 2 / 按层级查看 - 输出重定向到文件时丢失颜色,用
tree -C 可以强制开启颜色输出
验证方式
# 确认安装tree --version# 快速验证目录结构(2层,排除大目录)tree -L 2 -I "node_modules|proc|sys" /# 在脚本中使用前先测试tree -L 2 /data 2>&1 | head -20
命令7:watch —— 替代重复执行,实时监控命令输出变化
问题背景
很多运维场景需要反复执行同一个命令来观察变化:比如等一个备份脚本执行完、等连接数降下来、等进程启动、等负载降下来。手动反复按 ↑ + Enter 太累,watch 就是来解决这个问题的——它以固定间隔重复执行命令,高亮显示输出变化的行,一眼看出哪些指标变了。
适用场景
- 监控进程数是否降下来(kill -9 之后等进程退出)
- 监控服务状态(等 systemctl start 完成)
常用命令
# 最基础用法:每2秒执行一次 ss -s(默认2秒)watch ss -s# 指定间隔(每1秒)watch -n 1 ss -s# 高亮显示变化的行(默认开启)watch -d ss -s# 高亮显示持续变化的值(累计变化)watch -d=cumulative ss -s# 监控多个命令(用单引号包裹)watch -n 2 'echo "=== CPU ===" && uptime && echo "=== Memory ===" && free -h'# 从文件读取命令(适合复杂命令)watch -n 5 "$(cat /tmp/check.sh)"# 监控特定日志文件的新增行(监控 nginx 日志增长)watch -n 1 'tail -n 5 /var/log/nginx/access.log'# 监控进程数变化watch -n 1 'ps aux | grep nginx | grep -v grep | wc -l'# 监控目录大小变化watch -n 5 'du -sh /var/log'# 监控端口状态watch -n 2 'ss -tlnp | grep :80'# 监控服务状态watch -n 1 'systemctl is-active nginx'
实战技巧
场景一:kill 一个进程后确认它真的退出了
# 先找到进程 PIDps aux | grep nginx# 监控进程退出(每0.5秒检查一次,进程消失后 watch 自动退出)watch -n 0.5 'ps -p 12345 -o pid=,comm='# 如果输出为空,说明进程已退出
场景二:等磁盘空间释放
# 删了大文件之后,watch 监控空间释放watch -n 2 'df -h /'# 同时监控是否有进程持有已删除文件的句柄(空间不释放的原因)watch -n 2 'lsof +L1'
场景三:观察 MySQL 连接数变化
watch -n 3 'mysql -e "SHOW STATUS LIKE \"Threads_connected\";" && mysql -e "SHOW PROCESSLIST;" | wc -l'
场景四:滚动查看日志(tail -f 的 watch 版本)
# tail -f 实时追加,watch 可以定时刷新整个命令输出watch -n 2 'tail -n 20 /var/log/nginx/error.log | grep -i error'
管道在 watch 中的使用
# watch 里的管道需要用单引号包裹,防止 shell 预处理watch -n 2 'ss -tnp state established | wc -l'# 想用 awk 等工具,要确保引号正确watch -n 2 "ss -tnp state established | awk '{print \$5}' | cut -d: -f1 | sort | uniq -c | sort -rn"# watch 里执行多条命令,用 && 分隔watch -n 3 'echo "=== 连接数 ==="; ss -s | grep TCP; echo "=== 磁盘 ==="; df -h /'
风险提醒
- 不要对高开销命令使用 watch。
watch -n 1 mysqldump 会每秒执行一次备份命令,如果备份本身要 5 分钟,等于同时跑了 5 个备份进程。在交互式排查时,先用 time 确认命令执行时间,再用 watch 设定合理间隔 watch 本身不记录历史变化。如果需要记录一段时间内的变化曲线,用 sar(sysstat)收集数据到文件,然后用 Graphite 或 Prometheus 绘图watch 里执行 exit 或 Ctrl+C 只退出 watch,不退出被监控的命令- watch 的时间精度有限。
-n 1 表示每秒执行一次,但实际间隔可能有几百毫秒的抖动,精确计时的场景不适合用 watch
验证方式
# 确认 watch 安装which watch# 快速测试 watch 是否正常(按 q 退出)watch -n 1 date# 确认 watch 的 tty 权限(某些受限环境可能无法使用)watch -n 1 'echo test' &sleep 2 && kill $! 2>/dev/null
命令8:xz / zstd / pigz —— 压缩工具组合拳
问题背景
日志归档、备份传输、镜像打包——这些场景都需要压缩。gzip 是最常见的压缩工具,但速度太慢,大文件压缩可能等几分钟甚至更久。xz 压缩比最高但最慢,zstd 和 pigz 则在压缩比和速度之间取得更好的平衡。每个工具有自己的适用场景,运维工程师需要知道在什么情况下选什么工具。
适用场景
各工具对比
常用命令
gzip(系统默认)
# 压缩(原地替换,file.txt 变成 file.txt.gz)gzip file.txt# 指定压缩级别(1 最快压缩比最低,9 最慢压缩比最高,默认6)gzip -9 file.txtgzip -1 file.txt # 快速压缩(备份场景)# 解压gunzip file.txt.gzgzip -d file.txt.gz# 保留原文件gzip -c file.txt > file.txt.gz# 查看压缩文件内容(不解压)zcat file.txt.gz | head# 压缩目录(需要先 tar)tar czf logs.tar.gz /var/log# 解压 tar.gztar xzf logs.tar.gz
xz(高压缩比,适合长期归档)
# 压缩(默认使用所有 CPU 核心)xz file.txt# 指定线程数(0 表示全部核心)xz -T 4 file.txt# 压缩级别(0 极快,-e 极限压缩,-6 默认)xz -e -9 file.txtxz -0 file.txt# 解压unxz file.txt.xzxz -d file.txt.xz# 保留原文件xz -c file.txt > file.txt.xz# 查看压缩文件信息xz -l file.txt.xz
zstd(快速压缩,推荐生产使用)
# 压缩(自动多线程,速度极快)zstd file.txt# 指定压缩级别(1-19,默认3)zstd -19 file.txt # 高压缩比zstd -1 file.txt # 快速# 保留原文件zstd -k file.txt # -k 保留原文件(默认会删)# 解压unzstd file.txt.zst# 查看压缩文件信息zstd -l file.txt.zst# 标准输入压缩(管道使用)cat /var/log/nginx/access.log | zstd -o access.log.zst# 解压到标准输出zstd -dc file.txt.zst | grep error# 压缩目录(需要先 tar)tar -I zstd -cf logs.tar.zst /var/log# 解压 tar.zsttar -I zstd -xf logs.tar.zst
pigz(gzip 兼容的多线程版)
# 安装后,用 pigz 替代 gzippigz file.txt# 指定线程数pigz -p 8 file.txt# 解压(pigz 自动识别 .gz 文件)unpigz file.txt.gz# tar + pigz 配合使用(压缩比同 gzip,速度更快)tar --use-compress-program=pigz -cf logs.tar.gz /var/log# 或者用管道tar cf - /var/log | pigz -p 8 > logs.tar.gz
实战:压缩一个 10GB 的日志目录
方法一:用 zstd(推荐,速度最快)
# 时间:约 1-2 分钟(视 CPU 性能)time tar -I zstd -cf /backup/logs-$(date +%Y%m%d).tar.zst /var/log# 压缩结果:10GB → 约 1.5GB(取决于日志内容重复度)
方法二:用 pigz(gzip 兼容,tar 一条搞定)
# 时间:约 3-5 分钟time tar --use-compress-program=pigz -cf /backup/logs-$(date +%Y%m%d).tar.gz /var/log
方法三:用 xz(最高压缩比,适合存储受限场景)
# 时间:可能超过 15 分钟,不建议大文件使用time tar -I xz -cf /backup/logs-$(date +%Y%m%d).tar.xz /var/log
方法四:用 gzip(系统默认,不需要安装)
# 时间:约 8-10 分钟(单线程)time tar czf /backup/logs-$(date +%Y%m%d).tar.gz /var/log
日志压缩的完整流程
# 第一步:确认日志目录大小du -sh /var/log# 第二步:找到可以清理的日志(超过 30 天的)find /var/log -name "*.log" -mtime +30 -type f# 第三步:创建压缩备份(先压缩再删除,双重保险)find /var/log -name "*.log" -mtime +30 -type f | \ xargs -I {} sh -c 'f="{}"; zstd -k "$f" && echo "Compressed: $f"'# 第四步:确认压缩后大小du -sh /var/log/*.zst# 第五步:确认压缩文件正常zstd -t /var/log/*.zst# 第六步:删除原文件(确认压缩包正常后)find /var/log -name "*.log" -mtime +30 -type f -exec rm {} \;# 第七步:清理压缩包(可选,备份到其他存储后)# rm /var/log/*.zst
风险提醒
- 压缩是 CPU 密集型操作,在生产机上对大文件做压缩会占用大量 CPU,影响业务响应时间。建议在业务低峰期做,或者用
nice -n 19 降低优先级 - 压缩比不是一切。xz 压缩比最高,但如果备份要在 30 分钟内完成,xz 实际不可用。选工具要看实际时间约束
- 保留原文件要用
-k 参数(zstd),其他工具默认会删除原文件 - **pigz 解压需要
unpigz**,不是 pigz -d,别搞混 - zstd 压缩格式还不是所有系统都原生支持,如果备份要在各种老系统上解压,用 gzip 或 pigz 更保险
验证方式
# 确认各工具安装which xz zstd pigz gzip bzip2# 验证压缩包完整性(不解压)xz -l file.txt.xzzstd -t file.txt.zstpigz -l file.txt.gz# 验证解压正常zstd -d -k file.txt.zst && diff file.txt file.txt.zst.dec
命令9:mtr —— 替代 traceroute + ping,网络延迟排查一条龙
问题背景
当用户反映"网站打开慢"或者"API 响应不稳定"时,ping 只能告诉你网络通不通、延迟多大;traceroute 能告诉你每一跳的路由路径和延迟,但两者是分开的命令,而且在不同网络环境下结果可能不一致。mtr(My Traceroute)把 ping 和 traceroute 合二为一,实时持续探测,显示每一跳的丢包率和延迟,用一条命令就能看清整条网络路径的健康状况。
适用场景
常用命令
# 最基础用法(交互界面)mtr 8.8.8.8# 非交互模式(只输出一次结果,适合脚本)mtr -n --report 8.8.8.8# 指定报告模式(-r 等价于 --report)mtr -r 8.8.8.8# 指定每次探测的间隔(默认 1 秒)mtr -i 2 8.8.8.8# 指定探测次数(配合 -r 使用)mtr -r -c 10 8.8.8.8# 显示 AS 号(自治系统号,了解路由经过哪些运营商)mtr -b 8.8.8.8# 输出 JSON 格式(供监控工具消费)mtr -j 8.8.8.8# 不用域名解析(加快速度)mtr -n 8.8.8.8# ICMP 模式(更接近 traceroute 默认行为)mtr -I 1 8.8.8.8# TCP SYN 模式(防火墙可能过滤 ICMP 时用)mtr -T -P 80 8.8.8.8
输出字段解读
Packets Pings Host Loss% Snt Last Avg Best Wrst StDev 1. 192.168.1.1 0.0% 10 1.2 1.5 1.0 2.1 0.3 2. 10.0.0.1 0.0% 10 5.4 5.8 5.2 6.3 0.4 3. 72.14.215.85 0.0% 10 12.3 15.1 11.8 22.4 3.2 4. 108.170.252.1 10.0% 10 18.7 20.1 17.2 28.3 4.1 5. 142.250.169.14 0.0% 10 22.1 23.4 21.5 25.2 1.2 6. 8.8.8.8 0.0% 10 25.3 26.1 24.8 27.5 0.8
- **Loss%**:该跳的丢包率(0.0% 最好,10% 以上需要关注)
- StDev:标准差(标准差越大说明延迟越不稳定,即抖动/Jitter 严重)
排查思路:读懂 mtr 报告
第一步:看整体丢包率
最后一跳(目标地址)的丢包率是最重要的指标。如果最后一跳是 0% 但用户反映慢,问题可能在服务端或应用层;如果最后一跳丢包严重,说明网络层有问题。
第二步:看哪一跳开始丢包
如果第 3 跳开始丢包 10%,但之后的跳都正常,很可能是那一跳的路由器有限速或 QoS 策略,而不是端到端的问题。但如果最后一跳丢包,问题就是真实存在的。
第三步:看延迟是否突然升高
如果中间某一跳的 Wrst(最差延迟)远高于 Avg,说明那一跳有偶尔的严重延迟(可能是拥塞、队列堆积或路由器过载)。如果每一跳的延迟都在线性增长,说明是物理距离导致的正常延迟。
第四步:看标准差(StDev)
标准差大说明延迟忽高忽低,即网络抖动(Jitter)严重。Jitter 会导致 TCP 重传、视频卡顿、实时通话质量下降。如果 StDev 超过 Avg 的 20%,需要关注。
实战:定位跨运营商访问慢
# 场景:用户反映从电信网络访问华东机房的 API 很慢# 在用户侧(或模拟用户侧网络)执行mtr -r -c 30 -b 114.114.114.114# 在服务器端执行反向探测(看服务端到用户网络的路径)mtr -r -c 30 -b 用户侧IP# 如果两边 mtr 都没有丢包,但延迟都高# 说明跨运营商骨干网带宽不足或高延迟# 解决方案:CDN 加速、多线 BGP 接入、就近接入# 如果某一跳突然丢包严重# 记录该跳 IP,查询 IP 归属(判断是哪个运营商/哪个节点)whois 72.14.215.85 | grep -E "NetName|OrgName|Country"
mtr 与 traceroute / ping 的区别
安装方式
# CentOS / RHELsudo yum install mtr -y# Ubuntu / Debiansudo apt install mtr -y# macOS(已自带)
风险提醒
- mtr 持续探测会发送大量 ICMP/TCP 包,在生产网络上长时间跑 mtr 可能触发防火墙告警或被安全设备标记,建议用
-c 指定有限次数,排查完即停 - mtr 显示的丢包可能是中间节点限速,而不是真实丢包。很多路由器对 ICMP 有速率限制,导致 mtr 报告的丢包率虚高。判断方法:看最后一跳的丢包率,如果最后一跳 0% 但中间有丢包,大概率是中间节点限速
- mtr 默认使用 ICMP,在严格防火墙环境下可能不通。用
-T 切换到 TCP 模式探测特定端口(如 80、443) - mtr 结果受路由不对称影响。去程和回程可能走不同路由,mtr 显示的是去程路径,回程路径需要从对端 mtr 才能看到
验证方式
# 确认安装mtr --version# 基础连通性测试mtr -r -c 5 8.8.8.8# 查看 mtr 是否支持 TCP 模式mtr --help | grep -i tcp
命令10:jq —— JSON 数据处理,让你的排查效率翻倍
问题背景
现代运维产生的数据越来越多是 JSON 格式的:Docker 和 Kubernetes 的 API 输出、Prometheus 的查询结果、日志聚合服务的返回、配置中心的数据、微服务之间的 RPC 调用——到处都是 JSON。grep 只能匹配固定字符串,awk 处理 JSON 容易出错,jq 是专门为 JSON 设计的命令行解析器,能像 SQL 查询一样提取、过滤、转换 JSON 数据。
适用场景
- 处理 Docker / Kubernetes API 返回的 JSON
- 解析 Prometheus 查询结果的 JSON 格式
常用命令
基础语法
# 美化输出(格式化 JSON)cat file.json | jq '.'# 提取顶级字段cat file.json | jq '.name'# 提取嵌套字段(用点号)cat file.json | jq '.metadata.name'# 提取深层嵌套cat file.json | jq '.spec.containers[0].image'# 提取数组所有元素cat file.json | jq '.items[]'# 提取数组指定元素cat file.json | jq '.items[0]'# 获取字段数量cat file.json | jq '.items | length'# 获取所有元素的某个字段cat file.json | jq '.items[].metadata.name'
过滤和条件
# 只保留满足条件的元素cat file.json | jq '.items[] | select(.status.phase == "Running")'# 统计满足条件的数量cat file.json | jq '[.items[] | select(.status.phase == "Running")] | length'# 多条件过滤cat file.json | jq '.items[] | select(.status.phase == "Running" and .spec.replicas > 1)'# 正则匹配cat file.json | jq '.items[] | select(.metadata.name | test("^nginx-"))'# 字段重命名cat file.json | jq '{name: .metadata.name, status: .status.phase}'
函数和运算
# 数学运算echo'{"cpu": 0.5}' | jq '.cpu * 100'# 输出 50# 字符串处理echo'{"name": "nginx"}' | jq '.name | ascii_upcase'# "NGINX"# 字符串模板(字符串插值)echo'{"name": "nginx", "replicas": 3}' | jq '"当前服务: \(.name), 副本数: \(.replicas)"'# 日期处理(当前时间戳)echo'{}' | jq 'now | strftime("%Y-%m-%d %H:%M:%S")'# 数组操作echo'{"pods": [1,2,3]}' | jq '.pods | length'# 3echo'{"items": [1,2,3]}' | jq '.items | add'# 6echo'{"items": [1,2,3]}' | jq '.items | min'# 1echo'{"items": [1,2,3]}' | jq '.items | max'# 3
Kubernetes 实战
# 获取所有 Running 状态的 Podkubectl get pods -o json | jq '.items[] | select(.status.phase == "Running") | .metadata.name'# 获取所有 Pod 的 name 和 namespacekubectl get pods -o json | jq '.items[] | {name: .metadata.name, ns: .metadata.namespace}'# 获取 Deployment 的 replicas 配置和实际可用数kubectl get deployment nginx -o json | \ jq '{desired: .spec.replicas, available: .status.availableReplicas}'# 获取所有节点的 CPU 和内存 allocatablekubectl get nodes -o json | jq '.items[] | {node: .metadata.name, cpu: .status.allocatable.cpu, memory: .status.allocatable.memory}'# 统计每个 namespace 的 Pod 数量kubectl get pods --all-namespaces -o json | \ jq '[.items[] | .metadata.namespace] | group_by(.) | map({namespace: .[0], count: length})'# 获取所有 Services 的 name 和 clusterIPkubectl get svc -o json | jq '.items[] | {name: .metadata.name, ip: .spec.clusterIP}'
Docker 实战
# 获取容器 ID 和镜像名docker ps -a --format '{{json .}}' | jq -r '.ID + " " + .Image'# 获取容器状态信息docker inspect $(docker ps -q) | jq '.[].State'# 获取所有容器的端口映射docker ps --format '{{json .}}' | jq -r 'select(.Ports != "") | .Ports'
Prometheus 查询结果处理
# Prometheus API 返回格式处理curl -s "http://localhost:9090/api/v1/query?query=up" | \ jq '.data.result[] | {instance: .metric.instance, value: .value[1]}'# 查看所有指标名称curl -s "http://localhost:9090/api/v1/label/__name__/values" | jq '.data[]'# 查看某个指标的所有标签组合curl -s "http://localhost:9090/api/v1/query?query=node_cpu_seconds_total" | \ jq '.data.result[].metric | {job: .job, instance: .instance, mode: .mode}'
日志文件中的 JSON
很多应用的日志是 JSON 格式输出的(JSON Log):
# 从 JSON 日志中提取 error 级别日志cat /var/log/app.json.log | jq -r 'select(.level == "error") | .message'# 提取最近 1 小时内的 error 日志cat /var/log/app.json.log | jq -r 'select(.level == "error" and .timestamp > "2026-05-15T10:00:00") | .message'# 统计每种 level 的日志数量cat /var/log/app.json.log | jq -r '.level' | sort | uniq -c | sort -rn# 从嵌套 JSON 中提取 trace IDcat /var/log/app.json.log | jq -r '.extra.trace_id // .traceId // empty'
配置文件验证
# 验证 JSON 配置文件语法jq empty /etc/app/config.json && echo"Valid JSON" || echo"Invalid JSON"# 从配置文件中读取值(替代 grep)jq '.database.host' /etc/app/config.jsonjq '.database.password' /etc/app/config.json # 提醒:不要在日志中输出密码
jq 的优势
- 零依赖:不需要 Python、Node.js,直接一个二进制文件
- 速度快:C 语言实现,处理大文件(几百 MB 的 JSON)也能跑
- 处处可用:Shell 脚本、Dockerfile 里的 entrypoint、Ansible 的 when 条件
安装方式
# CentOS / RHEL 7(EPEL)sudo yum install jq -y# Ubuntu / Debiansudo apt install jq -y# macOSbrew install jq# 直接下载二进制(所有 Linux 发行版)curl -sL https://github.com/jqlang/jq/releases/download/jq-1.7/jq-linux64 -o /usr/local/bin/jq && chmod +x /usr/local/bin/jq
风险提醒
jq 对输入格式要求严格:如果 JSON 不完整或不规范(缺引号、多余逗号),jq 会报错退出,不会自动容错。如果日志中有非 JSON 行(如 nginx 的 accesslog 混合了 JSON 和普通文本),先 grep '{' | jq 过滤- 密码和敏感信息:在脚本中用
jq 提取配置文件的密码字段后,不要 echo 到标准输出或日志文件 - 数组索引越界:
jq '.items[99]' 如果数组不足 100 个元素会返回 null,不会报错,注意用 select(. != null) 过滤 jq 的默认输出格式:数组和对象默认会格式化打印,加上 -r(--raw-output)输出原始字符串,否则会带引号
验证方式
# 确认安装jq --version# 验证 jq 可以正确解析echo'{"name": "test", "value": 123}' | jq .# 确认 jq 处理大文件没问题time cat huge.json | jq '.' > /dev/null# 确认 jq 处理带换行符的 JSON 数组echo -e '{"items": [{"id": 1}, {"id": 2}]}' | jq '.items[].id'
总结:建立你自己的命令工具箱
工具选型原则
本文整理了 10 个实用命令,每个都能在特定场景下大幅提升排查效率。但工具不是目的,快速解决问题才是目的。不要为了用工具而用工具,而是:
- 先有场景,再找工具:先清楚自己在哪种场景下慢,然后去学对应的工具
- 工具要会用,还要用熟:
htop 的快捷键很多,但日常排查只需要 M(按内存排序)、P(按 CPU 排序)、k(杀掉进程)三个,记住常用的就行 - 组合优于单一:很多问题需要多个命令配合,比如
ss 定位连接数 + journalctl 查日志 + ncdu 定位磁盘,三者组合才能定位根因
工具与场景对照表
| |
|---|
| htop |
| glances |
| ncdu |
| journalctl |
| ss |
| tree |
| watch |
| zstd |
| mtr |
| jq |
持续积累
每次故障排查完后,花 5 分钟复盘:这次用了什么命令?有没有更好的工具?把这个命令记到自己的笔记本或脚本库里。积累几个月,你就有了自己的"运维工具箱",遇到问题不用临时查文档,直接上手。
进阶方向
- 监控体系:学会用 Prometheus + Grafana 把这些命令的输出变成图表和告警
- 自动化:把这些命令组合写到 Shell 或 Python 脚本里,一键输出诊断报告
- 输出格式化:用
jq + awk + sed 组合,把原始命令输出变成易读的摘要表格 - 日志聚合:单机
journalctl 够用,但多机场景要上 ELK / Loki / Grafana Alloy
工具会了,效率提升了,故障定位自然就快了。祝大家少加班,少熬夜,服务器稳如泰山。