跳到主要内容

进程创建

2024年04月09日
柏拉文
越努力,越幸运

一、认识


Node 提供了 child_process 模块来创建子进程,方法有:

  1. Spawning .bat and .cmd files on Windows:

  2. child_process.exec(command[, options][, callback]): 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。exec() 方法返回最大的缓冲区,并等待进程结束,一次性返回缓冲区的内容。 child_process.exec 比较适合开销比较小的任务,因为它是执行完之后才会调用回调把信息打印出来。

  3. child_process.execFile(file[, args][, options][, callback])

  4. child_process.fork(modulePath[, args][, options]): 是 spawn() 的特殊形式,用于在子进程中运行的模块,如 fork('./son.js') 相当于 spawn('node', ['./son.js']) 。与 spawn 方法不同的是,fork会在父进程与子进程之间,建立一个通信管道,用于进程之间的通信。child_process.forkspawn() 方法的特殊形式,用于创建进程。返回的对象除了拥有 ChildProcess 实例的所有方法,还有一个内建的通信信道。

  5. child_process.spawn(command[, args][, options]): 使用指定的命令行参数创建新进程。child_process.spawn 使用指定的命令行参数创建新进程。spawn() 方法返回流 (stdout & stderr),在进程返回大量数据时使用。进程一旦开始执行时 spawn() 就开始接收响应。child_process.spawn 适合执行耗时任务, 需要不断打印日志, 因为是通过流的方式输出结果。比如在安装依赖。

通过 child_process 模块,可以实现1个主进程,多个子进程的模式,主进程称为master进程,子进程又称为工作进程。

二、创建同步进程


2.1 child_process.execFileSync(file[, args][, options])

2.2 child_process.execSync(command[, options])

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

三、创建异步进程


3.1 Spawning .bat and .cmd files on Windows

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

child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式返回。exec() 方法返回最大的缓冲区,并等待进程结束,一次性返回缓冲区的内容。

child_process.exec 比较适合开销比较小的任务,因为它是执行完之后才会调用回调把信息打印出来。

语法

child_process.exec(command[, options], callback)
  • command: 字符串, 将要运行的命令,参数使用空格隔开

  • options:

    • cwd: 字符串,子进程的当前工作目录

    • env: 对象 环境变量键值对

    • encoding: 字符串,字符编码(默认: 'utf8')

    • shell: 字符串,将要执行命令的 Shell(默认: 在 UNIX 中为/bin/sh, 在 Windows 中为cmd.exe, Shell 应当能识别 -c开关在 UNIX 中,或 /s /c 在 Windows 中。 在Windows 中,命令行解析应当能兼容cmd.exe)

    • timeout: 数字,超时时间(默认: 0)

    • maxBuffer: 数字, 在 stdout 或 stderr 中允许存在的最大缓冲(二进制),如果超出那么子进程将会被杀死 (默认: 200*1024)

    • killSignal: 字符串,结束信号(默认:'SIGTERM')

    • uid: 数字,设置用户进程的 ID

    • gid: 数字,设置进程组的 ID

  • callback: 回调函数,包含三个参数error, stdoutstderr

用法

master.js

const path = require("path");
const { exec } = require("child_process");

const workerProcess01 = exec(`node ${path.resolve(__dirname, "support.js")} 01`, function(error, stdout, stderr){
if(error){
console.log(error.stack);
console.log('Error code: '+error.code);
console.log('Signal received: '+error.signal);
}

console.log("stdout: " + stdout);
console.log("stderr: " + stderr);
});

workerProcess01.on("exit", function(code){
console.log("子进程已退出,退出码 " + code);
});


const workerProcess02 = exec(`node ${path.resolve(__dirname, "support.js")} 02`, function(error, stdout, stderr){
if(error){
console.log(error.stack);
console.log('Error code: '+error.code);
console.log('Signal received: '+error.signal);
}

console.log("stdout: " + stdout);
console.log("stderr: " + stderr);
});

workerProcess02.on("exit", function(code){
console.log("子进程已退出,退出码 " + code);
});

support.js

console.log("进程" + process.argv[2] + "执行完毕")

3.3 child_process.execFile(file[, args][, options][, callback])

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

child_process.forkspawn() 方法的特殊形式,用于创建进程。返回的对象除了拥有 ChildProcess 实例的所有方法,还有一个内建的通信信道。

语法

child_process.fork(modulePath[, args][, options])
  • modulePath: String,将要在子进程中运行的模块

  • args: Array 字符串参数数组

  • options:

    • cwd String: 子进程的当前工作目录

    • env Object: 环境变量键值对

    • execPath String: 创建子进程的可执行文件

    • execArgv Array: 子进程的可执行文件的字符串参数数组(默认: process.execArgv)

    • silent Boolean: 如果为true,子进程的stdinstdoutstderr将会被关联至父进程,否则,它们将会从父进程中继承。(默认为:false)

    • uid Number: 设置用户进程的 ID

    • gid Number: 设置进程组的 ID

用法

const path = require("path");
const { fork } = require("child_process");

const workerProcess01 = fork(path.resolve(__dirname, "support.js"), ["01"]);
// 主进程向子进程发送消息
workerProcess01.send("hello support process", () => {
// 发送完消息后,需要关闭两个进程之间的通信,不然进程会一直等待,即光标会一直闪烁
workerProcess01.disconnect();
});
// 主进程接收子进程消息
workerProcess01.on("message", (msg) => {
console.log(msg);
});

workerProcess01.on("close", function (code) {
console.log("子进程已退出,退出码 " + code);
});

const workerProcess02 = fork(path.resolve(__dirname, "support.js"), ["02"]);
workerProcess02.on("close", function (code) {
console.log("子进程已退出,退出码 " + code);
});

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

child_process.spawn 使用指定的命令行参数创建新进程。spawn() 方法返回流 (stdout & stderr),在进程返回大量数据时使用。进程一旦开始执行时 spawn() 就开始接收响应。

child_process.spawn 适合执行耗时任务, 需要不断打印日志, 因为是通过流的方式输出结果。比如在安装依赖。

语法

child_process.spawn(command[, args][, options])
  • command: 将要运行的命令

  • args: Array 字符串参数数组

  • options:

    • cwd String: 子进程的当前工作目录

    • env Object: 环境变量键值对

    • stdio Array|String: 子进程的 stdio 配置

    • detached Boolean: 这个子进程将会变成进程组的领导

    • uid Number: 设置用户进程的 ID

    • gid Number: 设置进程组的 ID

用法

master.js

const path = require("path");
const { spawn } = require("child_process");

const workerProcess01 = spawn("node", [
path.resolve(__dirname, "support.js"),
"01",
]);
workerProcess01.stdout.on("data", function (data) {
console.log("stdout: " + data);
});
workerProcess01.stderr.on("data", function (data) {
console.log("stderr: " + data);
});
workerProcess01.on("close", function (code) {
console.log("子进程已退出,退出码 " + code);
});

const workerProcess02 = spawn("node", [
path.resolve(__dirname, "support.js"),
"02",
]);
workerProcess02.stdout.on("data", function (data) {
console.log("stdout: " + data);
});
workerProcess02.stderr.on("data", function (data) {
console.log("stderr: " + data);
});
workerProcess02.on("close", function (code) {
console.log("子进程已退出,退出码 " + code);
});

support.js

console.log("进程" + process.argv[2] + "执行完毕")