Child process

<!--introduced_in=v0.10.0-->

Stability: 2 - Stable

<!-- source_link=lib/child_process.js -->

The node:child_process module provides the ability to spawn subprocesses in a manner that is similar, but not identical, to popen(3). This capability is primarily provided by the [child_process.spawn()][] function:

const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);

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}`);
});
import { spawn } from 'node:child_process';
import { once } from 'node:events';
const ls = spawn('ls', ['-lh', '/usr']);

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

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

const [code] = await once(ls, 'close');
console.log(`child process exited with code ${code}`);

By default, pipes for stdin, stdout, and stderr are established between the parent Node.js process and the spawned subprocess. These pipes have limited (and platform-specific) capacity. If the subprocess writes to stdout in excess of that limit without the output being captured, the subprocess blocks, waiting for the pipe buffer to accept more data. This is identical to the behavior of pipes in the shell. Use the { stdio: 'ignore' } option if the output will not be consumed.

The command lookup is performed using the options.env.PATH environment variable if env is in the options object. Otherwise, process.env.PATH is used. If options.env is set without PATH, lookup on Unix is performed on a default search path search of /usr/bin:/bin (see your operating system's manual for execvpe/execvp), on Windows the current processes environment variable PATH is used.

On Windows, environment variables are case-insensitive. Node.js lexicographically sorts the env keys and uses the first one that case-insensitively matches. Only first (in lexicographic order) entry will be passed to the subprocess. This might lead to issues on Windows when passing objects to the env option that have multiple variants of the same key, such as PATH and Path.

The [child_process.spawn()][] method spawns the child process asynchronously, without blocking the Node.js event loop. The [child_process.spawnSync()][] function provides equivalent functionality in a synchronous manner that blocks the event loop until the spawned process either exits or is terminated.

For convenience, the node:child_process module provides a handful of synchronous and asynchronous alternatives to [child_process.spawn()][] and [child_process.spawnSync()][]. Each of these alternatives are implemented on top of [child_process.spawn()][] or [child_process.spawnSync()][].

  • [child_process.exec()][]: spawns a shell and runs a command within that shell, passing the stdout and stderr to a callback function when complete.
  • [child_process.execFile()][]: similar to [child_process.exec()][] except that it spawns the command directly without first spawning a shell by default.
  • [child_process.fork()][]: spawns a new Node.js process and invokes a specified module with an IPC communication channel established that allows sending messages between parent and child.
  • [child_process.execSync()][]: a synchronous version of [child_process.exec()][] that will block the Node.js event loop.
  • [child_process.execFileSync()][]: a synchronous version of [child_process.execFile()][] that will block the Node.js event loop.

For certain use cases, such as automating shell scripts, the [synchronous counterparts][] may be more convenient. In many cases, however, the synchronous methods can have significant impact on performance due to stalling the event loop while spawned processes complete.

Asynchronous process creation

The [child_process.spawn()][], [child_process.fork()][], [child_process.exec()][], and [child_process.execFile()][] methods all follow the idiomatic asynchronous programming pattern typical of other Node.js APIs.

Each of the methods returns a [ChildProcess][] instance. These objects implement the Node.js [EventEmitter][] API, allowing the parent process to register listener functions that are called when certain events occur during the life cycle of the child process.

The [child_process.exec()][] and [child_process.execFile()][] methods additionally allow for an optional callback function to be specified that is invoked when the child process terminates.

Spawning .bat and .cmd files on Windows

The importance of the distinction between [child_process.exec()][] and [child_process.execFile()][] can vary based on platform. On Unix-type operating systems (Unix, Linux, macOS) [child_process.execFile()][] can be more efficient because it does not spawn a shell by default. On Windows, however, .bat and .cmd files are not executable on their own without a terminal, and therefore cannot be launched using [child_process.execFile()][]. When running on Windows, .bat and .cmd files can be invoked by:

  • using [child_process.spawn()][] with the shell option set (not recommended, see [DEP0190][]), or
  • using [child_process.exec()][], or
  • spawning cmd.exe and passing the .bat or .cmd file as an argument (which is what [child_process.exec()][] does internally).

In any case, if the script filename contains spaces, it needs to be quoted.

const { exec, spawn } = require('node:child_process');

exec('my.bat', (err, stdout, stderr) => { /* ... */ });

// Or, spawning cmd.exe directly:
const bat = spawn('cmd.exe', ['/c', 'my.bat']);

// If the script filename contains spaces, it needs to be quoted
exec('"my script.cmd" a b', (err, stdout, stderr) => { /* ... */ });
import { exec, spawn } from 'node:child_process';

exec('my.bat', (err, stdout, stderr) => { /* ... */ });

// Or, spawning cmd.exe directly:
const bat = spawn('cmd.exe', ['/c', 'my.bat']);

// If the script filename contains spaces, it needs to be quoted
exec('"my script.cmd" a b', (err, stdout, stderr) => { /* ... */ });

child_process.exec(command[, options][, callback])

<!-- YAML added: v0.1.90 changes: - version: - v16.4.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/38862 description: The cwd option can be a WHATWG URL object using file: protocol. - version: v15.4.0 pr-url: https://github.com/nodejs/node/pull/36308 description: AbortSignal support was added. - version: v8.8.0 pr-url: https://github.com/nodejs/node/pull/15380 description: The windowsHide option is supported now. -->

  • command {string} The command to run, with space-separated arguments.
  • options {Object}
  • cwd {string|URL} Current working directory of the child process. Default: process.cwd().
  • env {Object} Environment key-value pairs. Default: process.env.
  • encoding {string} Default: 'utf8'
  • shell {string} Shell to execute the command with. See [Shell requirements][] and [Default Windows shell][]. Default: '/bin/sh' on Unix, process.env.ComSpec on Windows.
  • signal {AbortSignal} allows aborting the child process using an AbortSignal.
  • timeout {number} Default: 0
  • maxBuffer {number} Largest amount of data in bytes allowed on stdout or stderr. If exceeded, the child process is terminated and any output is truncated. See caveat at [maxBuffer and Unicode][]. Default: 1024 * 1024.
  • killSignal {string|integer} Default: 'SIGTERM'
  • uid {number} Sets the user identity of the process (see setuid(2)).
  • gid {number} Sets the group identity of the process (see setgid(2)).
  • windowsHide {boolean} Hide the subprocess console window that would normally be created on Windows systems. Default: false.
  • callback {Function} called with the output when process terminates.
  • error {Error}
  • stdout {string|Buffer}
  • stderr {string|Buffer}
  • Returns: {ChildProcess}

Spawns a shell then executes the command within that shell, buffering any generated output. The command string passed to the exec function is processed directly by the shell and special characters (vary based on shell) need to be dealt with accordingly:

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

exec('"/path/to/test file/test.sh" arg1 arg2');
// Double quotes are used so that the space in the path is not interpreted as
// a delimiter of multiple arguments.

exec('echo "The \\$HOME variable is $HOME"');
// The $HOME variable is escaped in the first instance, but not in the second.
import { exec } from 'node:child_process';

exec('"/path/to/test file/test.sh" arg1 arg2');
// Double quotes are used so that the space in the path is not interpreted as
// a delimiter of multiple arguments.

exec('echo "The \\$HOME variable is $HOME"');
// The $HOME variable is escaped in the first instance, but not in the second.

Never pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

If a callback function is provided, it is called with the arguments (error, stdout, stderr). On success, error will be null. On error, error will be an instance of [Error][]. The error.code property will be the exit code of the process. By convention, any exit code other than 0 indicates an error. error.signal will be the signal that terminated the process.

The stdout and stderr arguments passed to the callback will contain the stdout and stderr output of the child process. By default, Node.js will decode the output as UTF-8 and pass strings to the callback. The encoding option can be used to specify the character encoding used to decode the stdout and stderr output. If encoding is 'buffer', or an unrecognized character encoding, Buffer objects will be passed to the callback instead.

Using the signal option to destroy a long-lived child process as a resource cleanup mechanism is deprecated. The signal option remains appropriate for cancellation, externally propagated aborts, and timeouts. See [DEP0209](https://nodejs.org/docs/latest/api/deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources.

const { exec } = require('node:child_process');
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
});
import { exec } from 'node:child_process';
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
});

If timeout is greater than 0, the parent process will send the signal identified by the killSignal property (the default is 'SIGTERM') if the child process runs longer than timeout milliseconds.

Unlike the exec(3) POSIX system call, child_process.exec() does not replace the existing process and uses a shell to execute the command.

If this method is invoked as its [util.promisify()][]ed version, it returns a Promise for an Object with stdout and stderr properties. The returned ChildProcess instance is attached to the Promise as a child property. In case of an error (including any error resulting in an exit code other than 0), a rejected promise is returned, with the same error object given in the callback, but with two additional properties stdout and stderr.

const util = require('node:util');
const exec = util.promisify(require('node:child_process').exec);

async function lsExample() {
  const { stdout, stderr } = await exec('ls');
  console.log('stdout:', stdout);
  console.error('stderr:', stderr);
}
lsExample();
import { promisify } from 'node:util';
import child_process from 'node:child_process';
const exec = promisify(child_process.exec);

async function lsExample() {
  const { stdout, stderr } = await exec('ls');
  console.log('stdout:', stdout);
  console.error('stderr:', stderr);
}
lsExample();

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

const { exec } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const child = exec('grep ssh', { signal }, (error) => {
  console.error(error); // an AbortError
});
controller.abort();
import { exec } from 'node:child_process';
const controller = new AbortController();
const { signal } = controller;
const child = exec('grep ssh', { signal }, (error) => {
  console.error(error); // an AbortError
});
controller.abort();

child_process.execFile(file[, args][, options][, callback])

<!-- YAML added: v0.1.91 changes: - version: - v23.11.0 - v22.15.0 pr-url: https://github.com/nodejs/node/pull/57389 description: Passing args when shell is set to true is deprecated. - version: - v16.4.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/38862 description: The cwd option can be a WHATWG URL object using file: protocol. - version: - v15.4.0 - v14.17.0 pr-url: https://github.com/nodejs/node/pull/36308 description: AbortSignal support was added. - version: v8.8.0 pr-url: https://github.com/nodejs/node/pull/15380 description: The windowsHide option is supported now. -->

  • file {string} The name or path of the executable file to run.
  • args {string[]} List of string arguments.
  • options {Object}
  • cwd {string|URL} Current working directory of the child process.
  • env {Object} Environment key-value pairs. Default: process.env.
  • encoding {string} Default: 'utf8'
  • timeout {number} Default: 0
  • maxBuffer {number} Largest amount of data in bytes allowed on stdout or stderr. If exceeded, the child process is terminated and any output is truncated. See caveat at [maxBuffer and Unicode][]. Default: 1024 * 1024.
  • killSignal {string|integer} Default: 'SIGTERM'
  • uid {number} Sets the user identity of the process (see setuid(2)).
  • gid {number} Sets the group identity of the process (see setgid(2)).
  • windowsHide {boolean} Hide the subprocess console window that would normally be created on Windows systems. Default: false.
  • windowsVerbatimArguments {boolean} No quoting or escaping of arguments is done on Windows. Ignored on Unix. Default: false.
  • shell {boolean|string} If true, runs command inside of a shell. Uses '/bin/sh' on Unix, and process.env.ComSpec on Windows. A different shell can be specified as a string. See [Shell requirements][] and [Default Windows shell][]. Default: false (no shell).
  • signal {AbortSignal} allows aborting the child process using an AbortSignal.
  • callback {Function} Called with the output when process terminates.
  • error {Error}
  • stdout {string|Buffer}
  • stderr {string|Buffer}
  • Returns: {ChildProcess}

The child_process.execFile() function is similar to [child_process.exec()][] except that it does not spawn a shell by default. Rather, the specified executable file is spawned directly as a new process making it slightly more efficient than [child_process.exec()][].

Using the signal option to destroy a long-lived child process as a resource cleanup mechanism is deprecated. The signal option remains appropriate for cancellation, externally propagated aborts, and timeouts. See [DEP0209](https://nodejs.org/docs/latest/api/deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources.

The same options as [child_process.exec()][] are supported. Since a shell is not spawned, behaviors such as I/O redirection and file globbing are not supported.

const { execFile } = require('node:child_process');
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    throw error;
  }
  console.log(stdout);
});
import { execFile } from 'node:child_process';
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    throw error;
  }
  console.log(stdout);
});

The stdout and stderr arguments passed to the callback will contain the stdout and stderr output of the child process. By default, Node.js will decode the output as UTF-8 and pass strings to the callback. The encoding option can be used to specify the character encoding used to decode the stdout and stderr output. If encoding is 'buffer', or an unrecognized character encoding, Buffer objects will be passed to the callback instead.

If this method is invoked as its [util.promisify()][]ed version, it returns a Promise for an Object with stdout and stderr properties. The returned ChildProcess instance is attached to the Promise as a child property. In case of an error (including any error resulting in an exit code other than 0), a rejected promise is returned, with the same error object given in the callback, but with two additional properties stdout and stderr.

const util = require('node:util');
const execFile = util.promisify(require('node:child_process').execFile);
async function getVersion() {
  const { stdout } = await execFile('node', ['--version']);
  console.log(stdout);
}
getVersion();
import { promisify } from 'node:util';
import child_process from 'node:child_process';
const execFile = promisify(child_process.execFile);
async function getVersion() {
  const { stdout } = await execFile('node', ['--version']);
  console.log(stdout);
}
getVersion();

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

const { execFile } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const child = execFile('node', ['--version'], { signal }, (error) => {
  console.error(error); // an AbortError
});
controller.abort();
import { execFile } from 'node:child_process';
const controller = new AbortController();
const { signal } = controller;
const child = execFile('node', ['--version'], { signal }, (error) => {
  console.error(error); // an AbortError
});
controller.abort();

child_process.fork(modulePath[, args][, options])

<!-- YAML added: v0.5.0 changes: - version: - v17.4.0 - v16.14.0 pr-url: https://github.com/nodejs/node/pull/41225 description: The modulePath parameter can be a WHATWG URL object using file: protocol. - version: - v16.4.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/38862 description: The cwd option can be a WHATWG URL object using file: protocol. - version: - v15.13.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/37256 description: timeout was added. - version: - v15.11.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/37325 description: killSignal for AbortSignal was added. - version: - v15.6.0 - v14.17.0 pr-url: https://github.com/nodejs/node/pull/36603 description: AbortSignal support was added. - version: - v13.2.0 - v12.16.0 pr-url: https://github.com/nodejs/node/pull/30162 description: The serialization option is supported now. - version: v8.0.0 pr-url: https://github.com/nodejs/node/pull/10866 description: The stdio option can now be a string. - version: v6.4.0 pr-url: https://github.com/nodejs/node/pull/7811 description: The stdio option is supported now. -->

  • modulePath {string|URL} The module to run in the child.
  • args {string[]} List of string arguments.
  • options {Object}
  • cwd {string|URL} Current working directory of the child process.
  • detached {boolean} Prepare child process to run independently of its parent process. Specific behavior depends on the platform (see [options.detached][]).
  • env {Object} Environment key-value pairs. Default: process.env.
  • execPath {string} Executable used to create the child process.
  • execArgv {string[]} List of string arguments passed to the executable. Default: process.execArgv.
  • gid {number} Sets the group identity of the process (see setgid(2)).
  • serialization {string} Specify the kind of serialization used for sending messages between processes. Possible values are 'json' and 'advanced'. See [Advanced serialization][] for more details. Default: 'json'.
  • signal {AbortSignal} Allows closing the child process using an AbortSignal.
  • killSignal {string|integer} The signal value to be used when the spawned process will be killed by timeout or abort signal. Default: 'SIGTERM'.
  • silent {boolean} If true, stdin, stdout, and stderr of the child process will be piped to the parent process, otherwise they will be inherited from the parent process, see the 'pipe' and 'inherit' options for [child_process.spawn()][]'s [stdio][] for more details. Default: false.
  • stdio {Array|string} See [child_process.spawn()][]'s [stdio][]. When this option is provided, it overrides silent. If the array variant is used, it must contain exactly one item with value 'ipc' or an error will be thrown. For instance [0, 1, 2, 'ipc'].
  • uid {number} Sets the user identity of the process (see setuid(2)).
  • windowsHide {boolean} Hide the subprocess console window that would normally be created on Windows systems. Default: false.
  • windowsVerbatimArguments {boolean} No quoting or escaping of arguments is done on Windows. Ignored on Unix. Default: false.
  • timeout {number} In milliseconds the maximum amount of time the process is allowed to run. Default: undefined.
  • Returns: {ChildProcess}

The child_process.fork() method is a special case of [child_process.spawn()][] used specifically to spawn new Node.js processes. Like [child_process.spawn()][], a [ChildProcess][] object is returned. The returned [ChildProcess][] will have an additional communication channel built-in that allows messages to be passed back and forth between the parent and child. See [subprocess.send()][] for details.

Keep in mind that spawned Node.js child processes are independent of the parent with exception of the IPC communication channel that is established between the two. Each process has its own memory, with their own V8 instances. Because of the additional resource allocations required, spawning a large number of child Node.js processes is not recommended.

By default, child_process.fork() will spawn new Node.js instances using the [process.execPath][] of the parent process. The execPath property in the options object allows for an alternative execution path to be used.

Node.js processes launched with a custom execPath will communicate with the parent process using the file descriptor (fd) identified using the environment variable NODE_CHANNEL_FD on the child process.

Unlike the fork(2) POSIX system call, child_process.fork() does not clone the current process.

The shell option available in [child_process.spawn()][] is not supported by child_process.fork() and will be ignored if set.

Using the signal option to destroy a long-lived child process as a resource cleanup mechanism is deprecated. The signal option remains appropriate for cancellation, externally propagated aborts, and timeouts. See [DEP0209](https://nodejs.org/docs/latest/api/deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources.

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

const { fork } = require('node:child_process');

if (process.argv[2] === 'child') {
  setTimeout(() => {
    console.log(`Hello from ${process.argv[2]}!`);
  }, 1_000);
} else {
  const controller = new AbortController();
  const { signal } = controller;
  const child = fork(__filename, ['child'], { signal });
  child.on('error', (err) => {
    // This will be called with err being an AbortError if the controller aborts
  });
  controller.abort(); // Stops the child process
}
import { fork } from 'node:child_process';
import process from 'node:process';

if (process.argv[2] === 'child') {
  setTimeout(() => {
    console.log(`Hello from ${process.argv[2]}!`);
  }, 1_000);
} else {
  const controller = new AbortController();
  const { signal } = controller;
  const child = fork(import.meta.url, ['child'], { signal });
  child.on('error', (err) => {
    // This will be called with err being an AbortError if the controller aborts
  });
  controller.abort(); // Stops the child process
}

child_process.spawn(command[, args][, options])

<!-- YAML added: v0.1.90 changes: - version: - v23.11.0 - v22.15.0 pr-url: https://github.com/nodejs/node/pull/57389 description: Passing args when shell is set to true is deprecated. - version: - v16.4.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/38862 description: The cwd option can be a WHATWG URL object using file: protocol. - version: - v15.13.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/37256 description: timeout was added. - version: - v15.11.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/37325 description: killSignal for AbortSignal was added. - version: - v15.5.0 - v14.17.0 pr-url: https://github.com/nodejs/node/pull/36432 description: AbortSignal support was added. - version: - v13.2.0 - v12.16.0 pr-url: https://github.com/nodejs/node/pull/30162 description: The serialization option is supported now. - version: v8.8.0 pr-url: https://github.com/nodejs/node/pull/15380 description: The windowsHide option is supported now. - version: v6.4.0 pr-url: https://github.com/nodejs/node/pull/7696 description: The argv0 option is supported now. - version: v5.7.0 pr-url: https://github.com/nodejs/node/pull/4598 description: The shell option is supported now. -->

  • command {string} The command to run.
  • args {string[]} List of string arguments.
  • options {Object}
  • cwd {string|URL} Current working directory of the child process.
  • env {Object} Environment key-value pairs. Default: process.env.
  • argv0 {string} Explicitly set the value of argv[0] sent to the child process. This will be set to command if not specified.
  • stdio {Array|string} Child's stdio configuration (see [options.stdio][stdio]).
  • detached {boolean} Prepare child process to run independently of its parent process. Specific behavior depends on the platform (see [options.detached][]).
  • uid {number} Sets the user identity of the process (see setuid(2)).
  • gid {number} Sets the group identity of the process (see setgid(2)).
  • serialization {string} Specify the kind of serialization used for sending messages between processes. Possible values are 'json' and 'advanced'. See [Advanced serialization][] for more details. Default: 'json'.
  • shell {boolean|string} If true, runs command inside of a shell. Uses '/bin/sh' on Unix, and process.env.ComSpec on Windows. A different shell can be specified as a string. See [Shell requirements][] and [Default Windows shell][]. Default: false (no shell).
  • windowsVerbatimArguments {boolean} No quoting or escaping of arguments is done on Windows. Ignored on Unix. This is set to true automatically when shell is specified and is CMD. Default: false.
  • windowsHide {boolean} Hide the subprocess console window that would normally be created on Windows systems. Default: false.
  • signal {AbortSignal} allows aborting the child process using an AbortSignal.
  • timeout {number} In milliseconds the maximum amount of time the process is allowed to run. Default: undefined.
  • killSignal {string|integer} The signal value to be used when the spawned process will be killed by timeout or abort signal. Default: 'SIGTERM'.
  • Returns: {ChildProcess}

The child_process.spawn() method spawns a new process using the given command, with command-line arguments in args. If omitted, args defaults to an empty array.

If the shell option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution.

A third argument may be used to specify additional options, with these defaults:

const defaults = {
  cwd: undefined,
  env: process.env,
};

Use cwd to specify the working directory from which the process is spawned. If not given, the default is to inherit the current working directory. If given, but the path does not exist, the child process emits an ENOENT error and exits immediately. ENOENT is also emitted when the command does not exist.

Use env to specify environment variables that will be visible to the new process, the default is [process.env][].

undefined values in env will be ignored.

Using the signal option to destroy a long-lived child process as a resource cleanup mechanism is deprecated. The signal option remains appropriate for cancellation, externally propagated aborts, and timeouts. See [DEP0209](https://nodejs.org/docs/latest/api/deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources.

Example of running ls -lh /usr, capturing stdout, stderr, and the exit code:

const { spawn } = require('node:child_process');
const ls = spawn('ls', ['-lh', '/usr']);

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}`);
});
import { spawn } from 'node:child_process';
import { once } from 'node:events';
const ls = spawn('ls', ['-lh', '/usr']);

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

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

const [code] = await once(ls, 'close');
console.log(`child process exited with code ${code}`);

Example: A very elaborate way to run ps ax | grep ssh

const { spawn } = require('node:child_process');
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);

ps.stdout.on('data', (data) => {
  grep.stdin.write(data);
});

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

ps.on('close', (code) => {
  if (code !== 0) {
    console.log(`ps process exited with code ${code}`);
  }
  grep.stdin.end();
});

grep.stdout.on('data', (data) => {
  console.log(data.toString());
});

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

grep.on('close', (code) => {
  if (code !== 0) {
    console.log(`grep process exited with code ${code}`);
  }
});
import { spawn } from 'node:child_process';
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);

ps.stdout.on('data', (data) => {
  grep.stdin.write(data);
});

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

ps.on('close', (code) => {
  if (code !== 0) {
    console.log(`ps process exited with code ${code}`);
  }
  grep.stdin.end();
});

grep.stdout.on('data', (data) => {
  console.log(data.toString());
});

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

grep.on('close', (code) => {
  if (code !== 0) {
    console.log(`grep process exited with code ${code}`);
  }
});

Example of checking for failed spawn:

const { spawn } = require('node:child_process');
const subprocess = spawn('bad_command');

subprocess.on('error', (err) => {
  console.error('Failed to start subprocess.');
});
import { spawn } from 'node:child_process';
const subprocess = spawn('bad_command');

subprocess.on('error', (err) => {
  console.error('Failed to start subprocess.');
});

Certain platforms (macOS, Linux) will use the value of argv[0] for the process title while others (Windows, SunOS) will use command.

Node.js overwrites argv[0] with process.execPath on startup, so process.argv[0] in a Node.js child process will not match the argv0 parameter passed to spawn from the parent. Retrieve it with the process.argv0 property instead.

If the signal option is enabled, calling .abort() on the corresponding AbortController is similar to calling .kill() on the child process except the error passed to the callback will be an AbortError:

const { spawn } = require('node:child_process');
const controller = new AbortController();
const { signal } = controller;
const grep = spawn('grep', ['ssh'], { signal });
grep.on('error', (err) => {
  // This will be called with err being an AbortError if the controller aborts
});
controller.abort(); // Stops the child process
import { spawn } from 'node:child_process';
const controller = new AbortController();
const { signal } = controller;
const grep = spawn('grep', ['ssh'], { signal });
grep.on('error', (err) => {
  // This will be called with err being an AbortError if the controller aborts
});
controller.abort(); // Stops the child process

options.detached

<!-- YAML added: v0.7.10 -->

On Windows, setting options.detached to true makes it possible for the child process to continue running after the parent exits. The child process will have its own console window. Once enabled for a child process, it cannot be disabled.

On non-Windows platforms, if options.detached is set to true, the child process will be made the leader of a new process group and session. Child processes may continue running after the parent exits regardless of whether they are detached or not. See setsid(2) for more information.

By default, the parent will wait for the detached child process to exit. To prevent the parent process from waiting for a given subprocess to exit, use the subprocess.unref() method. Doing so will cause the parent process' event loop to not include the child process in its reference count, allowing the parent process to exit independently of the child process, unless there is an established IPC channel between the child and the parent processes.

When using the detached option to start a long-running process, the process will not stay running in the background after the parent exits unless it is provided with a stdio configuration that is not connected to the parent. If the parent process' stdio is inherited, the child process will remain attached to the controlling terminal.

Example of a long-running process, by detaching and also ignoring its parent stdio file descriptors, in order to ignore the parent's termination:

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

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore',
});

subprocess.unref();
import { spawn } from 'node:child_process';
import process from 'node:process';

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore',
});

subprocess.unref();

Alternatively one can redirect the child process' output into files:

const { openSync } = require('node:fs');
const { spawn } = require('node:child_process');
const out = openSync('./out.log', 'a');
const err = openSync('./out.log', 'a');

const subprocess = spawn('prg', [], {
  detached: true,
  stdio: [ 'ignore', out, err ],
});

subprocess.unref();
import { openSync } from 'node:fs';
import { spawn } from 'node:child_process';
const out = openSync('./out.log', 'a');
const err = openSync('./out.log', 'a');

const subprocess = spawn('prg', [], {
  detached: true,
  stdio: [ 'ignore', out, err ],
});

subprocess.unref();

options.stdio

<!-- YAML added: v0.7.10 changes: - version: - v15.6.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/29412 description: Added the overlapped stdio flag. - version: v3.3.1 pr-url: https://github.com/nodejs/node/pull/2727 description: The value 0 is now accepted as a file descriptor. -->

The options.stdio option is used to configure the pipes that are established between the parent and child process. By default, the child's stdin, stdout, and stderr are redirected to corresponding [subprocess.stdin][], [subprocess.stdout][], and [subprocess.stderr][] streams on the [ChildProcess][] object. This is equivalent to setting the options.stdio equal to ['pipe', 'pipe', 'pipe'].

For convenience, options.stdio may be one of the following strings:

  • 'pipe': equivalent to ['pipe', 'pipe', 'pipe'] (the default)
  • 'overlapped': equivalent to ['overlapped', 'overlapped', 'overlapped']
  • 'ignore': equivalent to ['ignore', 'ignore', 'ignore']
  • 'inherit': equivalent to ['inherit', 'inherit', 'inherit'] or [0, 1, 2]

Otherwise, the value of options.stdio is an array where each index corresponds to an fd in the child. The fds 0, 1, and 2 correspond to stdin, stdout, and stderr, respectively. Additional fds can be specified to create additional pipes between the parent and child. The value is one of the following:

  1. 'pipe': Create a pipe between the child process and the parent process. The parent end of the pipe is exposed to the parent as a property on the child_process object as [subprocess.stdio[fd]][subprocess.stdio]. Pipes created for fds 0, 1, and 2 are also available as [subprocess.stdin][], [subprocess.stdout][] and [subprocess.stderr][], respectively. These are not actual Unix pipes and therefore the child process can not use them by their descriptor files, e.g. /dev/fd/2 or /dev/stdout.
  2. 'overlapped': Same as 'pipe' except that the FILE_FLAG_OVERLAPPED flag is set on the handle. This is necessary for overlapped I/O on the child process's stdio handles. See the docs for more details. This is exactly the same as 'pipe' on non-Windows systems.
  3. 'ipc': Create an IPC channel for passing messages/file descriptors between parent and child. A [ChildProcess][] may have at most one IPC stdio file descriptor. Setting this option enables the [subprocess.send()][] method. If the child process is a Node.js instance, the presence of an IPC channel will enable [process.send()][] and [process.disconnect()][] methods, as well as ['disconnect'][] and ['message'][] events within the child process.

Accessing the IPC channel fd in any way other than [process.send()][] or using the IPC channel with a child process that is not a Node.js instance is not supported. 4. 'ignore': Instructs Node.js to ignore the fd in the child. While Node.js will always open fds 0, 1, and 2 for the processes it spawns, setting the fd to 'ignore' will cause Node.js to open /dev/null and attach it to the child's fd. 5. 'inherit': Pass through the corresponding stdio stream to/from the parent process. In the first three positions, this is equivalent to process.stdin, process.stdout, and process.stderr, respectively. In any other position, equivalent to 'ignore'. 6. {Stream} object: Share a readable or writable stream that refers to a tty, file, socket, or a pipe with the child process. The stream's underlying file descriptor is duplicated in the child process to the fd that corresponds to the index in the stdio array. The stream must have an underlying descriptor (file streams do not start until the 'open' event has occurred). NOTE: While it is technically possible to pass stdin as a writable or stdout/stderr as readable, it is not recommended. Readable and writable streams are designed with distinct behaviors, and using them incorrectly (e.g., passing a readable stream where a writable stream is expected) can lead to unexpected results or errors. This practice is discouraged as it may result in undefined behavior or dropped callbacks if the stream encounters errors. Always ensure that stdin is used as readable and stdout/stderr as writable to maintain the intended flow of data between the parent and child processes. The stream passed in the stdin position is the source from which the child process reads its input, and the streams in the stdout/stderr positions receive the output the child writes. This is the opposite of [subprocess.stdin][] (writable) and [subprocess.stdout][] (readable), which are the parent's ends of the pipes created by 'pipe'. 7. Positive integer: The integer value is interpreted as a file descriptor that is open in the parent process. It is shared with the child process, similar to how {Stream} objects can be shared. Passing sockets is not supported on Windows. 8. null, undefined: Use default value. For stdio fds 0, 1, and 2 (in other words, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the default is 'ignore'.

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

// Child will use parent's stdios.
spawn('prg', [], { stdio: 'inherit' });

// Spawn child sharing only stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });

// Open an extra fd=4, to interact with programs presenting a
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
import { spawn } from 'node:child_process';
import process from 'node:process';

// Child will use parent's stdios.
spawn('prg', [], { stdio: 'inherit' });

// Spawn child sharing only stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });

// Open an extra fd=4, to interact with programs presenting a
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

It is worth noting that when an IPC channel is established between the parent and child processes, and the child process is a Node.js instance, the child process is launched with the IPC channel unreferenced (using unref()) until the child process registers an event handler for the ['disconnect'][] event or the ['message'][] event. This allows the child process to exit normally without the process being held open by the open IPC channel. See also: [child_process.exec()][] and [child_process.fork()][].

Synchronous process creation

The [child_process.spawnSync()][], [child_process.execSync()][], and [child_process.execFileSync()][] methods are synchronous and will block the Node.js event loop, pausing execution of any additional code until the spawned process exits.

Blocking calls like these are mostly useful for simplifying general-purpose scripting tasks and for simplifying the loading/processing of application configuration at startup.

child_process.execFileSync(file[, args][, options])

<!-- YAML added: v0.11.12 changes: - version: - v16.4.0 - v14.18.0 pr-url: https://github.com/nodejs/node/pull/38862 description: The cwd option can be a WHATWG URL object using file: protocol. - version: v10.10.0 pr-url: https://github.com/nodejs/node/pull/22409 description: The input option can now be any TypedArray or a DataView. - version: v8.8.0 pr-url: https://github.com/nodejs/node/pull/15380 description: The windowsHide option is suppo

(本文超出站点单文档体积上限,已截断)