Skip to content

Commit 3d17a2a

Browse files
committed
Added spawn with pipes example
1 parent d8d487c commit 3d17a2a

1 file changed

Lines changed: 116 additions & 26 deletions

File tree

child-processes/index.md

Lines changed: 116 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,151 @@
11
---
2-
layout: default
2+
layout: post
33
title: Child Processes
4+
url: child-processes
5+
author: ian
46
---
57

6-
The `child_process` module provides the ability to spawn child processes. Whilst single-threaded, non-blocking performance in Node.js is great for a single process, but we can use `child_process` to handle the increasing workload in our applications.
8+
_Prerequisites: [events](../events), [streams](../buffers-and-streams)_
9+
10+
The `child_process` module provides the ability to spawn child processes and interact with other programs. Whilst single-threaded, non-blocking performance in Node.js is great for a single process, we can use `child_process` to handle the increasing workload in our applications in multiple threads.
711

812
Using multiple processes allows a Node application to scale. Node is designed for building distributed applications with many nodes, hence it's name Node.
913

10-
Child processes are spawned in a manner that is similar, but not identical, to [popen(3)](http://man7.org/linux/man-pages/man3/popen.3.html) from Linux programming using the `child_process.spawn()` function. This returns
11-
a `child` object (which is a `ChildProcess` object - which implements the `EventEmitter` API (link to events))
14+
Pipes for `stdin`, `stdout`, and `stderr` are established between the parent Node process and the spawned subprocess. The behaviour matches that of pipes in the shell.
1215

13-
## ChildProcess Events
16+
# `exec` vs `spawn`
1417

15-
The `child` processes communicates by emitting events to let the `parent` know what is going on.
18+
There are two main approaches to running child processesL `exec` and `spawn`.
1619

17-
| Event Name | Reason For Emitting |
18-
|--------------|-----------------------------------------------------------------------------|
19-
| `disconnect` | The parent process manually calls `child.disconnect` |
20-
| `error` | The process could not be spawned or killed. |
21-
| `exit` | The exit code for the child and the optional signalthat was used to terminate it. When null, imples the child process exited normally. |
22-
| `close` | The `stdio` streams of a child process get closed. |
23-
| `message` | This `child` process uses the `send` method to communicate with the parent. |
20+
| `exec` | `spawn` |
21+
|------------------------------------------------------------|-------------------------------------------------------------|
22+
| spawns a shell in which the command is executed | Does not spawn a shell |
23+
| buffers the data (waits until the process finishes and transfers all the data ) | Streams the data returned by the child process (data flow is constant) |
24+
| maximum data transfer 200kb (by default | has no data transfer size limit |
25+
26+
Typically, `spawn` is more suitable for long-running process with large outputs. spawn streams input/output with child process. `exec` buffered output in a small (by default 200K) buffer.
27+
28+
29+
## A Simple `exec`
2430

25-
## Spawn Example
31+
In this example, we will call the `ls` command to listwith the optional param `-l` to show a long list of details.
32+
<div class="repl-code">
2633

2734
```javascript
2835

36+
const { exec } = require('child_process');
37+
38+
// exec
39+
exec('ls -l', (err, stdout, stderr) => {
40+
console.log(stdout);
41+
});
42+
43+
```
44+
</div>
45+
46+
For more details of the options that can be passed to `exec`, please see https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
47+
48+
# spawn
49+
50+
The `spawn` method works by returning a new process. The process object that is returned has properties for each standard IO represented as a `Stream`: `.stdin` (`WriteStream`), `.stout` (`ReadStream`) and `.stderr` (`ReadStream`).
51+
52+
We will now implement the previous example using the `spawn` method:
53+
54+
<div class="repl-code">
55+
56+
```javascript
2957
const { spawn } = require('child_process');
58+
const ls = spawn('ls', ['-l']);
3059

31-
const child = spawn('ls');
60+
ls.stdout.on('data', (data) => {
61+
console.log(`stdout: ${data}`);
62+
});
3263

33-
child.on('exit', function (code, signal) {
34-
console.log(`child process exited with code ${code} and signal ${signal}`);
64+
ls.stderr.on('data', (data) => {
65+
console.error(`stderr: ${data}`);
3566
});
36-
child.on('exmessageit', function (code, signal) {
37-
console.log(`child process messaged with code ${code} and signal ${signal}`);
67+
68+
ls.on('close', (code) => {
69+
console.log(`child process exited with code ${code}`);
3870
});
3971

40-
spawn( ).stdout.pipe(process.stdout)
72+
```
73+
</div>
74+
75+
In this example we are listening to the `stout` and `stderr` streams for `data` events, as well as listening for a `close` event.
76+
77+
# spawn using pipes
78+
79+
We are going to run two child processes, and pipe the output from one as the input to another. We want to use `wc` (word count) to count the number of words in the output from the `ls` command we have been using so far. This is the same as running `ls -l | wc` on the Linux/Mac command line.
80+
81+
<div class="repl-code">
82+
83+
```javascript
84+
const { spawn } = require('child_process');
85+
const ls = spawn('ls', ['-l']);
86+
const wc = spawn('wc')
87+
88+
// pipe output from ls as input to wc
89+
ls.stdout.pipe(wc.stdin)
90+
91+
wc.stdout.on('data', (data) => {
92+
console.log(`wc stdout: ${data}`);
93+
});
94+
95+
wc.stderr.on('data', (data) => {
96+
console.error(`wc stderr: ${data}`);
97+
});
98+
99+
wc.on('close', (code) => {
100+
console.log(`wc child process wc exited with code ${code}`);
101+
});
41102

42103
```
104+
</div>
105+
106+
107+
# fork
108+
109+
110+
_To do_
111+
112+
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.
113+
114+
115+
116+
const exec_options = {
117+
cwd: null,
118+
env: null,
119+
encoding: 'utf8',
120+
timeout: 0,
121+
maxBuffer: 200 * 1024,
122+
killSignal: 'SIGTERM'
123+
};
43124

44-
_Not reviwewed/edited after this_
45125

46126

127+
## ChildProcess Events
128+
129+
The `child` processes communicates by emitting events to let the `parent` know what is going on.
130+
131+
| Event Name | Reason For Emitting |
132+
|--------------|-----------------------------------------------------------------------------|
133+
| `disconnect` | The parent process manually calls `child.disconnect` |
134+
| `error` | The process could not be spawned or killed. |
135+
| `exit` | The exit code for the child and the optional signalthat was used to terminate it. When null, imples the child process exited normally. |
136+
| `close` | The `stdio` streams of a child process get closed. |
137+
| `message` | This `child` process uses the `send` method to communicate with the parent. |
138+
139+
140+
_Not reviwewed/edited after this_
47141

48142

49143

50-
The returned process object will hold a property for each std type represented as a Stream: .stdin - WriteStream, .stout - ReadStream and finally .stderr - ReadStream. Accordingly, if we would like to run git log through a Node process and print it to the console we would do something like the following:
51144

52-
Every child process also gets the three standard stdio streams, which we can access using child.stdin, child.stdout, and child.stderr.
53145

54146
`spawn`
55147

56-
The first parameter is the path for an executable JavaScript file that starts the process, and the second argument is the arguments that will be passed into the process.
148+
The first parameter is the path for an executable file that starts the process, and the second argument is the arguments that will be passed into the process.
57149

58150

59151

@@ -76,8 +168,6 @@ So we can interact with the `ChildProcess` by listening for a series of events.
76168
77169
As you probably know, our typical OS has different processes running in the background. Each process is being managed by a single-core of our CPU and will run a series of calculations each time it is being ticked. As such, we can’t take full advantage of our CPU using a single process, we would need a number of processes that is at least equal to the number of cores in our CPU. In addition, each process might be responsible for running a series of calculations of different logic, which will give the end user a better control over the CPU’s behavior.
78170
79-
80-
81171
Why is this module called child_process and not just process? First of all, not to confuse with the main process instance global.process, and second, the child process is derived from the main process, which means that both can communicate - the main process will hold streams for the child process’s std types and they will both share an ipc channel (“Inter Process Communication” channel; more on that further this article).
82172
83173

0 commit comments

Comments
 (0)