Handling standard input/output/error in a child process in Node.js

Running child processes in Node.js is a common requirement when working with external programs or running system commands. When executing a child process, you may need to handle the standard input/output/error streams of the child process.

In this tutorial, we will explore how to handle standard input/output/error for a child process in Node.js.

Table of Contents

Inheriting Parent Process’ Streams

By default, when executing a child process in Node.js, the child process inherits the standard input/output/error streams of its parent process. This means that the child process can read input from the parent process and write output or error messages to the parent process.

Here’s an example of how to create a child process and inherit the parent process’ streams:

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

const child = spawn('ls', ['-la']);

child.stdout.on('data', (data) => {
  console.log(`Child process stdout: ${data}`);
});

child.stderr.on('data', (error) => {
  console.error(`Child process stderr: ${error}`);
});

child.on('close', (code) => {
  console.log(`Child process exited with code ${code}`);
});

In the above example, we spawn a child process to run the ls -la command, which lists the files and directories in the current directory. We attach event listeners to the child process’s stdout, stderr, and close events. This allows us to handle the standard output, standard error, and exit code of the child process, respectively.

Setting Custom Streams

In some cases, you may want to set custom streams for the child process, rather than inheriting the parent’s streams. For example, you might want to redirect the standard output of the child process to a file, or read standard input from a file.

To set custom streams for a child process, you can use the stdio option when spawning the child process. The stdio option accepts an array of I/O configurations.

Here’s an example of how to set a custom stream for the standard output of a child process:

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

const stdout = fs.createWriteStream('output.txt');
const child = spawn('ls', ['-la'], { stdio: ['ignore', stdout, 'ignore'] });

child.on('close', (code) => {
  console.log(`Child process exited with code ${code}`);
});

In the above example, we create a write stream using Node.js’ fs module and pass it as a custom stream for the standard output of the child process. This redirects the output of the child process to the specified file (output.txt).

Handling Standard Input

To provide standard input to a child process, you can write to the stdin property of the child process. This allows you to send input data to the child process programmatically.

Here’s an example of how to provide standard input to a child process:

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

const child = spawn('grep', ['hello']);

child.stdout.on('data', (data) => {
  console.log(`Child process stdout: ${data}`);
});

child.on('close', (code) => {
  console.log(`Child process exited with code ${code}`);
});

// Writing to standard input
child.stdin.write('hello world\n');
child.stdin.end();

In the above example, we spawn a child process to run the grep hello command, which searches for the word “hello” in the input. We write the input “hello world” to the child process’s stdin and then close the input stream.

Handling Standard Output

In the previous examples, we used the stdout event of the child process to handle the standard output. However, you can also retrieve the standard output as a buffer using the stdout property.

Here’s an example of how to retrieve the standard output as a buffer:

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

const result = spawnSync('ls', ['-la']);

console.log(`Standard output: ${result.stdout.toString()}`);

In the above example, we use spawnSync instead of spawn to run the child process synchronously. We retrieve the standard output as a buffer using the stdout property of the result object and convert it to a string using the toString() method.

Handling Standard Error

Similar to handling standard output, you can handle standard error by attaching an event listener to the stderr event of the child process.

Here’s an example of how to handle the standard error:

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

const child = spawn('echo', ['hello world'], { stdio: ['pipe', 'pipe', 'pipe'] });

child.stderr.on('data', (error) => {
  console.error(`Child process stderr: ${error}`);
});

child.on('close', (code) => {
  console.log(`Child process exited with code ${code}`);
});

In the above example, we spawn a child process to run the echo command with the argument “hello world”. Since the echo command does not produce an error, the stderr event will not be triggered. However, if the child process encounters an error, you can handle it by attaching an event listener to the stderr event.

Conclusion

Handling standard input/output/error for a child process in Node.js allows us to integrate external programs or interact with system commands seamlessly. By inheriting the parent process’ streams or setting custom streams, we can control the flow of data between the child process and the parent process.

Remember to carefully handle standard input, standard output, and standard error based on your requirements to ensure efficient communication with child processes.

#nodejs #childprocess