Node.js 的 child_process 模块提供执行系统命令的能力,是实现服务器端自动化任务和系统操作的核心功能。
核心方法解析
exec()
:执行简单命令
适用场景:短时命令(如 ls
、git status
),需获取完整输出时。
示例:
const { exec } = require('child_process'); exec('ls -l', (error, stdout, stderr) => { if (error) { console.error(`执行失败: ${error.message}`); return; } console.log(`输出结果:\n${stdout}`); // 输出目录列表 if (stderr) console.error(`错误流: ${stderr}`); });
特点:
- 缓存全部输出后回调(大输出可能内存溢出)
- 自动解析命令参数(需注意安全风险)
spawn()
:处理流式输出
适用场景:长时间任务(如日志监控、实时数据处理),需逐行处理输出。
示例:
const { spawn } = require('child_process'); const child = spawn('find', ['.', '-type', 'f']); // 安全:参数独立传递 child.stdout.on('data', (data) => { console.log(`发现文件: ${data}`); }); child.stderr.on('data', (data) => { console.error(`错误: ${data}`); }); child.on('close', (code) => { console.log(`子进程退出,代码 ${code}`); });
优势:
- 通过流(Stream)实时处理数据
- 内存效率高(适合大数据量)
- 避免 Shell 注入(默认不启动 Shell)
execFile()
:直接运行二进制文件
适用场景:执行系统应用(如 Python 脚本、编译工具),跳过 Shell 解析。
示例:
const { execFile } = require('child_process'); execFile('/path/to/script.sh', ['arg1', 'arg2'], (error, stdout) => { if (error) throw error; console.log(stdout); });
安全提示:
- 不通过 Shell 执行(防御命令注入攻击)
- 需指定可执行文件绝对路径
fork()
:运行 Node.js 子进程
适用场景:CPU 密集型任务(如数学计算),需进程间通信(IPC)。
示例:
// parent.js const { fork } = require('child_process'); const child = fork('child_script.js'); child.send({ data: '指令' }); // 发送数据到子进程 child.on('message', (msg) => { console.log('子进程返回:', msg); }); // child_script.js process.on('message', (msg) => { console.log('收到父进程数据:', msg); process.send({ result: '处理完成' }); // 返回结果 });
特点:
- 基于 IPC 的双向通信
- 独立 V8 实例(避免阻塞主线程)
安全与最佳实践
-
防御命令注入
错误做法:exec('rm ' + userInput);
(用户输入可能含; rm -rf /
)
正确方案:- 使用
spawn()
或execFile()
分离参数 - 过滤输入(如校验白名单字符)
- 使用
-
资源管理
- 设置超时(避免僵尸进程):
exec('sleep 30', { timeout: 2000 }, (error) => { if (error?.code === 'ETIMEDOUT') console.log('进程超时终止'); });
- 清理子进程:
const child = spawn('long-running-task'); setTimeout(() => child.kill('SIGTERM'), 5000); // 5秒后终止
- 设置超时(避免僵尸进程):
-
错误处理
- 监听
error
事件(如命令不存在) - 检查退出码(
code !== 0
表示异常)
- 监听
方法选型指南
方法 | 适用场景 | 是否启动 Shell | 输出处理 |
---|---|---|---|
exec() |
短命令、需完整输出 | 是 | 缓冲回调 |
spawn() |
实时流、大数据、长时间任务 | 可选 | 流式事件 |
execFile() |
运行二进制文件 | 否 | 缓冲回调 |
fork() |
Node.js 子进程、IPC 通信 | 否 | 消息传递 |
典型应用场景
- 自动化部署:
spawn('git', ['pull', 'origin', 'master'])
- 日志分析:
spawn('tail', ['-f', '/var/log/app.log'])
- 多进程优化:
fork()
分散 CPU 负载 - 调用外部工具:
execFile('/usr/bin/convert', ['image.png', 'output.jpg'])
引用说明: 参考 Node.js 官方文档 Child Process 模块,遵循 MIT 开源协议,安全实践部分依据 OWASP 命令注入防御指南。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/5577.html