Node.js runs in single-threaded, event-driven mode, which is good for improving performance via multiple child process.

Each child process has three stream objects:

  • child.stdin

  • child.stdout

  • child.stderr

All these three stream objects may share their parent’s stdio, or set to use their own stream object independently.

Node.js offers child_process module to create new child process:

  • execchild_process.exec use child process to execute shell command, and buffer the output for callback. This means the exec will buffer the whole returned value in buffer, usually you should limit the buffer in 200k, if not, the process will exit with Error: maxBuffer exceeded.

  • spawnchild_process.spawn use command line to create new process. spawn will return a stream object with stdout and stderr. We can use stdout stream to read the data returned from child process. stdout has event handles like data, end. You can use spawn when a large data will returned from child process.

  • forkchild_process.fork is the spawn in special mode(specify node to run the command). fork('./son.js') equals to spawn('node', ['./son.js']). Different from spawn, fork will build a message pipe between main and child process.

exec

1
2
3
4
5
6
7
8
9
10
11
const exec = require('child_process').exec
exec('dir', {encoding: 'utf-u'}, function(err, stdout, stderr) {
if (err) {
console.log(err.stack)
console.log('Error Code: ' + err.code)
console.log('Signal Received: ' + err.signal)
}
console.log('data: ' + stdout)
}).on('exit', function (code) {
console.log('child process exit with code: ' + code)
})

spawn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const spawn = require('child_process').spawn
const spawnedProcess = spawn('ping', ['127.0.0.1'], { encoding: 'utf-8'})

spawnedProcess.stdout.on('data', function (chunk) {
console.log(chunk.toString())
})

spawnedProcess.stderr.on('data', function (data) {
console.log(data)
})

spawnedProcess.on('close', function (code) {
console.log('close code: ' + code)
})

spawnedProcess.on('exit', function (code) {
console.log('exit code: ' + code)
fs.close(fd, function(err) {
if (err) {
console.error(err)
}
})
})

fork

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// parent.js
console.log('parent pid: ' + process.pid)
const fork = require('child_process').fork

const child = fork('./child.js')
console.log('fork return pid: ' + child.pid)
child.on('message', function (msg) {
console.log('parent recieve message: ' + JSON.stringify(msg))
})
child.send({
key: 'parent value',
})

// child.js
console.log('child pid: ' + process.pid)
process.on('message', function (msg) {
console.log('child recieve message: ' + msg)
})
process.send({
key: 'child value',
})