bugl
bugl
HomeLearnPatternsSearch
HomeLearnPatternsSearch

Loading lesson path

Learn/Node.js/Perfomance & Scaling
Node.js•Perfomance & Scaling

Node.js Child Process Module

Concept visual

Node.js Child Process Module

push / pop from the top({[← top

What is the Child Process Module?

Formula

The Child Process module is a built - in Node.js module that allows you to create and manage child processes.

It provides several ways to execute external commands and communicate with subprocess instances. This capability is essential for tasks like: Running system commands from your Node.js application

Executing CPU-intensive tasks in separate processes

Running multiple processes in parallel to utilize multiple CPU cores

Interfacing with external programs and scripts

Importing the Child Process Module

The Child Process module is included in Node.js by default. You can use it by requiring it in your script:

const childProcess = require('child_process');
// Or using destructuring to access specific methods const { exec, spawn, fork } = require('child_process');

Methods for Creating Child Processes

The Child Process module provides four primary methods for creating and managing child processes, each with different behaviors and use cases:

Method

Description

Use Case exec()

Spawns a shell and executes a command, buffering the output When you need to run a shell command and get the entire output at once execFile()

Similar to exec()

but doesn't spawn a shell

Formula

More efficient for executing file - based commands without shell interpretation spawn()
Spawns a new process without creating a shell, with streaming I/O
When dealing with long - running processes or large output fork()

A special case of spawn()

for creating Node.js processes When you need to run another Node.js module as a separate process with IPC

The exec() Method

The exec()

method creates a shell and executes a command within that shell. It buffers the entire output and provides it via a callback when the command completes.

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

Formula

// Execute the 'ls - la' command (or 'dir' on Windows)
const command = process.platform === 'win32' ? 'dir' : 'ls -la';
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${error.message}`);
return;
}
if (stderr) {
console.error(`Command stderr: ${stderr}`);
}
console.log(`Command output:\n${stdout}`);
});
// With options exec('echo $HOME', {
env: { HOME: '/custom/home/directory' }
}, (error, stdout, stderr) => {
console.log(`Custom home directory: ${stdout.trim()}`);
});

Warning:

Never pass unsanitized user input to exec()

as it runs commands with full shell syntax, which can lead to command injection attacks. exec() with Promise Using a promise wrapper to handle the callback:

const { exec } = require('child_process');
const util = require('util');
// Convert exec to a promise-based function const execPromise = util.promisify(exec);
async function executeCommand(command) {
try {
const { stdout, stderr } = await execPromise(command);
if (stderr) {
console.error(`Command stderr: ${stderr}`);
}
console.log(`Command output:\n${stdout}`);
return stdout;
} catch (error) {
console.error(`Error executing command: ${error.message}`);
throw error;
}
}
// Using the promise-based function executeCommand('node --version').then(version => console.log(`Node.js version: ${version.trim()}`)).catch(err => console.error('Failed to get Node.js version'));

The execFile() Method

The execFile()

method is similar to exec(), but it doesn't spawn a shell. It's more efficient for executing external binaries.

const { execFile } = require('child_process');
// Execute 'node' with arguments execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
console.error(`Error executing file: ${error.message}`);
return;
}
console.log(`Node.js version: ${stdout.trim()}`);
});
// On Windows, execute a batch file if (process.platform === 'win32') {
execFile('C:\\Windows\\System32\\cmd.exe', ['/c', 'echo Hello from batch!'], (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
console.log(`Output: ${stdout.trim()}`);
});
}

Note:

execFile() is more secure than exec() for running commands with user input, as it doesn't process shell metacharacters.

The spawn() Method

The spawn()

method launches a new process with the given command.

Formula

Unlike exec(), it doesn't buffer the output, instead providing stream - based access to stdout and stderr.
const { spawn } = require('child_process');
// Spawn a process to list files const ls = process.platform === 'win32'
? spawn('cmd', ['/c', 'dir'])
: spawn('ls', ['-la']);
// Handle process output streams ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`Child process exited with code ${code}`);
});
// Spawn with options const grep = spawn('grep', ['hello', 'input.txt'], {
cwd: '/tmp',         // Working directory env: { ...process.env, CUSTOM_ENV: 'value' }, stdio: 'pipe',       // Configure stdio detached: false,     // Process group behavior shell: false         // Whether to run in a shell
});
// Handling errors grep.on('error', (err) => {
console.error(`Failed to start subprocess: ${err.message}`);
});

When to Use spawn()

spawn() is especially useful for:

Formula

Long - running processes (like server processes or watchers)

Processes that produce large amounts of output

When you need to process data as it's generated, rather than waiting for completion

Using spawn() with stdin const { spawn } = require('child_process');
// Spawn a process that reads from stdin const process = spawn('wc', ['-w']); // Word count
// Send data to the process's stdin process.stdin.write('Hello world from Node.js!');
process.stdin.end(); // Signal the end of input
// Capture output process.stdout.on('data', (data) => {
console.log(`Number of words: ${data}`);
});

The fork() Method

The fork()

method is a special case of spawn() specifically for creating Node.js processes. It sets up an IPC channel that allows sending messages between the parent and child processes. // In the main file (parent.js)

const { fork } = require('child_process');
// Fork a child process const child = fork('child.js');
// Send a message to the child child.send({ message: 'Hello from parent' });
// Receive messages from the child child.on('message', (message) => {
console.log('Message from child:', message);
});
// Handle child process exit child.on('close', (code) => {
console.log(`Child process exited with code ${code}`);
});
// In the child file (child.js)
console.log('Child process started', process.pid);
// Listen for messages from the parent process.on('message', (message) => {
console.log('Message from parent:', message);
// Send a message back to the parent process.send({ response: 'Hello from child' });
// After 3 seconds, exit the process setTimeout(() => {
process.exit(0);
}, 8080);
});

Benefits of fork()

Each forked process gets its own V8 instance and memory

Formula

Isolates CPU - intensive work from the main event loop

Previous

Node.js Performance Diagnostics

Next

Node.js Cluster Module