61

I can run a bash command in node.js like so:

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);
});

How do I get the exit code of that command (ls -la in this example)? I've tried running

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

This somehow always returns 0 regardless of the the exit code of the previous command though. What am I missing?

1
  • your first example is already giving you the stdout in the console.log Commented Jun 9, 2016 at 17:24

5 Answers 5

70

Those 2 commands are running in separate shells.

To get the code, you should be able to check err.code in your callback.

If that doesn't work, you need to add an exit event handler

e.g.

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
});
Sign up to request clarification or add additional context in comments.

2 Comments

Awesome! The exit event handler works great; err.code only returns a number if the error code is not 0.
Also execSync(command[, options]) for those interested in the synchronous version. nodejs.org/api/…
10

From the docs:

If a callback function is provided, it is called with the arguments (error, stdout, stderr). On success, error will be null. On error, error will be an instance of Error. The error.code property will be the exit code of the child process while error.signal will be set to the signal that terminated the process. Any exit code other than 0 is considered to be an error.

So:

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

Should work.

Comments

7

child_process.spawnSync()

This function exposes the nicest sync interface: https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options

Example:

#!/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();

Output:

status: 0
stdout: 
stderr: 

status: 1
stdout: 
stderr: 

status: 0
stdout: abc

stderr: 

Tested in Node.js v10.15.1, Ubuntu 19.10.

Comments

3

If anyone is looking for an await/Promise version:

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).

If the command is successful, then the it'll output an object like {stderr, stdout}. If it has a non-zero exit code, then it'll output an error object with {stderr, stdout, code, killed, signal, cmd} and the usual JavaScript Error object properties like message and stack.

Comments

1

In node documentation i found this information for the callback function:

On success, error will be null. On error, error will be an instance of Error. The error.code property will be the exit code of the child process while error.signal will be set to the signal that terminated the process. Any exit code other than 0 is considered to be an error.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.