Skip to content

Latest commit

 

History

History
181 lines (125 loc) · 8.8 KB

File metadata and controls

181 lines (125 loc) · 8.8 KB

Child Process

In Node.js, the child_process module provides methods to create and manage child processes. The three commonly used methods are exec, spawn, and fork. Each serves a different purpose and has distinct use cases. Here's a detailed explanation:


🔹 1. spawn()

  • What it does: Launches a new process with a given command.

  • Returns: A ChildProcess object (streams for stdin, stdout, stderr).

  • Best for: Long-running processes or when you need to stream data from the child process in real-time.

  • Purpose: Spawns a new process to run a command without buffering the output in memory.

  • Use Case: When you need to handle large outputs or stream data in real-time (e.g., streaming logs or processing large files).

  • Key Features:

  • Does not use a shell by default (but can be configured to do so).

  • Streams the output (stdout and stderr) instead of buffering it.

  • Suitable for long-running processes or processes with large outputs.

✅ Example:

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

const ls = spawn('ls', ['-lh', '/usr']); // runs "ls -lh /usr"

ls.stdout.on('data', (data) => {
  console.log(`Output: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`Error: ${data}`);
});

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

🔹 Good when you expect large output (streaming is efficient).


🔹 2. exec()

  • What it does: Executes a command in a shell.
  • Returns: The command’s entire output via a callback (buffers all data first).
  • Best for: Running commands where you want the complete result (not streaming). Use Case: When you need to run a shell command and capture its output as a string (e.g., running ls, grep, or other shell utilities).

Key Features:

  • Buffers the entire output in memory, which can cause issues with large outputs.
  • Executes the command in a shell, so shell features like piping (|) and redirection (>) are available.
  • In Node.js, the child_process module provides different ways to create and manage subprocesses. The main methods you’ll see are fork(), spawn(), and exec(). They’re all used to start child processes, but they have different use cases:

✅ Example:

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

exec('ls -lh /usr', (error, stdout, stderr) => {
  if (error) {
    console.error(`Execution error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
});

🔹 Not good for very large output (since it buffers everything in memory).


🔹 3. fork()

  • What it does: Special case of spawn() to launch a Node.js module as a new process.
  • Returns: A ChildProcess object with a communication channel (send() and on('message')).
  • Best for: Running another Node.js script and communicating via messages (IPC).

Purpose: Spawns a new Node.js process and establishes a communication channel between the parent and child processes. Use Case: When you need to run a separate Node.js script and communicate with it (e.g., for worker threads or background tasks).

  • Key Features:
  • Specifically designed for spawning Node.js scripts.
  • Creates an IPC (Inter-Process Communication) channel for message passing between parent and child.
  • Does not execute shell commands.

✅ Example:

// parent.js
const { fork } = require('child_process');

const child = fork('child.js');

child.on('message', (msg) => {
  console.log('Message from child:', msg);
});

child.send({ hello: 'world' });

// child.js
process.on('message', (msg) => {
  console.log('Message from parent:', msg);
  process.send({ foo: 'bar' });
});

🔹 Great for building worker processes that run Node.js code.


🚀 Quick Comparison

Method Runs… Output handling Use Case
spawn Any command Streams (stdout/stderr) Long-running commands, large output
exec Any command (via shell) Buffers (callback) Quick commands, small output
fork Node.js scripts only IPC messages Worker processes, parallel Node.js code

Comparison table for spawn(), exec(), and fork() showing:

  • What they return
  • How they handle output
  • When to use them
  • Key trade-offs

🔹 Node.js child_process Methods — Comparison

Feature / Method spawn() exec() fork()
Syntax spawn(command, [args], options) exec(command, options, callback) fork(modulePath, args, options)
What it runs Any system command/program Any command (inside a shell) Node.js scripts only
Return value A ChildProcess object (with stdin, stdout, stderr streams) No direct child process (callback only, though a ChildProcess exists internally) A ChildProcess object with an IPC channel (send, on('message'))
Output style Streamed → emits 'data' events as output arrives Buffered → entire output returned at once in callback Normal stdout/stderr + structured IPC messages
Performance Lower overhead than exec (no shell), efficient for large output Higher overhead (spawns a shell), not safe for untrusted input Similar to spawn, but optimized for Node.js inter-process comms
Best for Long-running processes, large output, real-time logs (ping, tail -f) Short commands with small output (git status, ls) Running another Node.js script and exchanging JSON/messages
Limitations You need to manually read from streams Buffers output in memory (risk of crash with huge data) Only runs Node scripts, not shell commands
IPC (message passing) ❌ No ❌ No ✅ Yes (child.send(), process.on('message'))
Shell execution ❌ No (runs directly) ✅ Yes (runs inside /bin/sh or cmd.exe) ❌ No
Example spawn('ls', ['-lh', '/usr']) exec('ls -lh /usr', cb) fork('child.js')

🔹 When to Use Each

  • spawn()

    • ✅ Use when: Process runs for a long time or produces a lot of output.
    • ✅ Good for: Streaming logs, watching files, processing huge data streams.
    • ❌ Not good for: Simple commands where you just need the result once.
  • exec()

    • ✅ Use when: Command is short-lived and produces small output.
    • ✅ Good for: Shell one-liners (ls, git status, echo).
    • ❌ Not good for: Long-running tasks or huge outputs (memory blow-up risk).
  • fork()

    • ✅ Use when: You want to run another Node.js script and communicate with it.
    • ✅ Good for: Worker processes, clustering, background jobs.
    • ❌ Not good for: Running system commands (ls, ping, etc.).

👉 In simple words:

  • spawnfire up a process, stream its output (big/long tasks).
  • execfire up a process, give me final result (small tasks).
  • forkrun another Node.js script and talk to it (workers).

Do you want me to also make a flow diagram side-by-side in the same table (like small ASCII sketches under each row) so you can visually see buffered vs streamed vs IPC?