捕获 promisify `child_process.exec` 的错误
这个东西文档里没写清楚,所以写篇博客记一下。
在 Node.js 里,我们可以使用 child_process 下的命令分裂出一个进程,执行其他的命令。这些命令包括 exec,execFile 和 spawn。
我比较常使用 exec 和 spawn。前者用起来比较方便,只要传入完整的命令和参数,很接近日常命令行体验;后者传参要麻烦一些,不过可以实时获取输出,包括 stdout 和 stderr,比较方便给用户及时反馈。
下面贴一下文档里的例子,spawn 的使用将来有机会再说。
const { exec } = require('child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});
Node.js 8 之后,我们可以用 util.promisify() 命令将 exec 转换为 Promise 风格的方法,即不再需要 callback 函数,而是返回 Promise 实例,方便我们链式调用或者使用 Async function。
此时,它的样子是这样的:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function lsExample() {
const { stdout, stderr } = await exec('ls');
console.log('stdout:', stdout);
console.error('stderr:', stderr);
}
lsExample();
官方文档没解释清楚错误处理,经过我的尝试,是这样的:
- 命令发生错误,或者被意外中断都会引发错误
- 如果不出错,就会正确返回
stdout和stderr - 否则,错误实例里会包含
stdout,stderr和code - 1~127 是各种错误编码,128+ 则是
signal+ 127 的结果,通常来说是受控于我们的操作。比如使用 FFmpeg 录屏的时候,结束录制就要 Ctrl+C,此时就会得到值为 128 的code。所以此时很可能不是真的失败。
const util = require('util');
const exec = util.promisify(require('child_process').exec);
(async () => {
let code, stdout, stderr;
try {
({stdout, stderr} = await exec('ls'));
} catch (e) {
({code, stdout, stderr} = e);
}
if (code && code > 127) {
// 确实失败了
}
console.log('stdout:', stdout);
console.log('stderr:', stderr);
})();
相关文章
Promise 改造 child_process.exec
`util.promisify(child_process.exec)` 得到的函数无法获取 `exit code`,所以我重新封装了一下。
2018-07-073 分钟
在 Code.fun 做 Code Review(四)
时光如梭,一晃 2022 年已经过去 2/3,我们一起迎来 9 月。秋风送爽,丹桂漂亮,下面,我们一起回顾 8 […]
2022-09-036 分钟
使用 Node.js 驱动 FFMPEG 录屏
FFMPEG 功能非常强大,不仅能转换视频格式、压缩视频、添加字幕等,还能录制屏幕内容。使用 FFMPEG 录 […]
2021-01-148 分钟


