Home

Customize child_processes

This is meant as a follow-up to the exec post and the spawn post.
child_processes can be given a config object to customize some

Pass Environment Variables

By default, child_processes inherit the process.env.___ from the parent process. The config object, though, can be updated to include new env vars:

const { spawn } = require('child_process');

const COMMAND_TO_RUN = ['-p', 'process.env'];
const spawnObj = spawn(`${process.execPath}`, COMMAND_TO_RUN, {
  env: {
    CUSTOM_VAL: 'i wrote this value in the parent process'
  },
});
console.log('parent process env var: ', process.env.CUSTOM_VAL);
spawnObj.stdout.pipe(process.stdout);

The output of that will look something like:

parent process env var:  undefined
{
  CUSTOM_VAL: 'i wrote this value in the parent process',
  __CF_USER_TEXT_ENCODING: '0x1F5:0x0:0x0'
}

Change the working directory of the child process

const { spawn } = require('child_process');

const COMMAND_TO_RUN = ['-p', 'console.log("child process cwd: ",process.cwd())'];
const spawnObj = spawn(`${process.execPath}`, COMMAND_TO_RUN, {
 cwd: './../'
});
console.log('parent process cwd: ', process.cwd());
spawnObj.stdout.pipe(process.stdout);

The output of this will return something like:

parent process cwd:  /Dir/To/Starting/path
child process cwd:  /Dir/To/Starting/
undefined

Change how stdio streams get handled

One way to "get" child-process stdio info is to listen for data events on the child_process object's stdout & stderr. Here:

  • a child_process gets spawned
  • the child process
    • logs an error
    • pipes its own stdin to its own stdout
  • the parent prcoess
    • listens for the stdout and stderr data events on the child process and logs strings when those child_process streans get data
    • writes to the child process stdin a string
const { spawn } = require('child_process');
const parent_string = 'the is a string in the parent';
const childProcessString = `console.error('child err output string'); process.stdin.pipe(process.stdout)`;
const sp = spawn(
  process.execPath,
  ['-e', childProcessString],
);

sp.stdout.on('data', (d) => console.log(d.toString()))
sp.stderr.on('data', (d) => console.log(d.toString()));

sp.stdin.write(`${parent_string}\n`);
sp.stdin.end();

The output of the parent process will look like:

child err output string

the is a string in the parent

One of the configuration object properties of the child_process spawn (and others) is stdio. That property can be leveraged to simplify the code above.
The 3 below example review a couple implementations of the inherit, parent process stream routing, and ignore options of configuring the child process stdio.

direct child process stdout to the parent

const { spawn } = require('child_process');
const parent_string = 'the is a string in the parent';
const childProcessString = `console.error('child err output string'); process.stdin.pipe(process.stdout)`;
const sp = spawn(process.execPath, ['-e', childProcessString], {
  stdio: ['pipe', 'inherit', 'pipe']
});

sp.stderr.on('data', (d) => console.log(d.toString()));

sp.stdin.write(`${parent_string}\n`);
sp.stdin.end();

the stdio config property takes a few options. The most detailed is the array of 3 strings.
pipe is the "default" behavior.
inherit. This makes the child process inherit the parent processes stream.
The order of the three strings represent stdin, stdout, and stderr in that order.
The above code output will be the exact same as the previous example.

direct child process stderr to the parent

const { spawn } = require('child_process');
const parent_string = 'the is a string in the parent';
const childProcessString = `console.error('child err output string'); process.stdin.pipe(process.stdout)`;
const sp = spawn(process.execPath, ['-e', childProcessString], {
  stdio: ['pipe', 'inherit', process.stdout]
});

sp.stdin.write(`${parent_string}\n`);
sp.stdin.end();

Above, the child process stderr stdio config value is set to the parent processes process.stdout. This is like "piping" the child process stderr to the parent processes stdout.

ignore the child process stderr

const { spawn } = require('child_process');
const parent_string = 'the is a string in the parent';
const childProcessString = `console.error('child err output string'); process.stdin.pipe(process.stdout)`;
const sp = spawn(process.execPath, ['-e', childProcessString], {
  stdio: ['pipe', 'inherit', 'ignore'],
});

sp.stdin.write(`${parent_string}\n`);
sp.stdin.end();

In this example, the stderr of the child process is ignored. As the node docs read, this is like opening /dev/null and "shouting into the void". The console.error message essentially gets "lost".

Tags: