23 processchild_processcluster Cheatsheet

process 高频属性与方法

API 作用 注意事项
process.pid 当前 PID 每个 Cluster Worker 不同
process.ppid 父 PID 容器/进程管理器下需结合进程树
process.argv 命令行参数 前两项通常是 Node 和脚本路径
process.execArgv Node 启动选项 不等于业务参数
process.env 环境变量 值是字符串或 undefined;不要完整打印
process.cwd() 当前工作目录 相对路径以此为基准
process.chdir() 改变 cwd 服务中慎用,会影响整个进程
process.exitCode 设置自然退出码 通常优于立即 exit()
process.exit() 立即进入退出流程 可能截断异步日志/stdout
process.memoryUsage() 内存指标 RSS、Heap、External 含义不同
process.cpuUsage() CPU 微秒统计 不是直接的百分比
process.uptime() 运行秒数 可用于诊断
process.kill(pid, signal) 给 PID 发送 Signal 名称不代表一定“杀死”

标准流

stdin   fd 0,Readable
stdout  fd 1,Writable
stderr  fd 2,Writable
stdio   三者及额外通道的统称/配置
process.stdin.pipe(process.stdout);
process.stderr.write("diagnostic\n");

Bash:

command > stdout.log
command 2> stderr.log
command > all.log 2>&1
producer | consumer

记住:stderr 有输出不等于进程失败,成功通常由退出码和业务协议共同决定。

Process 事件与 Signal

事件 用途 注意事项
SIGINT Ctrl+C 等中断 Windows/终端行为存在差异
SIGTERM PM2/systemd/容器停机 做优雅关闭
beforeExit 事件循环将为空 不是通用停机钩子
exit 即将退出 只能可靠执行同步代码
warning Node.js 警告 例如监听器过多
uncaughtException 未捕获异常 进程状态可能不可靠,应清理后退出
unhandledRejection 未处理 Promise 拒绝 不应仅记录后继续假装健康

child_process 选择

API Shell 输出 推荐场景
spawn() 默认否 Stream 长任务、大输出、实时进度
exec() 缓冲后回调/Promise 可信、短小 Shell 命令
execFile() 默认否 缓冲后回调/Promise 明确可执行文件、小输出
fork() 启动 Node.js Stream + IPC Node.js 子任务
*Sync() 视 API 阻塞返回 CLI/启动阶段,Express 中避免

默认优先:

spawn(executable, args, {
  shell: false,
});

ChildProcess 常用属性

属性 含义 易错点
pid 子进程 PID 启动失败时可能不可用
stdin 子进程标准输入 stdio 非 pipe 时可能为 null
stdout 子进程标准输出 必须消费或明确 inherit/ignore
stderr 子进程标准错误 有内容不等于失败
exitCode 已退出时的码 运行中通常为 null
signalCode 终止 Signal 被 Signal 终止时使用
killed 是否成功发送过终止请求 不代表进程已经退出
connected IPC 是否连接 不代表业务健康

ChildProcess 事件

事件 含义 使用建议
spawn 成功创建子进程 仅表示启动阶段成功
error 启动/发送等失败 命令不存在通常在这里
exit 子进程已退出 stdio 可能尚未全部关闭
close 进程结束且 stdio 关闭 常用于最终 settle
message IPC 消息 必须运行时校验
disconnect IPC 断开 不等于进程必然退出

常见时间线:

启动失败:error → close
正常:spawn → data... → exit(0) → close(0)
业务失败:spawn → data... → exit(non-zero) → close(non-zero)
Signal:spawn → exit(null, signal) → close(null, signal)

事件的精确组合还受平台、stdio 和 API 调用影响,封装必须避免 Promise 重复 settle。

stdio 配置

stdio: "pipe"       // 父进程可访问 child.stdin/out/err
stdio: "inherit"    // 直接继承父终端
stdio: "ignore"     // 丢弃
stdio: ["pipe", "pipe", "pipe", "ipc"]

数组索引:

0 stdin
1 stdout
2 stderr
3+ 额外 fd/IPC

超时和取消

const controller = new AbortController();

const child = spawn(command, args, {
  signal: controller.signal,
});

controller.abort();

取消后仍需要:

处理 AbortError/error
等待 close
确认进程树策略
清理半成品
更新任务状态

IPC

fork()

child.send({
  type: "start",
  taskId,
});

child.on("message", (message: unknown) => {
  // 运行时校验
});

不能发送并共享:

普通函数
Express Request
Sequelize 连接
EventEmitter 实例状态
任意巨大对象而不考虑复制成本

Cluster 高频 API

API 作用
cluster.isPrimary 当前是否 Primary
cluster.isWorker 当前是否 Worker
cluster.fork() 创建 Worker 进程
cluster.workers Worker 映射
cluster.worker 当前 Worker 信息
cluster.setupPrimary() 配置 Worker 启动参数
cluster.disconnect() 断开 Worker 并等待关闭
worker.send() Primary 向 Worker 发 IPC
worker.kill() 终止 Worker

Cluster 事件:

fork
online
listening
message
disconnect
exit

技术选择

调用 Python/R/Bash          spawn()/execFile()
运行 Node.js 子任务 + IPC    fork()
CPU 密集 JavaScript          worker_threads
多进程共享 Express 端口      cluster 或 PM2 cluster mode
可靠后台任务                 BullMQ/任务系统 + Worker
跨机器通信                   Redis/消息队列/数据库

Cluster 上线检查

[ ] 每个 Worker 都会执行入口文件
[ ] 定时任务/迁移没有重复运行
[ ] 内存 Session、Map、限流不被误认为共享
[ ] 数据库总连接数已乘 Worker 数量
[ ] 日志包含 PID/Worker ID
[ ] Worker 崩溃重启有退避和上限
[ ] SIGTERM 能优雅关闭 Server 和子进程
[ ] WebSocket/长连接策略明确
[ ] PM2 没有与代码 Cluster 双重扩容

子进程上线检查

[ ] executable 来自白名单配置
[ ] args 使用数组,没有拼接 Shell
[ ] cwd 与 env 明确
[ ] stdout/stderr 有界消费
[ ] Chunk 按流处理,不假设是一行
[ ] error 与 close 都处理
[ ] 非零退出、Signal、结果缺失均能识别
[ ] timeout/abort 后等待实际退出
[ ] 孙进程/进程树策略经过目标平台测试
[ ] 临时结果失败后清理
[ ] 日志不含秘密和敏感数据