Ubuntu服务器出现异常时,最直接的排查入口不是翻日志,而是先看进程。进程是系统资源的最小调度单位,CPU飙升、内存泄漏、磁盘IO打满、网络连接异常,最终都会体现在某个或某几个进程的状态上。很多运维人员习惯一上来就重启服务,结果把现场破坏了,问题反复出现却找不到根因。正确的做法是先定位到具体进程,再分析它的资源占用、状态变化和调用关系,最后才决定是否重启或调整配置。
在Ubuntu上做进程监控,最基础也最常用的命令是ps。但很多人只会用ps aux这一条,看到一堆输出就不知道下一步该看什么。实际上ps的参数组合可以精确筛选出你需要的信息。比如要查看某个服务的进程树,用ps -ef --forest配合grep就能看到父子进程关系。要按CPU占用排序,用ps aux --sort=-%cpu,按内存排序则把字段换成%mem。排查异常时建议先按CPU和内存各排一次序,把排在最前面的几个进程PID记下来,这些就是当前最可疑的对象。
用top和htop做实时动态监控ps拿到的是某一时刻的快照,但很多异常是间歇性的,比如某个进程每隔几分钟就突然占用大量CPU,然后又恢复正常。这时候需要实时监控工具。Ubuntu默认自带top,输入top后按P键按CPU排序,按M键按内存排序,按c键显示完整命令行。top的缺点是界面简陋,信息密度不够。建议安装htop,它支持鼠标点击、进程树视图、直接给进程发信号,还能用F5切换树形结构,非常直观。htop里重点关注LOAD AVERAGE三个数值,如果第一个数值持续大于CPU核心数,说明系统已经过载,需要进一步定位是哪个进程在消耗资源。
定位CPU异常消耗的进程CPU异常通常表现为某个进程持续占用一个或多个核心的接近100%。先用top或htop找到PID,然后需要确认这个进程到底在干什么。执行cat /proc/PID/status可以查看进程的详细状态,包括线程数、内存占用、运行状态等。执行cat /proc/PID/stat可以拿到进程的CPU时间片信息,其中第14和第15个字段分别是用户态和内核态消耗的CPU时间。如果内核态时间占比很高,说明进程在做大量的系统调用,可能是IO操作或者网络操作频繁。接下来用strace -p PID跟踪进程的系统调用,看看它卡在哪个调用上。注意strace对性能有影响,跟踪时间不要过长,拿到关键信息就退出。
内存泄漏和内存异常排查内存问题比CPU问题更隐蔽,因为内存泄漏是一个缓慢累积的过程,可能几天甚至几周才会触发OOM。排查时先用free -h查看整体内存使用情况,注意available这一列才是真正可用的内存。如果available很小但used很大,说明内存确实紧张。然后用ps aux --sort=-%mem找出占用内存最多的进程。对于可疑进程,查看/proc/PID/smaps文件,这个文件详细列出了进程的各个内存映射区域,包括堆、栈、共享库、匿名映射等。重点关注Rss和Pss两个指标,Rss是进程实际占用的物理内存,Pss是按比例分摊共享内存后的值。如果某个进程的Rss持续增长且不回落,基本可以判断存在内存泄漏。还可以用pmap -x PID查看更简洁的内存映射汇总。
磁盘IO瓶颈与进程关联分析磁盘IO打满会导致整个系统响应变慢,但很多人只看到iowait高,却不知道是哪个进程在疯狂读写磁盘。Ubuntu上可以用iotop命令实时查看每个进程的IO情况,包括读写速度和IO占比。如果系统没有安装iotop,先用apt install iotop安装。运行iotop后按o键只显示有IO活动的进程,按左右方向键切换排序字段。找到IO占用高的进程后,用lsof -p PID查看它打开了哪些文件,再用ls -lh确认文件大小和修改时间。很多情况下,异常IO是日志文件无限增长或者数据库频繁刷盘导致的。如果是日志问题,需要检查日志轮转配置是否失效;如果是数据库刷盘,需要检查缓存配置和查询效率。
网络连接异常的进程级排查服务器出现网络异常时,可能是某个进程占用了大量带宽,也可能是进程建立了过多连接导致端口耗尽。先用ss -s查看整体网络连接统计,再用ss -tunap查看所有TCP和UDP连接及其对应的进程。ss比netstat更快,输出也更清晰。重点关注State列中的TIME_WAIT和CLOSE_WAIT状态。TIME_WAIT过多通常是短连接频繁建立和断开导致的,可以通过调整内核参数net.ipv4.tcp_tw_reuse来缓解。CLOSE_WAIT过多则是应用程序没有正确关闭连接,属于代码层面的问题。用ss -tunap | grep CLOSE_WAIT找出具体是哪个进程和哪个端口,然后检查该服务的连接处理逻辑。如果某个进程的Recv-Q或Send-Q持续不为零,说明数据在缓冲区堆积,可能是处理速度跟不上网络流量。
进程状态异常与僵尸进程处理用ps aux查看进程时,STAT列会显示进程的状态。常见的状态包括R(运行中)、S(睡眠)、D(不可中断睡眠)、Z(僵尸)、T(停止)。D状态进程通常是在等待IO操作完成,如果大量进程长期处于D状态,说明磁盘或网络IO存在严重瓶颈。Z状态是僵尸进程,表示进程已经结束但父进程没有回收它的资源。少量僵尸进程影响不大,但如果数量持续增长,说明父进程存在bug。用ps aux | grep Z找出僵尸进程,再用ps -o ppid= -p PID找到它的父进程,然后检查父进程的代码逻辑。如果父进程是系统服务,可以考虑重启该服务来清理僵尸进程。
用systemd管理服务进程状态Ubuntu从16.04开始全面采用systemd作为初始化系统,服务进程都由systemd管理。排查服务异常时,首先要看systemctl status 服务名,它会显示服务的运行状态、最近几条日志、主进程PID等信息。如果服务启动失败,用journalctl -u 服务名 -n 50查看最近的日志,journalctl会记录服务的标准输出和标准错误,这是排查启动失败最直接的线索。systemd还提供了资源限制功能,可以用systemctl show 服务名查看该服务的CPU、内存、任务数等限制。如果某个服务频繁被OOM Killer杀掉,可以在服务单元文件中设置MemoryLimit来限制其最大内存使用,避免影响整个系统。
进程监控的自动化与告警机制人工盯着终端看进程状态不现实,生产环境需要自动化监控和告警。Ubuntu上可以部署Prometheus配合node_exporter采集进程级指标,再用Grafana做可视化展示。node_exporter会自动采集所有进程的CPU、内存、IO等指标,Prometheus负责存储和查询,Grafana负责展示和告警。对于关键进程,可以配置告警规则,比如某个进程的CPU使用率连续5分钟超过80%就发送通知。如果不想部署整套监控系统,也可以用简单的脚本配合cron实现基础监控。比如写一个shell脚本,每分钟检查一次关键进程是否存在,不存在就发送邮件或调用Webhook通知。脚本内容如下:
#!/bin/bash
PROCESS_NAME="nginx"
if ! pgrep -x "$PROCESS_NAME" > /dev/null; then
echo "进程 $PROCESS_NAME 已停止运行" | mail -s "进程告警" admin@example.com
fi
把这个脚本加入crontab,每分钟执行一次,就能实现最基本的进程存活监控。但这种方式只能检测进程是否存在,无法检测进程的资源占用异常。更完善的方案是结合ps命令提取关键指标,超过阈值就触发告警。
进程排查的完整思路总结Ubuntu服务器进程异常排查的核心思路是先宏观后微观。先用uptime看系统负载,用free看内存,用df看磁盘,用ss看网络,快速判断异常类型。然后根据异常类型选择合适的工具定位到具体进程,比如CPU高就用top或htop,内存高就用ps排序,IO高就用iotop,网络异常就用ss。定位到进程后,深入分析进程的内部状态,用/proc文件系统查看详细信息,用strace跟踪系统调用,用lsof查看文件句柄。最后根据分析结果决定处理方式,是调整配置、修复代码还是重启服务。整个过程中要保留现场数据,不要一上来就重启,否则问题会反复出现,排查成本反而更高。
进程监控不是一次性的排查动作,而是一个持续的过程。生产环境应该建立常态化的监控体系,把进程级指标纳入日常巡检范围。同时要熟悉Ubuntu系统自带的排查工具,这些工具不需要额外安装,在紧急情况下能快速定位问题。掌握了这些方法和思路,面对大多数Ubuntu服务器进程异常都能做到心中有数,不至于手忙脚乱。
