From f93d495747a2be4f72639d3dfa6a0b6e3eecd045 Mon Sep 17 00:00:00 2001 From: Aviv Keller <38299977+RedYetiDev@users.noreply.github.com> Date: Thu, 27 Jun 2024 19:17:18 -0400 Subject: [PATCH 1/5] doc, child_process: add esm snippets --- doc/api/child_process.md | 550 ++++++++++++++++++++++++++++++++++----- 1 file changed, 489 insertions(+), 61 deletions(-) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index b08ba65917aadc..65843d5eb8d5cd 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -10,7 +10,7 @@ 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: -```js +```cjs const { spawn } = require('node:child_process'); const ls = spawn('ls', ['-lh', '/usr']); @@ -27,6 +27,23 @@ ls.on('close', (code) => { }); ``` +```mjs +import { spawn } from '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}`); +}); +``` + 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 @@ -109,39 +126,36 @@ When running on Windows, `.bat` and `.cmd` files can be invoked using spaces it needs to be quoted. ```js -// On Windows Only... const { spawn } = require('node:child_process'); -const bat = spawn('cmd.exe', ['/c', 'my.bat']); +const spawned = spawn('my_command', ['arguments']); -bat.stdout.on('data', (data) => { +spawned.stdout.on('data', (data) => { console.log(data.toString()); }); -bat.stderr.on('data', (data) => { +spawned.stderr.on('data', (data) => { console.error(data.toString()); }); -bat.on('exit', (code) => { +spawned.on('exit', (code) => { console.log(`Child exited with code ${code}`); }); ``` -```js -// OR... -const { exec, spawn } = require('node:child_process'); -exec('my.bat', (err, stdout, stderr) => { - if (err) { - console.error(err); - return; - } - console.log(stdout); +```mjs +import { spawn } from 'node:child_process'; +const spawned = spawn('my_command', ['arguments']); + +spawned.stdout.on('data', (data) => { + console.log(data.toString()); }); -// Script with spaces in the filename: -const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true }); -// or: -exec('"my script.cmd" a b', (err, stdout, stderr) => { - // ... +spawned.stderr.on('data', (data) => { + console.error(data.toString()); +}); + +spawned.on('exit', (code) => { + console.log(`Child exited with code ${code}`); }); ``` @@ -197,7 +211,7 @@ directly by the shell and special characters (vary based on [shell](https://en.wikipedia.org/wiki/List_of_command-line_interpreters)) need to be dealt with accordingly: -```js +```cjs const { exec } = require('node:child_process'); exec('"/path/to/test file/test.sh" arg1 arg2'); @@ -208,6 +222,17 @@ exec('echo "The \\$HOME variable is $HOME"'); // The $HOME variable is escaped in the first instance, but not in the second. ``` +```mjs +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.** @@ -225,7 +250,7 @@ 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. -```js +```cjs const { exec } = require('node:child_process'); exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => { if (error) { @@ -237,6 +262,18 @@ exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => { }); ``` +```mjs +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 will send the signal identified by the `killSignal` property (the default is `'SIGTERM'`) if the child runs longer than `timeout` milliseconds. @@ -251,7 +288,7 @@ 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`. -```js +```cjs const util = require('node:util'); const exec = util.promisify(require('node:child_process').exec); @@ -263,11 +300,24 @@ async function lsExample() { lsExample(); ``` +```mjs +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`: -```js +```cjs const { exec } = require('node:child_process'); const controller = new AbortController(); const { signal } = controller; @@ -277,6 +327,16 @@ const child = exec('grep ssh', { signal }, (error) => { controller.abort(); ``` +```mjs +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])`