Node.js 如何执行命令行二进制程序?
Node.js 执行外部程序用 child_process 模块:exec 执行简单命令拿输出,execFile 直接执行二进制(不经 shell 更安全),spawn 处理流式大输出,execSync 同步执行。本文对比四种方法与适用场景。
简单命令用 exec,执行二进制文件用 execFile(不经 shell 更安全),输出量大用 spawn,脚本里图省事用 execSync。
exec:执行 shell 命令
const { exec } = require('child_process');
exec('ls -la /tmp', (error, stdout, stderr) => {
if (error) {
console.error(`执行出错: ${error.message}`);
return;
}
console.log(`输出: ${stdout}`);
});
经 shell 执行,能用管道、重定向等 shell 特性;注意输出有 1MB 默认上限(可配 maxBuffer)。
execFile:直接执行二进制(推荐)
const { execFile } = require('child_process');
execFile('/usr/bin/convert', ['input.png', '-resize', '50%', 'output.png'],
(error, stdout, stderr) => {
if (error) { console.error(error.message); return; }
console.log(stdout);
});
不经 shell,参数以数组传递——天然免疫 shell 注入,参数来自外部输入时必须用它而不是字符串拼接的 exec。
spawn:流式大输出
const { spawn } = require('child_process');
const child = spawn('ffmpeg', ['-i', 'input.mp4', 'output.webm']);
child.stdout.on('data', (data) => console.log(`输出: ${data}`));
child.stderr.on('data', (data) => console.error(`日志: ${data}`));
child.on('close', (code) => console.log(`退出码: ${code}`));
输出按流处理,不装进内存,适合长时间运行、输出量大的命令。
execSync:同步执行
const { execSync } = require('child_process');
const output = execSync('git rev-parse HEAD').toString().trim();
阻塞事件循环,只在 CLI 脚本/构建工具里用。
选型速查
| 需求 | 方法 |
|---|---|
| 简单命令拿结果 | exec |
| 执行二进制+参数来自用户 | execFile |
| 大输出/长时运行/要实时日志 | spawn |
| 脚本里同步执行 | execSync |
常见问题(FAQ)
Q:报 Error: spawn XXX ENOENT?
命令不在 PATH 里。用绝对路径,或 spawn 时设 { shell: true }(注意注入风险)。
Q:exec 输出被截断?
默认 maxBuffer 是 1MB。调大 exec(cmd, { maxBuffer: 10*1024*1024 }),或改用 spawn。
Q:Windows 上 .cmd/.bat 执行不了?
Windows 下批处理文件必须经 shell:spawn('npm', { shell: true }) 或用 exec。