exec and execSync
A step-by-step order of creating and "getting" results from child-processes:
- create the parent process: this is a js file that node will read
- have a process that you want to run as a child inside the parent: to start here, this will contain trivial stuff
- instruct the parent process to create a child_process: pass the process execution command the child_process
- get the output from the child process and handle it in the parent process
a synchronous approach with execSync
// the dependency
const { execSync } = require('child_process');
// a process to run - here, node evaluating a console.log
const COMMAND_TO_RUN = `node -e "console.log('string from node -e nested string')"`;
// running the command
const execOut = execSync(COMMAND_TO_RUN);
// doing something with the output
console.log(execOut)
NOTE: the output from the above example, and any execSync
output, is a buffer. The output above will start with <Buffer ...
. To convert it to a string, add execOut.toString()
.
Here's another example doing some math. This uses the -p flag to print the result.
const { execSync } = require('child_process');
const node_command = `4 + 7`;
const COMMAND_TO_RUN = `node -p "${node_command}"`;
const execOut = execSync(COMMAND_TO_RUN);
console.log(Number(execOut.toString()));
use the current node executable path
When executing a node process in the exec
command, rather than running node with the node
keyword, the process.execPath can (and should?!) be used. On my machine at the time of writing this variable returs /usr/local/bin/node
as the value. Here's the above math example now using the node executable path from a variable:
const { execSync } = require('child_process');
const node_command = `4 + 7`;
const COMMAND_TO_RUN = `${process.execPath} -p "${node_command}"`;
const execOut = execSync(COMMAND_TO_RUN);
console.log(Number(execOut.toString()));
handle errors of the executable process
// the dependency
const { execSync } = require('child_process');
// a process to run - here, node evaluating a console.log
const COMMAND_TO_RUN = `${process.execPath} -e "throw new Error('this is an error')"`;
try {
// running the command
const execOut = execSync(COMMAND_TO_RUN);
// doing something with the output
console.log(execOut.toString());
} catch (error) {
console.log("child process error caught by parent process: ",error.message)
}
an async approach with exec
A simple example:
const { exec } = require('child_process');
const COMMAND_TO_RUN = `node -e "console.log('string from node -e nested string')"`;
function execResponseHandler(err, stdout, stderr) {
console.log({
err,
stdout,
stderr
})
}
exec(COMMAND_TO_RUN, execResponseHandler);
An example running some math:
const { exec } = require('child_process');
const node_command = `4 + 7`;
const COMMAND_TO_RUN = `node -p "${node_command}"`;
function execResponseHandler(err, stdout, stderr) {
console.log({
err,
stdout,
stderr,
});
console.log(Number(stdout.toString()));
}
exec(COMMAND_TO_RUN, execResponseHandler);
Using the execPath
instead of node
directly:
const { exec } = require('child_process');
const node_command = `4 + 7`;
const COMMAND_TO_RUN = `${process.execPath} -p "${node_command}"`;
function execResponseHandler(err, stdout, stderr) {
console.log({
err,
stdout,
stderr,
});
console.log(Number(stdout.toString()));
}
exec(COMMAND_TO_RUN, execResponseHandler);
Handle a process error:
const { exec } = require('child_process');
const COMMAND_TO_RUN = `${process.execPath} -e "throw new Error('this is an error')"`;
function execResponseHandler(err, stdout, stderr) {
console.log({
err,
stdout,
stderr: stderr.toString(),
});
}
exec(COMMAND_TO_RUN, execResponseHandler);
Handling stderr output via a console.error
statement
const { exec } = require('child_process');
// // a process to run - here, node evaluating a console.log
const COMMAND_TO_RUN = `${process.execPath} -e "console.log('this is a stout string'); console.error('this is a stderr string')"`;
function execResponseHandler(err, stdout, stderr) {
console.log({
err,
stdout: stdout.toString(),
stderr: stderr.toString(),
});
}
exec(COMMAND_TO_RUN, execResponseHandler);