Linux小课堂: 深入解析 top、htop、glances 及进程终止机制
动态进程监控工具:top
命令详解
在 Linux 系统中,进程是资源调度的基本单位,掌握其运行状态对于系统性能调优至关重要。虽然上一节介绍了 ps
命令用于获取某一时刻的进程快照,但其本质是静态输出,无法反映系统的实时变化
为实现对进程活动的持续观察,必须使用动态监控工具 —— top
。执行:
top
即可进入一个实时刷新、交互式界面的进程监控视图。该命令每 3 秒自动更新一次,默认按 CPU 使用率(%CPU)从高到低排序,确保最消耗资源的进程始终位于列表顶端。
1 ) top
输出结构解析
top
的输出分为多个逻辑区域,每一部分均提供关键系统信息:
-
第一行:系统概览
- 显示当前时间、系统已运行时长(uptime)、用户登录数量及系统负载(load average)。例如:
此处负载值分别代表过去 1 分钟、5 分钟、15 分钟的平均任务数。top - 17:21:26 up 31 min, 2 users, load average: 0.15, 0.10, 0.05
- 显示当前时间、系统已运行时长(uptime)、用户登录数量及系统负载(load average)。例如:
-
第二行:任务统计
- 统计总任务数(Tasks)、运行中(running)、休眠中(sleeping)、停止(stopped)和僵死进程(zombie)的数量
Tasks: 212 total, 3 running, 209 sleeping, 0 stopped, 1 zombie
- 其中,“zombie”即僵死进程,表示已终止但未被父进程回收的进程,长期存在可能引发资源泄漏
- 统计总任务数(Tasks)、运行中(running)、休眠中(sleeping)、停止(stopped)和僵死进程(zombie)的数量
-
第三至第四行:CPU 与内存使用情况
%Cpu(s): 2.0 us, 1.5 sy, 0.0 ni, 96.2 id, 0.3 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 8000.0 total, 2000.0 free, 4500.0 used, 1500.0 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 3000.0 avail Mem
- CPU 使用分布:包括用户态(us)、系统态(sy)、空闲(id)、等待 I/O(wa)等百分比。
- 物理内存(Mem)与交换分区(Swap):以 KB 或 MB 为单位显示总量、已用、空闲及缓存使用量。
-
第五行起:进程列表主体
- 每行对应一个进程,主要字段包括:
- PID:进程标识符(Process ID)
- USER:启动该进程的用户
- %CPU:当前 CPU 占用率
- %MEM:内存占用百分比
- VSZ / RSS:虚拟内存大小 / 实际常驻内存
- TTY:关联终端设备
- STAT:进程状态(R=运行, S=睡眠, Z=僵尸等)
- START / TIME+:启动时间与累计 CPU 时间
- COMMAND:启动命令名
- 每行对应一个进程,主要字段包括:
注意:top
不会显示所有进程,仅呈现适合终端页面容量的部分结果,可通过滚动或交互操作查看更多。
top
的交互式控制功能
top
是高度可交互的,支持多种键盘快捷键进行动态调整:
快捷键 | 功能说明 |
---|---|
q | 退出 top 界面 |
h | 显示帮助文档,列出所有可用命令 |
b | 高亮显示当前选中的进程(可重复按下切换) |
f / F | 添加或删除显示列(如增加 PPID 、NI 等高级字段) |
o / O | 调整列的显示顺序 |
u | 按用户名过滤进程(输入用户名后仅显示其所属进程) |
k | 发送信号终止指定 PID 的进程(默认发送 SIGTERM ) |
s | 修改刷新间隔时间(单位:秒),提升响应频率或降低开销 |
< / > | 调整排序依据字段(左移/右移列) |
Shift + F | 设置排序字段(Sort field selection) |
示例:
- 若系统响应迟缓,可立即运行
top
查看前几项高 CPU 占用进程,并通过 k → 输入 PID → 回车 结束异常进程 - 若怀疑系统响应缓慢,可通过
top
查看%CPU
或%MEM
最高进程,结合k
输入其 PID 主动终止异常进程 top
实际读取/proc
文件系统中的虚拟文件获取进程数据,如/proc/<pid>/stat
、/proc/meminfo
等,具备极低开销和高精度特性
此外,通过 f
可添加更多维度信息列(如 IO-wait、nice 值等),增强诊断能力
增强型监控工具:glances
与 htop
尽管 top
功能强大,现代运维更倾向于使用功能更全、可视化更强的替代工具
1 ) 安装并使用 glances
glances
是基于 Python 的跨平台系统监控工具,集成度高,提供网络、磁盘 I/O、传感器等多项指标。
安装步骤(以 CentOS/RHEL 为例):
安装 EPEL 扩展源(含 glances 依赖)
sudo yum install -y epel-release安装 Python 开发包(必要组件)
sudo yum install -y python3-pip python3-devel 使用 pip 安装 glances
sudo pip3 install glances[all]
注:[all]
表示安装所有插件模块(如 Web UI、MQTT 支持等)
若需支持 Web 模式,额外安装 $ sudo pip3 install 'glances[web]'
启动与特性展示:
glances
界面包含以下核心模块:
- 主机名与公网 IP 地址
- Uptime:运行时间
- CPU 使用率曲线图(区分用户/系统/等待)
- 内存与 Swap 使用详情
- Load Average 负载均值(1/5/15分钟)
- Network Interfaces:各网卡收发速率
- Disk I/O:读写吞吐量 性能统计
- Process Count & Top Processes
- Sensors Temperature(如有硬件支持)
- 文件系统挂载点使用率
- 当前任务数与活跃进程数
支持 Web 模式运行(远程访问):
glances -w # 启动 Web Server,默认端口 61208
浏览器访问:http://<server_ip>:61208
退出方式仍为按 q
键
2 ) 安装并使用 htop
htop
是 top
的现代化增强版本,具备彩色界面、鼠标支持、树状视图等功能。
安装方式:
CentOS/RHEL
sudo yum install -y htopUbuntu/Debian
sudo apt-get install -y htop
启动命令:
htop
核心快捷键(底部菜单提示):
键位 | 功能描述 |
---|---|
F1 | Help 帮助文档 |
F2 | Setup 设置界面(可自定义颜色、显示项) |
F3 | Search 搜索进程 |
F4 | Filter 过滤显示特定名称的进程 |
F5 | Tree 以父子关系树状展开进程 |
F6 | Sort By 排序列选择(支持按 MEM、TIME+、PID 等排序) |
F9 | Kill 向选定进程发送信号(推荐使用此方式而非手动 kill) |
F10 | Quit 退出 htop |
q | 同 F10,退出程序 |
颜色编码:不同状态进程以颜色区分(绿色=运行,蓝色=休眠,红色=高优先级)
示例:按下 F5
可清晰查看某服务启动的多个子进程层级结构;使用 F6
切换至按内存排序,迅速发现内存泄漏进程
提示:相比 top
,htop
更直观且支持垂直/水平滚动查看全部进程,无需翻页
进程终止机制:kill
、killall
与强制手段
当发现异常进程占用过多资源时,需及时终止
Linux 提供多层级控制策略
1 ) kill
命令:精准终止单个进程
语法格式:
kill [signal] <PID>
<PID>
:目标进程的唯一编号,可通过ps aux | grep <name>
或top
获取。[signal]
:可选参数,默认为SIGTERM
(信号 15),表示“友好请求退出”。- 常用信号:
SIGTERM
(15):优雅终止,允许进程清理资源后再退出(默认)SIGKILL
(9):强制终止,立即杀死进程,不可被捕获或忽略
示例:
kill 8461 # 向 PID 8461 发送 SIGTERM
kill -9 7291 # 强制杀死 PID 7291(使用 SIGKILL)
SIGKILL(-9)不可被捕获或忽略,适用于无响应进程,但可能导致数据丢失,请慎用。
若进程由 root 启动而当前为普通用户,则需提权:
sudo kill -9 15529
同时结束多个进程:
kill 8461 8561 1706
获取 PID 方法:
ps aux | grep find # 查找 find 相关进程
top # 观察动态 PID 分布
pgrep find # 直接获取 find 进程 PID 列表
权限说明:普通用户只能终止自身拥有的进程;终止 root 进程需使用 sudo
提权
sudo kill 15529
2 ) killall
命令:批量终止同名进程
相比 kill
需要手动查找 PID,killall
支持直接通过程序名称终止所有匹配进程
当同一程序启动多个实例(如多个 find
查找任务),逐个 kill 效率低下。此时应使用:
语法:
killall [options] <process_name>
假设用户 oscar
在多个终端中并发运行 find
命令查找文件:
find /home/oscar -name "*.log"
此时可用以下命令一键清除所有 find
进程:
killall find
亦可指定信号:
killall -9 find # 强制终止所有 find 进程
结合权限控制:
查看 oscar 用户运行的所有 find 进程
ps -u oscar | grep find 批量终止(无需逐个获取 PID)
killall -u oscar find
重要提示:killall
行为受系统实现影响,在某些 Unix 系统上含义不同,建议在脚本中谨慎使用
技术细节:killall
实际上匹配的是 进程名(comm 字段),而非完整命令路径。因此建议配合 ps
验证
3 )Ctrl+C:中断前台终端进程
组合键 Ctrl+C
向当前终端中运行的前台进程发送 SIGINT(Signal Interrupt) 信号,默认行为是终止程序
注意:此操作仅作用于终端关联的前台进程组,无法影响后台守护进程或其它会话中的进程
// 示例:Node.js 服务器监听时可通过 Ctrl+C 终止
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';async function bootstrap() {const app = await NestFactory.create(AppModule);await app.listen(3000);
}
bootstrap().catch(err => {console.error('Server failed to start:', err);
});
终端运行上述 NestJS 应用后,按 Ctrl+C
将触发退出流程
系统级操作:关机与重启命令详解
完成进程管理后,进一步学习如何安全地关闭或重启整个系统。
1 ) shutdown
:最安全的关机方式
shutdown
是底层统一调用接口,halt
、reboot
、poweroff
均可能最终调用它
该命令允许设定延迟、广播通知、取消操作,是生产环境首选
sudo shutdown # 默认 1 分钟后关机
sudo shutdown now # 立即关机
sudo shutdown +5 # 5 分钟后关机
sudo shutdown 23:30 # 指定时间关机
sudo shutdown -r +10 # 10 分钟后重启
取消已计划的关机:
sudo shutdown -c
底层原理:halt
、reboot
、poweroff
均由 shutdown
调用,确保优雅停机流程(同步文件系统、通知服务等)
基本语法:
shutdown [OPTIONS] [TIME] [MESSAGE]
常见用法:
立即关机
sudo shutdown now10 分钟后重启
sudo shutdown -r +10 "System will reboot for maintenance."取消已计划的关机
sudo shutdown -c
参数说明:
-r
:重启-h
:停机(halt)-c
:取消待执行的 shutdown 任务now
或+0
:立即执行"message"
:广播通知所有登录用户
查阅手册:
man shutdown
可进一步探索定时关机、单用户模式切换等功能
2 ) reboot
与 poweroff
:直接控制系统电源
sudo reboot # 重启系统
sudo poweroff # 关闭系统
注意权限差异:
reboot
和halt
通常需要 root 权限reboot
同样支持普通用户调用(依赖权限策略),触发完整重启流程
poweroff
在多数发行版中允许普通用户执行(受限于 polkit 规则)
3 ) 组合键 Ctrl+C
:中断前台终端进程
这是最常用的即时中断方式,作用于当前终端正在执行的前台进程
top # 运行中...
按下 Ctrl+C
输出:^C
top 进程被 SIGINT 信号终止
区别理解:
Ctrl+C
→ 发送SIGINT
,仅影响终端前台进程kill
→ 发送指定信号,可作用于任意后台进程- 图形界面中
Ctrl+C/V
为复制粘贴;终端中需使用Ctrl+Shift+C/V
NestJS 中模拟进程监控逻辑(TypeScript)
1 )方案1
虽然 Node.js 应用本身不直接管理 OS 进程,但在开发系统监控类服务时,可通过调用 shell 命令实现集成
示例:使用 NestJS 创建一个 /system/processes
接口返回 top
数据
// src/system/system.service.ts
import { Injectable } from '@nestjs/common';
import { exec } from 'child_process';
import { promisify } from 'util';const execAsync = promisify(exec);@Injectable()
export class SystemService {async getTopProcesses(): Promise<string> {try {const { stdout } = await execAsync('top -b -n 1 | head -20');return stdout;} catch (error) {throw new Error(`Failed to retrieve top processes: ${error.message}`);}}async killProcess(pid: number): Promise<string> {try {await execAsync(`kill ${pid}`);return `Process ${pid} sent SIGTERM signal.`;} catch (error) {try {await execAsync(`sudo kill ${pid}`); // fallback with sudoreturn `Process ${pid} killed with sudo.`;} catch (sudoError) {throw new Error(`Cannot kill process ${pid}: ${sudoError.message}`);}}}async forceKillProcess(pid: number): Promise<string> {try {await execAsync(`kill -9 ${pid}`);return `Process ${pid} was force-killed with SIGKILL.`;} catch (error) {throw new Error(`Force kill failed for PID ${pid}: ${error.message}`);}}async getSystemUptime(): Promise<string> {const { stdout } = await execAsync('uptime');return stdout.trim();}
}
// src/system/system.controller.ts
import { Controller, Get, Param, Post } from '@nestjs/common';
import { SystemService } from './system.service';@Controller('system')
export class SystemController {constructor(private readonly systemService: SystemService) {}@Get('processes')async getProcesses() {const processes = await this.systemService.getTopProcesses();return { @Get('uptime')async getUptime() {const uptime = await this.systemService.getSystemUptime();return { uptime };}@Post('kill/:pid')async kill(@Param('pid') pid: string) {const result = await this.systemService.killProcess(+pid);return { message: result };}@Post('force-kill/:pid')async forceKill(@Param('pid') pid: string) {const result = await this.systemService.forceKillProcess(+pid);return { message: result };}
}
// src/app.module.ts
import { Module } from '@nestjs/common';
import { SystemController } from './system/system.controller';
import { SystemService } from './system/system.service';@Module({controllers: [SystemController],providers: [SystemService],
})
export class AppModule {}
使用说明:
GET /system/processes
返回前 20 行top
输出POST /system/kill/:pid
尝试正常终止进程POST /system/force-kill/:pid
强制终止- 需配置 sudo 权限免密码或使用 systemd service 提权运行应用
2 ) 方案2
基于 NestJS 的简易进程监控 API,利用 Node.js 子进程调用系统命令,返回格式化数据
// src/process/process.service.ts
import { Injectable } from '@nestjs/common';
import { exec } from 'child_process';
import { promisify } from 'util';const asyncExec = promisify(exec);interface ProcessInfo {pid: string;user: string;cpu: string;mem: string;command: string;
}interface SystemStatus {uptime: string;loadAverage: string[];processes: ProcessInfo[];memory: { total: string; used: string; free: string };
}@Injectable()
export class ProcessService {async getTopProcesses(): Promise<SystemStatus> {try {// 获取 top 命令输出(仅前10行)const { stdout } = await asyncExec('top -b -n 1 | head -20');const lines = stdout.trim().split('\n');const status: Partial<SystemStatus> = {};// 解析 uptime 与 loadconst loadMatch = lines[0].match(/up\s+(.+?),\s+load average:\s+(.+)/);if (loadMatch) {status.uptime = loadMatch[1];status.loadAverage = loadMatch[2].split(', ').map(l => l.trim());}// 解析内存const memLine = lines.find(l => l.includes('MiB Mem'));if (memLine) {const memData = Array.from(memLine.matchAll(/\d+\.\d+/g)).map(m => m[0]);if (memData.length >= 3) {status.memory = {total: `${memData[0]} MiB`,used: `${memData[1]} MiB`,free: `${memData[2]} MiB`,};}}// 解析进程列表(跳过头部)const processLines = lines.slice(6, 16);status.processes = processLines.map(line => {const parts = line.trim().split(/\s+/);return {pid: parts[0],user: parts[1],cpu: parts[8],mem: parts[9],command: parts.slice(11).join(' ') || parts[10],} as ProcessInfo;});return status as SystemStatus;} catch (error) {throw new Error(`Failed to retrieve process }}async killProcess(pid: string): Promise<{ success: boolean; message: string }> {try {await asyncExec(`kill ${pid}`);return { success: true, message: `Process ${pid} terminated.` };} catch (error) {return { success: false, message: `Failed to kill ${pid}: ${error.message}` };}}async shutdownSystem(): Promise<{ success: boolean; message: string }> {try {await asyncExec('sudo shutdown now');return { success: true, message: 'System shutting down...' };} catch (error) {return { success: false, message: `Shutdown failed: ${error.message}` };}}
}
// src/process/process.controller.ts
import { Controller, Get, Param, Post } from '@nestjs/common';
import { ProcessService } from './process.service';@Controller('system')
export class ProcessController {constructor(private readonly processService: ProcessService) {}@Get('status')async getStatus() {return this.processService.getTopProcesses();}@Post('kill/:pid')async kill(@Param('pid') pid: string) {return this.processService.killProcess(pid);}@Post('shutdown')async shutdown() {return this.processService.shutdownSystem();}
}
部署建议:生产环境需配置权限策略(如 sudoers 免密)、HTTPS 加密通信及身份认证中间件
3 ) 方案3
NestJS 中模拟系统事件监听(非实际关机,仅为示意):
import { Injectable, OnApplicationShutdown } from '@nestjs/common';@Injectable()
export class SystemMonitorService implements OnApplicationShutdown {onApplicationShutdown(signal?: string) {console.log(`Received shutdown signal: ${signal}`);// 清理数据库连接、关闭日志流、保存缓存等this.cleanupResources();}private cleanupResources() {console.log('Cleaning up resources before exit...');// 模拟资源释放}
}
此类机制可用于优雅关闭微服务实例,避免数据丢失
总结与重点提炼
类别 | 工具/命令 | 特性与用途 |
---|---|---|
静态进程查看 | ps | 获取某一时刻的进程快照,适合脚本分析 |
动态监控 | top | 实时刷新、交互式、默认按 CPU 排序 |
高级监控 | htop | 彩色界面、支持鼠标、树状结构、易用性强 |
综合仪表盘 | glances | 多维度监控(网络、I/O、温度)、支持 Web 访问 |
终止单进程 | kill <PID> | 精准控制,支持信号定制(如 -9 ) |
批量终止 | killall <name> | 终止所有同名进程,提高效率 |
中断前台任务 | Ctrl+C | 终止当前终端运行的程序(发送 SIGINT ) |
系统关机 | shutdown | 最安全方式,支持定时、广播、取消 |
立即关机 | poweroff | 普通用户也可执行,快速断电 |
重启系统 | reboot | 需 root 权限,触发完整重启流程 |
重点强调
- top 是动态且交互式的进程监控工具,优于
ps
的静态特性 - Ctrl+C 仅适用于终端前台进程,不能终止后台或系统级服务
- kill 命令需配合 PID 使用,而
killall
则基于程序名批量操作 - 强制终止应慎用
-9
信号,优先尝试SIGTERM
实现优雅关闭 - shutdown 是最推荐的关机方式,支持延迟与消息通知,保障多用户环境安全
- htop 和 glances 提供更佳可视化体验,建议作为生产环境标准监控组件部署
- 所有命令均基于
/proc
与信号机制,理解底层有助于深入调优
核心思想:
- 监控先行:优先使用
htop
或glances
全面掌握系统状态 - 安全终止:优先尝试
SIGTERM
,无效再使用SIGKILL
- 权限管理:敏感操作(如 kill root 进程)需合理配置
sudo
策略 - 自动化集成:可通过 NestJS 等框架构建可视化系统健康检测平台
最终提醒:任何强制终止(如 kill -9
)都应作为最后手段,优先尝试 SIGTERM
保障数据一致性。系统操作务必谨慎,避免误操作导致服务中断