Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Node .js sub-processes


May 10, 2021 Node.js


Table of contents


Sub-processes

Node.js is a single-threaded model architecture that enables efficient CPU utilization while limiting the use of multiple core CPUs, so Node.js child_process for multithreaded multi-core CPU use.

稳定性: 3 - 稳定

Node child_process popen(3)

It can pass data through stdin stdout a stderr manner.

Note: Some programs use internal linear buffering I/O, which does not prevent node .js, but the data you send to child processes is not immediately canceled.

You can require('child_process').spawn() using require require('child_process').fork() There is a difference between the two approaches, which are explained below.

It's more efficient to see the technology counterparts during development.

Class: ChildProcess

ChildProcess is an EventEmitter.

Sub-processes have three related child.stdin child.stdout child.stderr They may be shared with the stdiostreams of the parent process, or they may be independent objects.

The ChildProcess class cannot be called directly, spawn() exec() execFile() fork() of child processes.

Event: 'error'

  • err Object) error.

Occurs at:

  1. The process could not be created.
  2. The process could not be killed.
  3. Whatever the cause, sending a message to the child process failed.

Note: exit can be called after an error occurs, or they may not be called, so if you listen for both events to trigger a function, remember that the prevention function is called twice.

Refer ChildProcess#kill() ChildProcess#send()

Event: 'exit'

  • code s Number exit code, valid until normal exit.
  • signal is killed by the parent process, it is a signal to the child process

This event is triggered at the end of the child process. I f the child process terminates code is the final exit code, otherwise it null If the signal caused by signal is a string, otherwise it is null

Note: The stdio flow of the child process may still be on mode.

Note that node 'SIGINT' 'SIGTERM so when the signal comes, they do not terminate but exit.

Rely on waitpid(2)

Event: 'close'

  • code s Number exit code, valid until normal exit.
  • signal is killed by the parent process, it is a signal to the child process.

This event is triggered when all stdio streams in the child process are closed. To be separated from 'exit' because multiple processes can share a stdio stream.

Event: 'disconnect'

This event is triggered after the .disconnect() the parent or child process. Messages are not sent to each other after disconnection, .connected property value is false.

Event: 'message'

  • message (Object) A parsed JSON object, or an original value.
  • sendHandle (Handle object) A Socket or Server object

The .send(message, [sendHandle])

child.stdin

  • {Stream object}

The stdin process Writable Stream (writeable stream). If the child process is waiting for input, it pauses until it end()

child.stdin is child.stdio[0] Both point to the same object, or null.

child.stdout

  • {Stream object}

The stdout is Readable Stream (readable stream).

child.stdout is child.stdio[1] Both point to the same object, or null.

child.stderr

  • {Stream object}

The stderr is Readable Stream (writeable stream).

child.stderr is child.stdio[2] Both point to the same object, or null.

child.stdio

  • {Array}

The pipeline array of child processes corresponds to the content order set to 'pipe' the stdio of spawn.

Note that streams can also be represented by ChildProcess.stdin, ChildProcess.stdout, and ChildProcess.stderrNote, respectively.

In the following example, only the fd 1 the child process is set to the pipe pipeline, so child.stdio[1] of the parent process is a stream and the other values in the 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}

The PID of the child process.

Example:

var spawn = require('child_process').spawn,
    grep  = spawn('grep', ['ssh']);

console.log('Spawned child pid: ' + grep.pid);
grep.stdin.end();

child.connected

  • When '.disconnect' is called, it is set to false

If .connected the message is no longer available.

child.kill([signal])

  • signal {String}

Send a signal to the child process. If there are no 'SIGTERM' sent, see signal(7)

var spawn = require('child_process').spawn,
    grep  = spawn('grep', ['ssh']);

grep.on('close', function (code, signal) {
  console.log('child process terminated due to receipt of signal '+signal);
});

// send SIGHUP to process
grep.kill('SIGHUP');

The 'error' event is triggered when the signal cannot be transmitted. Sending a signal to a 'error' because it is possible that piD (process ID) has been reassigned to other processes, the signal is sent to a new process, and it is impossible to imagine what would happen.

Note: When a function calls kill signal, it doesn't actually kill the process, it just sends a signal to the process.

See kill(2)

child.send(message[, sendHandle])

  • message {Object}
  • sendHandle {Handle object}

When child_process.fork() you can write data to the child process child.send(message, [sendHandle]) which 'message'

For example:

var cp = require('child_process');

var n = cp.fork(__dirname + '/sub.js');

n.on('message', function(m) {
  console.log('PARENT got message:', m);
});

n.send({ hello: 'world' });

The code for the child 'sub.js' :

process.on('message', function(m) {
  console.log('CHILD got message:', m);
});

process.send({ foo: 'bar' });

The process object in process send() method that fires when it receives information through the channel and returns the object.

Note: The parent and child send() should not be used to send large chunks of data (which can be child_process.spawn

However, it is a special {cmd: 'NODE_foo'} All NODE_ prefixes are not triggered because they are the internalMessage avoiding this feature as much as possible.

The sendHandle property in child.send() is used to send TCP services or socket objects to other processes, which use the received message to the message event.

Failure to send a message triggers an 'error' such as a child process that has exited.

Example: Send the server object

Here are some examples:

var child = require('child_process').fork('child.js');

// Open up the server object and send the handle.
var server = require('net').createServer();
server.on('connection', function (socket) {
  socket.end('handled by parent');
});
server.listen(1337, function() {
  child.send('server', server);
});

The child process will receive this server object:

process.on('message', function(m, server) {
  if (m === 'server') {
    server.on('connection', function (socket) {
      socket.end('handled by child');
    });
  }
});

Note that now that the parent-child process shares a server, some connections are processed by the parent process and some by the child process.

dgram server, the workflow is the same, listening to message connection server.bind server.listen (UNIX platform only currently supported)

Example: Send socket objects

The following is an example of sending a socket object. H e will create two subthreads and process the connection at the same 74.125.127.100 as a VIP to a special subprocess and the other to the normal process. v ar normal=require('child_process').fork('child.js', ['normal']); var special = require('child_process').fork('child.js', ['special']);

// Open up the server and send sockets to child
var server = require('net').createServer();
server.on('connection', function (socket) {

  // if this is a VIP
  if (socket.remoteAddress === '74.125.127.100') {
    special.send('socket', socket);
    return;
  }
  // just the usual dudes
  normal.send('socket', socket);
});
server.listen(1337);

child.js is as follows:

process.on('message', function(m, socket) {
  if (m === 'socket') {
    socket.end('You were handled as a ' + process.argv[2] + ' person');
  }
});

Note that when the socket is sent to a child process, if the socket is destroyed, the parent process no longer .connections null In this case, .maxConnections

child.disconnect()

Turning off all IPC channels between parent and child processes allows the child process to exit gracefully. When this method is called, the .connected flag in .connected process false more messages can be sent.

The 'disconnect' event is triggered when there are no messages in the process to process.

Note that in the case of sub-processes and IPC fork() you can process.disconnect() to close it.

Create asynchronous processing

These methods follow common asynchronous processing patterns, such as callbacks, or return an event handling.

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

  • command to run
  • args (Array) string parameter table
  • options {Object}
    • cwd of the cwd(String) sub-process
    • env (Object) environment
    • stdio {Array| The stdio configuration of the String?sub-process.
    • customFds (Array) Deprecated is a file marker used by the sub-process stdio.
    • detached sub-process will become the leader of a process group.
    • uid Number sets the ID of the user process. (See setuid (2))
    • gid Number sets the ID of the process group. (see setgid (2))
  • Back: childProcess object

A command is published with the specified args is a command line argument. If ignored, args is an empty array.

The third parameter is used to specify additional settings, the default:

{ cwd: undefined,
  env: process.env
}

Cwd is used in the child cwd which, if not specified, is inherited by default from the current working directory.

Use env the environment variables that are visible to the new process. The default process.env

For example, ls -lh /usr to stdout stderr exit code:

var spawn = require('child_process').spawn,
    ls    = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});

ls.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});

ls.on('close', function (code) {
  console.log('child process exited with code ' + code);
});

For example, a very sophisticated way to perform the 'ps ax | grep ssh'

var spawn = require('child_process').spawn,
    ps    = spawn('ps', ['ax']),
    grep  = spawn('grep', ['ssh']);

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

ps.stderr.on('data', function (data) {
  console.log('ps stderr: ' + data);
});

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

grep.stdout.on('data', function (data) {
  console.log('' + data);
});

grep.stderr.on('data', function (data) {
  console.log('grep stderr: ' + data);
});

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

options.stdio

stdio be one of several parameters:

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

child_process.spawn() parameter in the 1990s.spawn() is an array that corresponds to the fd of the child process, and its value is as follows:

  1. 'pipe' - Creates a pipe between the parent and child processes. T he parent process side of the child_process the parent process in the form of a property of the child process, such as ChildProcess.stdio[fd] Pipelines created for fds 0 - 2 can also be accessed independently through ChildProcess.stdin, ChildProcess.stdout, and ChildProcess.stderr.

  2. 'ipc' - Creates an IPC channel between the parent and child processes to pass message/file descriptors. A child process can have up to 1 IPC stdio file identity. S etting this option activates the ChildProcess.send() method. I f a child process writes a JSON message to this file identity, ChildProcess.on is triggered. If the child process is .js Node, the IPC channel activates process.send() and process.on.

  3. 'ignore' set this file identity in sub-processes, be aware that Node always opens fd 0-2 for its spawn process. If any of them are ignored, node will /dev/null assign fd to the child process.

  4. Stream Object - Shares a ttty, file, socket, or brush readable or writeable stream to sub-processes. The file identity at the bottom of the stream is copied in a sub-process to the file identity (fd) corresponding to the stdio array index.

  5. Positive number - This integer is understood to be a file identity that is opened in the parent process and is shared with child processes, similar to a Stream object.

  6. null undefined - use the default value. F or stdio fds 0, 1 and 2 (in other words, stdin, stdout, or stderr), the pipe pipe is established. For fd 3 and later, the default is 'ignore'

For example:

var spawn = require('child_process').spawn;

// 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 present a
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

options.detached

If the detached the child process will be treated as a leader for the new process group, which allows the child process to continue running after the parent process exits.

By default, the parent process waits for the detached child process to exit. To prevent the parent process from waiting for such a child process, call the child.unref() method, which will not be included in the event loop reference count of the parent process.

detaching a long-running process and pointing the output back to the file:

 var fs = require('fs'),
     spawn = require('child_process').spawn,
     out = fs.openSync('./out.log', 'a'),
     err = fs.openSync('./out.log', 'a');

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

 child.unref();

When detached option to start a long-running process, the process does not remain running in the background unless he provides a stdio that is not connected to the parent process. If the stdio of the parent stdio the child process continues to control the terminal.

options.customFds

Abandoned, customFds you to specify a specific file descriptor as the stdio T he API cannot be ported to all platforms and is therefore discarded. customFds you can hook the new process's stdin stdout stderr to an existing stream; Use at your own risk.

See child_process.exec() child_process.fork()

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

  • command to execute, space split
  • options {Object}
    • cwd of the cwd s string sub-process
    • env s Object environment variables
    • encoding (By default: 'utf8')
    • shell (the default is: '/bin/sh' UNIX, 'cmd.exe' Windows, which must receive -c or /s /c Windows. O n Windows, command resolution must be cmd.exe )
    • timeout (default: 0)
    • maxBuffer (Number) (default: 200*1024 )
    • killSignal (String' (default: 'SIGTERM')
    • uid Number sets the user ID in the process. ( See setuid (2).) )
    • gid Number sets the group identity in the process. ( See setgid (2).) )
  • callback the callback process terminates
    • error {Error}
    • stdout {Buffer}
    • stderr {Buffer}
  • Back: ChildProcess object

Execute the command in the shell and buffer the output.

var exec = require('child_process').exec,
    child;

child = exec('cat *.js bad_file | wc -l',
  function (error, stdout, stderr) {
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
    if (error !== null) {
      console.log('exec error: ' + error);
    }
});

The callback (error, stdout, stderr) I f successful, the error is null If it fails, error Error error.code is equal to the child process exit error.signal to the signal name that ends the process.

The second parameter can set some options. The default is as follows:

{ encoding: 'utf8',
  timeout: 0,
  maxBuffer: 200*1024,
  killSignal: 'SIGTERM',
  cwd: null,
  env: null }

If timeout than 0, the child process will be terminated when it runs longer than timeout killSignal (default: 'SIGTERM' can kill sub-processes. maxBuffer the maximum amount of data for stdout or stderr, which will be killed if the number of sub-processes exceeds.

(file[, args][, options][, callback])

  • file the file name of the program you want to run
  • args (Array) parameter list
  • options {Object}
    • cwd of the cwd(String) sub-process
    • env (Object) environment
    • encoding (By default: 'utf8')
    • timeout (default: 0)
    • maxBuffer (Number) (default: 200 x 1024)
    • killSignal (String' (default: 'SIGTERM')
    • uid Number sets the user ID in the process. ( See setuid (2).) )
    • gid Number sets the group identity in the process. ( See setgid (2). )
  • callback the callback process terminates
    • error {Error}
    • stdout {Buffer}
    • stderr {Buffer}
  • Back: ChildProcess object

Similar child_process.exec() difference is that this is a specified file, so it is child_process.exec with the same parameters.

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

  • modulePath runs in a modulePath sub-process
  • args (Array) parameter list
  • options {Object}
    • cwd of the cwd(String) sub-process
    • env (Object) environment
    • execPath (String) executes the file path
    • execArgv (Array) execution parameters (default: process.execArgv )
    • silent the child process will use the parent process's stdin, stdout, and stderr, otherwise it will inherit from the parent process, see the "pipe" and "inherit" options in stdio parameter of spawn() for more details (default false)
    • uid Number sets the user ID in the process. ( See setuid (2).) )
    • gid Number sets the group identity in the process. ( See setgid (2).) )
  • Back: ChildProcess object

This spawn() for deriving the Node process. I n addition to having all the methods of the child process, its return object also has a built-in communication channel. See child.send(message, [sendHandle])

These Nodes are completely new V8 instantiations, assuming that each Node requires a minimum of 30ms of startup time, 10mb of storage space, and it is, predictally, unrealistic to create thousands of Nodes.

The execPath property in the options object can be used to execute a file (not the node to create child processes. T his needs to be used with care, and by default fd represents the NODE_CHANNEL_FD NODE_CHANNEL_FD variables. The input and output of the fa are JSON objects that are split in rows.

Create a synchronization process

These methods are synchronized, which means that he blocks the event loop and pauses execution of the code until the spawned process exits.

Synchronization methods simplify the task process, such as simplifying the initial loading/processing process in the application.

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

  • command to be executed by the command
  • args (Array) parameter list
  • options {Object}
    • cwd of the cwd s string sub-process
    • input {String| The value passed by Buffer to the spawned process, which stdio[0]
    • stdio configuration of the stdio sub-process of the stdio.array.
    • env s Object environment variables
    • uid Number sets the ID of the user process. ( See setuid (2).) )
    • gid Number sets the ID of the process group. ( See setgid (2). )
    • timeout milliseconds that a timeout sub-process runs. (Default: undefined)
    • killSignal is used to terminate the signal of the child process. (Default: 'SIGTERM')
    • maxBuffer {Number}
    • encoding stdio inputs and outputs are encoded. (Default: 'buffer')
  • Back: s Object
    • pid of the pid of the child process of the pid
    • output of results output by output (Array) stdio
    • stdout {Buffer| The output[1]
    • stderr {Buffer| The output[2]
    • status code for the status s.number?sub-process
    • signal are used to kill sub-process signals
    • error code for error-error sub-process errors or timeouts

spawnSync until the child process is closed. T imed out or received killSignal and will not return until the process exits completely. The process does not SIGTERM signal until the child process exits completely.

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

  • command to be executed by the command
  • args (Array) parameter list
  • options {Object}
    • cwd of the cwd s string sub-process
    • input {String| The value passed to the spawned process, which overrides stdio[0]
    • stdio configuration of the stdio sub-process of the stdio (Array) sub-process. (Default: 'pipe')
      • stderr is output to the parent process's stderr unless stdio
    • env s Object environment variables
    • uid Number sets the ID of the user process. ( See setuid (2).) )
    • gid Number sets the ID of the process group. ( See setgid (2). )
    • timeout milliseconds that the timeout process runs. (Default: undefined)
    • killSignal is used to terminate the signal of the child process. (Default: 'SIGTERM')
    • maxBuffer {Number}
    • encoding stdio inputs and outputs are encoded. (Default: 'buffer')
  • Back: sd buffer| S tring is from the command's stdout

execFileSync completely. T imed out or received killSignal and will not return until the process exits completely. The process does not SIGTERM signal until the child process exits completely.

If the process times out, or exits abnormally, the method throws an exception. Error contains the child_process.spawnSync

child_process.execSync(command[, options])

  • command to be executed by the command
  • options {Object}
    • cwd of the cwd s string sub-process
    • input {String| The value passed by Buffer to the spawned process, which stdio[0]
    • stdio configuration of the stdio sub-process of the stdio.array. (Default: 'pipe')
      • stderr output to the parent process's 'stderr' by default unless stdio
    • env s Object environment variables
    • uid Number sets the ID of the user process. ( See setuid (2).) )
    • gid Number sets the ID of the process group. ( See setgid (2). )
    • timeout milliseconds that the timeout process runs. (Default: undefined)
    • killSignal is used to terminate the signal of the child process. (Default: 'SIGTERM')
    • maxBuffer {Number}
    • encoding stdio inputs and outputs are encoded. (Default: 'buffer')
  • Back: sd buffer| S tring is from the command stdout

execSync does not return until the child process exits completely. T imed out or received killSignal and will not return until the process exits completely. The process does not SIGTERM signal until the child process exits completely.

If the process times out, or exits abnormally, the method throws an exception. Error contains the child_process.spawnSync

That's .js node's official documentation about sub-processes.