process 属性与运行时上下文
本章解决的问题
- 怎样获得当前进程、Node.js 版本、工作目录和资源用量?
memoryUsage()各字段表示什么?- 如何写一个可用于排错、但不会泄密的诊断脚本?
工作原理
process 是 Node.js 提供的全局对象,代表当前操作系统进程。它暴露启动上下文、资源统计、标准流和生命周期事件。虽然 TypeScript 中可直接使用,为了明确来源也可以写:
import process from "node:process";
本项目编译为 CommonJS;import 只是 TypeScript 源码写法,实际运行模块格式仍由 tsconfig.json 的 module 决定。
高频 API
const report = {
pid: process.pid,
ppid: process.ppid,
platform: process.platform,
arch: process.arch,
nodeVersion: process.version,
componentVersions: process.versions,
cwd: process.cwd(),
uptimeSeconds: process.uptime(),
memory: process.memoryUsage(),
cpu: process.cpuUsage(),
resources: process.resourceUsage(),
};
console.log(report);
版本和目录
process.version:当前 Node.js 版本,例如v22.x.x。process.versions:V8、OpenSSL、libuv 等组件版本。process.cwd():进程当前工作目录,通常由启动者决定。process.execPath:当前 Node.js 可执行文件绝对路径,NVM/PM2 排错很有用。
内存
process.memoryUsage() 常见字段均以字节计:
rss:进程驻留物理内存,包含堆、栈、本地代码等,不只是 JS 堆。heapTotal:V8 当前已申请的 JS 堆。heapUsed:V8 当前已使用的 JS 堆。external:绑定到 JS 对象、但由 V8 堆外管理的内存。arrayBuffers:ArrayBuffer/Buffer所占内存,是external的组成部分之一。
CPU
process.cpuUsage() 返回用户态和内核态消耗的微秒数,不是 CPU 百分比。传入上次结果可得到区间差值:
const startCpu: NodeJS.CpuUsage = process.cpuUsage();
const startTime: number = Date.now();
setTimeout(() => {
const elapsedMs: number = Date.now() - startTime;
const delta: NodeJS.CpuUsage = process.cpuUsage(startCpu);
console.log({ elapsedMs, cpuMicroseconds: delta });
}, 1_000);
CPU 百分比还涉及时间区间和多核定义,不应直接把 user 当作百分比展示。
具体代码:安全诊断报告
interface RuntimeReport {
pid: number;
ppid: number;
node: string;
executable: string;
platform: NodeJS.Platform;
arch: string;
cwd: string;
uptimeSeconds: number;
rssMiB: number;
heapUsedMiB: number;
}
const bytesToMiB = (bytes: number): number =>
Math.round((bytes / 1024 / 1024) * 100) / 100;
const memory: NodeJS.MemoryUsage = process.memoryUsage();
const report: RuntimeReport = {
pid: process.pid,
ppid: process.ppid,
node: process.version,
executable: process.execPath,
platform: process.platform,
arch: process.arch,
cwd: process.cwd(),
uptimeSeconds: Math.round(process.uptime()),
rssMiB: bytesToMiB(memory.rss),
heapUsedMiB: bytesToMiB(memory.heapUsed),
};
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
这个报告故意不输出完整 process.env、命令行秘密或业务数据。
正常时间线
启动进程 → 读取静态上下文 → 采集资源快照 → 输出结构化报告 → 自然退出
异常时间线
内存持续增长 → 周期性快照显示 rss/heapUsed 上升
→ 达到进程或系统限制 → GC 频繁或分配失败 → 服务变慢/崩溃
单次快照不能证明内存泄漏。应在相同负载阶段比较趋势,并区分 JS 堆、Buffer 和本地内存。
Windows 与 Linux
process.platform在 Windows 返回win32,即使系统是 64 位;位数看process.arch。process.resourceUsage()的部分统计受平台支持情况影响,跨平台监控前应验证字段含义和单位。cwd由启动方式决定:交互终端、PM2、systemd、Windows 服务可能不同。- 路径判断使用
node:path,不要只依据平台手动拼/或\。
常见错误
- 把
cwd当成源码目录:它是“从哪里启动”,不是“文件在哪里”。 - 只看
heapUsed判断总内存:大量 Buffer 可能体现在external、arrayBuffers和rss。 - 每个请求都打印完整资源报告:增加 I/O 和日志噪音。
- 将
process.env整体写入日志:可能泄露密码、令牌和连接串。 - 看到 RSS 暂未下降就认定泄漏:运行时可能保留已申请内存供后续复用。
最佳实践
- 启动时记录版本、PID、平台、cwd,但对路径和参数做脱敏。
- 资源指标使用结构化字段和固定单位,例如
rssBytes或rssMiB。 - 用时间序列和稳定负载判断趋势,不从一次快照下结论。
- 多 Worker 时统计“单进程”与“全体进程总量”,特别注意连接池和 RSS 相乘。
练习题
- 扩展报告,添加
externalMiB、arrayBuffersMiB。 - 分配一个 50 MiB 的
Buffer,比较前后的内存字段。 - 分别从项目目录和上级目录运行同一脚本,观察
cwd。
验收点
- [ ] 能解释
rss与heapUsed的区别。 - [ ] 知道
cpuUsage()返回累计微秒而不是百分比。 - [ ] 能区分
cwd、脚本目录和 Node.js 可执行文件路径。 - [ ] 诊断日志不会输出完整环境变量。