Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Fix child process docs #8639

Closed
wants to merge 7 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 68 additions & 33 deletions doc/api/child_process.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -90,29 +90,71 @@ Messages send by `.send(message, [sendHandle])` are obtained using the
* {Stream object}

A `Writable Stream` that represents the child process's `stdin`.
Closing this stream via `end()` often causes the child process to terminate.
If the child is waiting to read all its input, it will not continue until this
stream has been closed via `end()`.

If the child stdio streams are shared with the parent, then this will
If the child was not spawned with `stdio[0]` set to `'pipe'`, then this will
not be set.

`child.stdin` is shorthand for `child.stdio[0]`. Both properties will refer
to the same object, or null.

### child.stdout

* {Stream object}

A `Readable Stream` that represents the child process's `stdout`.

If the child stdio streams are shared with the parent, then this will
If the child was not spawned with `stdio[1]` set to `'pipe'`, then this will
not be set.

`child.stdout` is shorthand for `child.stdio[1]`. Both properties will refer
to the same object, or null.

### child.stderr

* {Stream object}

A `Readable Stream` that represents the child process's `stderr`.

If the child stdio streams are shared with the parent, then this will
If the child was not spawned with `stdio[2]` set to `'pipe'`, then this will
not be set.

`child.stderr` is shorthand for `child.stdio[2]`. Both properties will refer
to the same object, or null.

### child.stdio

* {Array}

A sparse array of pipes to the child process, corresponding with positions in
the [stdio](#child_process_options_stdio) option to
[spawn](#child_process_child_process_spawn_command_args_options) that have been
set to `'pipe'`.
Note that streams 0-2 are also available as ChildProcess.stdin,
ChildProcess.stdout, and ChildProcess.stderr, respectively.

In the following example, only the child's fd `1` is setup as a pipe, so only
the parent's `child.stdio[1]` is a stream, all other values in the array are
`null`.

child = child_process.spawn("ls", {
stdio: [
0, // use parents stdin for child
'pipe', // pipe child's stdout to parent
fs.openSync("err.out", "w") // direct child's stderr to a file
]
});

assert.equal(child.stdio[0], null);
assert.equal(child.stdio[0], child.stdin);

assert(child.stdout);
assert.equal(child.stdio[1], child.stdout);

assert.equal(child.stdio[2], null);
assert.equal(child.stdio[2], child.stderr);

### child.pid

* {Integer}
Expand Down Expand Up @@ -299,11 +341,13 @@ child process has any open IPC channels with the parent (i.e `fork()`).
* `args` {Array} List of string arguments
* `options` {Object}
* `cwd` {String} Current working directory of the child process
* `stdio` {Array|String} Child's stdio configuration. (See below)
* `customFds` {Array} **Deprecated** File descriptors for the child to use
for stdio. (See below)
* `env` {Object} Environment key-value pairs
* `detached` {Boolean} The child will be a process group leader. (See below)
* `stdio` {Array|String} Child's stdio configuration. (See
[below](#child_process_options_stdio))
* `customFds` {Array} **Deprecated** File descriptors for the child to use
for stdio. (See [below](#child_process_options_customFds))
* `detached` {Boolean} The child will be a process group leader. (See
[below](#child_process_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).)
* return: {ChildProcess object}
Expand All @@ -317,8 +361,11 @@ The third argument is used to specify additional options, which defaults to:
env: process.env
}

`cwd` allows you to specify the working directory from which the process is spawned.
Use `env` to specify environment variables that will be visible to the new process.
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.

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

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

Expand Down Expand Up @@ -374,24 +421,16 @@ Example: A very elaborate way to run 'ps ax | grep ssh'
});


Example of checking for failed exec:

var spawn = require('child_process').spawn,
child = spawn('bad_command');
### options.stdio

child.stderr.setEncoding('utf8');
child.stderr.on('data', function (data) {
if (/^execvp\(\)/.test(data)) {
console.log('Failed to start child process.');
}
});
As a shorthand, the `stdio` argument may also be one of the following
strings:

Note that if spawn receives an empty options object, it will result in
spawning the process with an empty environment rather than using
`process.env`. This due to backwards compatibility issues with a deprecated
API.
* `'pipe'` - `['pipe', 'pipe', 'pipe']`, this is the default value
* `'ignore'` - `['ignore', 'ignore', 'ignore']`
* `'inherit'` - `[process.stdin, process.stdout, process.stderr]` or `[0,1,2]`

The 'stdio' option to `child_process.spawn()` is an array where each
Otherwise, the 'stdio' option to `child_process.spawn()` is an array where each
index corresponds to a fd in the child. The value is one of the following:

1. `'pipe'` - Create a pipe between the child process and the parent process.
Expand Down Expand Up @@ -422,13 +461,6 @@ index corresponds to a fd in the child. The value is one of the following:
words, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the
default is `'ignore'`.

As a shorthand, the `stdio` argument may also be one of the following
strings, rather than an array:

* `ignore` - `['ignore', 'ignore', 'ignore']`
* `pipe` - `['pipe', 'pipe', 'pipe']`
* `inherit` - `[process.stdin, process.stdout, process.stderr]` or `[0,1,2]`

Example:

var spawn = require('child_process').spawn;
Expand All @@ -443,6 +475,8 @@ Example:
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you:

  1. move this example block up above the paragraph starting at 464.
  2. add a new level 4 subheading above "In the child, ..." that reads #### Sharing non-stdio file descriptors.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense, you'd have:

#### Sharing non-stdio file descriptors

In the child, file descriptors 0 - 2 are automatically wrapped into streams by node, and made
available as `process.stdin`, `process.stdout`, and `process.stderr`,
respectively. ...

That's a heading saying "non-studio", followed by a sentence documenting _stdio_.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, the whole paragraph is basically just a factoring out (not by me) of common prose for options 1, 3, 4, and 5. Without this info, you don't know what the pipes create in 1., for example, look like in the child, or how to use them.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair. The reason I was looking for that reorganization is that the new paragraph pushes down the example snippet, while leading into it with a sentence describing a feature that is not often utilized.

Descriptors greater than 2 can have a stream associated with them by
constructing a 'net.Socket' with the fd
option, be passed directly to fs APIs if they are files, etc.

Example:

It definitely struck me as something that needs a code example, and if I were coming to the docs fresh, I could definitely see myself losing a few moments reconciling that sentence with the succeeding example code. However, you're right, it doesn't make sense to immediately launch a paragraph about non-stdio fd's with a sentence describing fds.

If it's the case that sharing non-stdio fds are not widely supported, then we can create the aforementioned level-4 subsection describing them and how they're not available on windows.


### options.detached

If the `detached` option is set, the child process will be made the leader of a
new process group. This makes it possible for the child to continue running
after the parent exits.
Expand Down Expand Up @@ -471,6 +505,8 @@ will not stay running in the background unless it is provided with a `stdio`
configuration that is not connected to the parent. If the parent's `stdio` is
inherited, the child will remain attached to the controlling terminal.

### options.customFds

There is a deprecated option called `customFds` which allows one to specify
specific file descriptors for the stdio of the child process. This API was
not portable to all platforms and therefore removed.
Expand Down Expand Up @@ -561,7 +597,6 @@ leaner than `child_process.exec`. It has the same options.
* `options` {Object}
* `cwd` {String} Current working directory of the child process
* `env` {Object} Environment key-value pairs
* `encoding` {String} (Default: 'utf8')
* `execPath` {String} Executable used to create the child process
* `execArgv` {Array} List of string arguments passed to the executable
(Default: `process.execArgv`)
Expand Down