Ubuntu运维日常监控的核心不是装一堆工具然后看图表,而是要搞清楚三件事:内核参数当前状态是否合理、进程行为是否异常、资源瓶颈到底卡在哪里。具体来说,你需要关注CPU调度、内存回收策略、I/O调度算法、网络连接跟踪、进程调度延迟这些内核层面的指标,同时配合top、htop、vmstat、iostat、sar、perf、bpftrace等工具对进程级行为做深度分析。下面我把这套体系从头到尾拆开讲,每一块都给你具体命令和调优思路。

一、内核参数监控:从sysctl到/proc的全面摸底

Ubuntu的内核参数默认配置是通用型的,生产环境几乎一定要调。第一步就是把当前所有内核参数导出来看一遍:

sysctl -a > /tmp/kernel_params_before.txt

重点关注以下几类参数。第一类是内存管理相关:vm.swappiness默认值是60,意味着内核比较积极地把内存页换到swap。如果你的服务器跑的是数据库或者Java应用,建议调到10甚至1:

sysctl vm.swappiness=10
echo "vm.swappiness=10" >> /etc/sysctl.conf

第二类是网络相关:net.core.somaxconn默认128,高并发场景下连接队列容易满,建议调到65535;net.ipv4.tcp_max_syn_backlog默认128,同样需要拉高到65535;net.ipv4.tcp_tw_reuse设为1可以快速回收TIME_WAIT连接:

sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
sysctl -w net.ipv4.tcp_tw_reuse=1

第三类是文件描述符和进程限制:fs.file-max决定系统级别最大打开文件数,建议设为1000000以上;fs.nr_open是单个进程的文件描述符上限,默认1048576通常够用但要确认:

sysctl -w fs.file-max=2097152
sysctl -w fs.nr_open=1048576

这些参数不是改一次就完事,要定期用sysctl -a对比,防止被其他脚本或者内核升级覆盖。同时建议用/etc/sysctl.d/目录下的独立配置文件管理,方便版本控制和审计。

二、CPU监控与进程行为分析:不只是看使用率

很多人用top只看CPU%列,这远远不够。你要关注的是负载均衡(Load Average)、上下文切换(Context Switch)、进程调度延迟(Scheduling Latency)和CPU窃取(Steal Time)。vmstat 1可以实时看到这些:

vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 8392432 245760 4521344    0    0     0     0  234  567 12  3 85  0  0

其中cs列是每秒上下文切换次数,如果持续超过50000就要警惕,说明进程间竞争激烈。r列是运行队列长度,超过CPU核数就意味着有进程在排队。us+sy超过80%说明CPU已经比较紧张,需要进一步用pidstat定位具体进程:

pidstat -u 1

更硬核的做法是用perf做采样分析,直接看内核态和用户态的热点函数:

perf top -g

这个命令会实时显示哪些内核函数占用CPU最多,比如你发现ext4_file_read_iter或者tcp_v4_rcv占比很高,就知道I/O或网络是瓶颈。对于进程行为异常,比如某个进程CPU突然飙高但top里看不到明显原因,可以用strace跟踪系统调用:

strace -p <PID> -c -f

-c参数会统计每个系统调用的耗时和次数,-f会跟踪子进程。如果发现大量futex或者epoll_wait调用,说明进程在等锁或者网络事件,需要从应用层排查。

三、内存监控:从free到slab的全链路追踪

free -h只能看到大致的内存使用情况,但真正的问题往往藏在细节里。你要同时看几个维度:可用内存(available)、缓冲区(buffers)、缓存(cache)、Slab占用、HugePages使用情况。用slabtop可以看到内核对象缓存的分布:

slabtop -o

如果发现dentry或者inode_cache占用异常高,可能是文件系统元数据过多,需要清理或者调整挂载参数。另外,/proc/meminfo里的SReclaimable和SUnreclaim两项要重点关注,前者是可以回收的Slab,后者是不能回收的,如果SUnreclaim持续增长说明有内存泄漏嫌疑。

对于Java、Python这类有自己内存管理的应用,还要监控/proc/<PID>/status里的VmRSS、VmSize、VmSwap,以及通过smaps看具体内存段的映射:

cat /proc/<PID>/smaps_rollup

如果某个进程的Anonymous内存段异常膨胀,基本可以判断是应用层内存泄漏,需要配合jmap、pympler或者valgrind做进一步定位。

四、磁盘I/O监控:iostat与iotop的组合拳

磁盘是最容易被忽视但最容易出问题的环节。iostat -xz 1可以看到每个磁盘的util、await、r/s、w/s、rMB/s、wMB/s。util接近100%说明磁盘已经饱和,await超过20ms对于SSD来说偏高,超过50ms对于HDD来说基本不可用:

iostat -xz 1
Device         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     5.23    3.45   12.34   138.00   493.60    79.42     0.85    53.78    4.23   64.12   3.12  17.56

iotop -o可以看到具体哪个进程在吃I/O,配合--accumulated参数可以看到累计I/O量。如果发现某个进程持续大量写操作但你不知道原因,用lsof看它打开了哪些文件:

lsof -p <PID> | grep -v "^COMMAND"

对于I/O调度算法,Ubuntu默认用mq-deadline或者none(对于NVMe),可以用cat /sys/block/sda/queue/scheduler查看和切换。数据库场景推荐用none或noop减少调度开销,通用场景用mq-deadline比较均衡。

五、网络监控:从ss到tcpdump的多层透视

网络问题排查要分三层:连接状态、流量统计、包级分析。ss -s可以快速看到连接数汇总,包括ESTAB、TIME-WAIT、CLOSE-WAIT的数量:

ss -s
Total: 1245
TCP:   890 (estab 45, closed 312, orphaned 0, synrecv 0, timewait 310/0), ports 0

Transport Total     IP        IPv6
*         890       -         -
RAW       0         0         0
UDP       12        8         4
TCP       878       870       8
INET      890       878       12
FRAG      0         0         0

TIME-WAIT过多说明连接回收慢,除了前面提到的tcp_tw_reuse,还要检查tcp_fin_timeout是否合理,默认60秒可以降到15秒。CLOSE-WAIT过多说明应用层没有正确关闭连接,这是代码问题。用iftop或nload看实时带宽,用nethogs看每个进程的网络用量。

真遇到丢包或者延迟问题,tcpdump是终极武器:

tcpdump -i eth0 -nn port 80 -c 1000

抓包后用wireshark分析,或者直接用tcpdump的统计模式:

tcpdump -i eth0 -nn -c 5000 | awk '{print $1}' | sort | uniq -c | sort -rn

这条命令会统计每个源IP的包数量,快速定位异常流量来源。

六、进程行为深度分析:perf、bpftrace与eBPF的实战

传统工具能看到"什么进程占用了什么资源",但看不到"为什么"。这时候需要eBPF工具链。bpftrace是目前最好用的动态追踪工具,可以在不重启服务的情况下内核级观测。比如你想看哪些进程打开了超过1000个文件:

bpftrace -e 'tracepoint:syscalls:sys_enter_openat { @files[comm] = count(); }'

想看进程的CPU调度延迟分布:

bpftrace -e 'tracepoint:sched:sched_switch { @us[comm] = hist(nsecs); }'

perf record + perf report可以做离线采样分析,适合抓一段时间的数据再慢慢看:

perf record -a -g -p <PID> -- sleep 30
perf report

这些工具组合起来,基本可以覆盖从宏观到微观的所有进程行为分析需求。关键是要建立基线,正常状态下跑一遍这些命令,把输出存下来,出问题时对比就能快速定位。

七、自动化监控与告警体系搭建

手动跑命令不是长久之计,必须上自动化。Prometheus + node_exporter是目前最主流的方案,node_exporter能暴露几百个指标,覆盖CPU、内存、磁盘、网络、文件系统、内核参数等方方面面。配合Grafana做可视化,设置合理的告警阈值。关键指标的告警建议:CPU使用率持续5分钟超过80%告警、可用内存低于10%告警、磁盘util超过85%告警、TIME-WAIT超过5000告警、负载超过CPU核数2倍告警。

另外建议写几个自定义脚本做补充监控,比如用cron每5分钟跑一次vmstat和iostat,异常时自动发通知。把所有监控数据和调优记录归档,形成运维知识库,下次遇到类似问题直接查历史方案,效率会高很多。

总结一下,Ubuntu运维监控不是单一工具的事,而是一套从内核参数到进程行为、从实时监控到离线分析的完整体系。内核参数调优解决的是"地基"问题,进程行为分析解决的是"楼上哪户在漏水"的问题,两者缺一不可。把这套东西跑通了,你的服务器稳定性会上一个大台阶。