在 Node.js 中执行 bash 命令并获取退出代码

60

我可以像这样在Node.js中运行Bash命令:

var sys = require('sys')
var exec = require('child_process').exec;

function puts(error, stdout, stderr) { sys.puts(stdout) }
exec("ls -la", function(err, stdout, stderr) {
  console.log(stdout);
});

如何获取该命令的退出代码(例如此示例中的 ls -la)?我尝试运行

exec("ls -la", function(err, stdout, stderr) {
  exec("echo $?", function(err, stdout, stderr) {
    console.log(stdout);
  });
});

无论之前的命令退出代码是什么,这总是返回0。我错过了什么吗?


你的第一个示例已经在控制台中使用console.log输出了stdout。 - Manatax
5个回答

68

这两个命令在不同的 shell 中运行。

要获得代码,您应该能够在回调函数中检查 err.code

如果这不起作用,您需要添加一个 exit 事件处理程序。

例如:

dir = exec("ls -la", function(err, stdout, stderr) {
  if (err) {
    // should have err.code here?  
  }
  console.log(stdout);
});

dir.on('exit', function (code) {
  // exit code is code
});

1
太棒了!exit事件处理程序运行良好;只有当错误代码不为0时,err.code才会返回一个数字。 - Marc Bacvanski
3
对于那些对同步版本感兴趣的人,可以使用execSync(command[, options])。详见:https://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options - Joshua Robinson

10

根据文档:

如果提供了callback函数,则将使用参数(error, stdout, stderr)调用。成功时,error将为null。在出现错误时,error将是一个Error实例,error.code属性将是子进程的退出代码,而error.signal将被设置为终止该进程的信号。任何退出代码不为0都被视为错误。

所以:

exec('...', function(error, stdout, stderr) {
  if (error) {
    console.log(error.code);
  }
});

应该可以工作。


6

child_process.spawnSync()

这个函数提供了最好的同步接口:https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options 例子:
#!/usr/bin/env node

const child_process = require('child_process');
let out;

out = child_process.spawnSync('true');
console.log('status: ' + out.status);
console.log('stdout: ' + out.stdout.toString('utf8'));
console.log('stderr: ' + out.stderr.toString('utf8'));
console.log();

out = child_process.spawnSync('false');
console.log('status: ' + out.status);
console.log('stdout: ' + out.stdout.toString('utf8'));
console.log('stderr: ' + out.stderr.toString('utf8'));
console.log();

out = child_process.spawnSync('echo', ['abc']);
console.log('status: ' + out.status);
console.log('stdout: ' + out.stdout.toString('utf8'));
console.log('stderr: ' + out.stderr.toString('utf8'));
console.log();

输出:

status: 0
stdout: 
stderr: 

status: 1
stdout: 
stderr: 

status: 0
stdout: abc

stderr: 

在Node.js v10.15.1和Ubuntu 19.10中进行了测试。


2

如果有人在寻找一个 await/Promise 版本:

const exec = require('util').promisify(require('child_process').exec);

let out = await exec(`echo hello`).catch(e => e);

console.log(out.stdout); // outputs "hello"
console.log(out.code); // Note: `out.code` is *undefined* if successful (instead of 0).

如果命令执行成功,那么它将输出一个对象,格式如下:{stderr, stdout}。如果命令退出码为非零值,则会输出一个错误对象,格式如下:{stderr, stdout, code, killed, signal, cmd},同时还包括JavaScript中通常的Error对象属性,例如messagestack。请注意保留HTML标签。

1
在Node文档中,我找到了有关回调函数的以下信息:
成功时,错误将为null。发生错误时,错误将是一个Error实例。error.code属性将是子进程的退出代码,而error.signal将被设置为终止进程的信号。除0以外的任何退出代码都被视为错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接