本文目录导读:

在脚本(如 Bash、Python、Node.js、Shell 等)中监控内存使用,通常关注以下关键指标,这些指标可以帮助判断是否发生内存泄漏、内存溢出或性能瓶颈。
核心指标(进程级)
这些指标主要针对脚本自身进程的内存占用。
| 指标名称 | 常见别名 | 含义说明 | 在脚本中的意义 |
|---|---|---|---|
| RSS (Resident Set Size) | 常驻内存集 | 进程实际占用的物理内存大小(包括共享库)。 | 最常用指标,表示你的脚本“霸占”了多少RAM,如果持续增长,大概率是内存泄漏。 |
| VSZ (Virtual Memory Size) | 虚拟内存大小 | 进程可访问的整个虚拟地址空间大小(包括已换出的、未分配的、共享的库)。 | 通常大于RSS,可以用来初步判断脚本是否申请了过多内存(如创建了大数组)。 |
| PSS (Proportional Set Size) | 比例集大小 | RSS按比例分配了共享库后的内存。 | 更准确的计算多个进程共享内存时的真实占用。 |
| USS (Unique Set Size) | 唯一集大小 | 进程独占的物理内存(不包含共享库)。 | 检测内存泄漏最准确的指标,如果USS持续增长,说明脚本有专属内存没有被释放。 |
| Heap Usage | 堆内存 | 动态分配的内存(如 malloc、new、list.append 等)。 |
特别是对于Python/Java/Node.js脚本,堆的峰值和当前使用量至关重要。 |
| Stack Usage | 栈内存 | 局部变量、函数调用的内存。 | 递归过深或局部变量过大可能导致栈溢出。 |
系统级指标(环境监控)
这些指标用于判断脚本运行环境的整体健康状况,防止脚本被系统杀死(OOM)。
| 指标名称 | 含义说明 | 在脚本中的意义 |
|---|---|---|
| Total Memory | 物理内存总量 | 服务器有多大内存。 |
| Available Memory | 可用内存 | 当前系统还有多少内存可供新进程使用(包括可回收的缓存)。 |
| Swap Usage | 交换分区使用量 | 内存不足时,系统将内存数据放到磁盘上。如果Swap使用持续增加,说明内存非常紧张,脚本性能会急剧下降。 |
| OOM Score | 内核的OOM杀手评分 | 内核决定哪个进程在内存耗尽时被杀死,数值越高,越容易被杀,可以监控脚本的oom_score来预判风险。 |
不同脚本语言的特定指标
Bash/Shell 脚本
Bash本身不直接管理内存,但可以监控其子进程或调用外部命令的内存。
- 常用命令:
ps aux或ps -o pid,rss,vsz,comm - 监控命令内存:
grep、sort、awk处理大文件时,它们的内存消耗才是关键。 - 查看 /proc 文件系统:
# 查看特定进程的内存状态 cat /proc/$PID/status | grep -E "VmRSS|VmSize|VmPeak|VmSwap"
Python 脚本
- 常用库:
psutil(进程和系统监控神器),tracemalloc(标准库,追踪内存分配),objgraph(可视化对象引用)。 - 关键指标:
rss(物理内存)vms(虚拟内存)uss(唯一内存 - 用psutil获取)- 存活对象数:Python GC 未回收的对象数量,如
len(gc.get_objects())。 - N最耗内存对象:定位具体是哪行代码、哪个对象导致内存增长。
- 命令行工具:
memory_profiler(逐行分析内存)。
import psutil, os
# 获取当前脚本进程信息
process = psutil.Process(os.getpid())
print(f"RSS: {process.memory_info().rss / 1024**2:.2f} MB")
print(f"USS: {process.memory_info().uss / 1024**2:.2f} MB")
Node.js 脚本
- 内置工具:
process.memoryUsage()(V8引擎内存快照)。 - 关键指标:
rss(物理内存)heapTotal(V8堆空间总容量)heapUsed(当前活跃的堆内存,核心指标)external(绑定到JS对象的C++对象占用内存)arrayBuffers(ArrayBuffer分配的内存)
- GC监控:使用
--trace-gc标志启动脚本,可以看到GC(垃圾回收)速度:如果GC频繁且回收量少,可能是内存泄漏。
const usage = process.memoryUsage();
console.log(`heapUsed: ${(usage.heapUsed / 1024 / 1024).toFixed(2)} MB`);
console.log(`rss: ${(usage.rss / 1024 / 1024).toFixed(2)} MB`);
Java 脚本
- 核心指标:
- 堆内存 (Heap):新生代、老年代、元空间。
- 非堆内存 (Non-Heap):Code Cache, Thread Stack等。
- GC情况:Full GC 次数和耗时;Young GC 频率,频繁的 Full GC 往往意味着老年代内存不足或泄漏。
- 常用工具:
jstat,jmap,VisualVM,Prometheus + Grafana。
重点关注的“危险信号”
在编写监控脚本时,以下情况需要发出警报:
- 持续性增长:
- 指标:
RSS/heapUsed/USS在脚本运行期间只增不减(没有因为GC或释放而下降),并且趋势线向上。 - 高度疑似内存泄漏。
- 指标:
- 峰值过高:
- 指标:
VmPeak或RSS接近系统Available Memory或Swap Total。 - 存在突发的内存尖峰,可能触发 OOM Killer(内核OOM杀手)。
- 指标:
- Swap 大量写入:
- 指标:通过
cat /proc/$PID/status查看VmSwap,或者系统si(Swap in) /so(Swap out) 频繁增加。 - 物理内存不足,性能将严重下降(磁盘 I/O 远慢于内存)。
- 指标:通过
- GC 异常(针对托管语言):
- 指标:GC 时间占比过高(如 > 20%),或 Full GC 频繁发生。
- 内存分配压力大,回收效率低。
一个简单的 Shell 监控脚本模板
你可以使用以下脚本包装或自监控来记录关键指标:
#!/bin/bash
# monitor_memory.sh
PID_TO_MONITOR=$1
SLEEP_INTERVAL=5
echo "Time, RSS(MB), VSZ(MB), OOM_Score"
while true; do
if [ ! -d /proc/$PID_TO_MONITOR ]; then
echo "Process $PID_TO_MONITOR ended."
break
fi
# 获取 RSS 和 VSZ
MEM_INFO=$(ps -p $PID_TO_MONITOR -o rss=,vsz= 2>/dev/null)
if [ $? -ne 0 ]; then
echo "Process $PID_TO_MONITOR ended."
break
fi
RSS_KB=$(echo $MEM_INFO | awk '{print $1}')
VSZ_KB=$(echo $MEM_INFO | awk '{print $2}')
# 获取 OOM 分数
OOM_SCORE=$(cat /proc/$PID_TO_MONITOR/oom_score 2>/dev/null || echo "N/A")
# 转换为 MB
RSS_MB=$((RSS_KB / 1024))
VSZ_MB=$((VSZ_KB / 1024))
echo "$(date +%T), $RSS_MB, $VSZ_MB, $OOM_SCORE"
sleep $SLEEP_INTERVAL
done
总结建议
- 新手入门:重点监控 RSS (常驻内存集) 和 系统可用内存。
- 高级定位:监控 USS (唯一内存) 和 语言的 GC (垃圾回收) / Heap (堆) 指标。
- 崩溃预警:监控 OOM Score (OOM 评分) 和 Swap 使用量。
- 工具选择:
- 通用:
ps,/proc,top,htop。 - Python:
psutil。 - Node.js:
process.memoryUsage()+clinic.js。 - Java:
jstat,VisualVM。 - 系统级:
free -m,vmstat,smem。
- 通用: