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