nodejs 创建子进程

官方文档:https://nodejs.org/api/child_process.html

nodejs创建子进程主要有4个函数:

spawn、exec、execFile、fork

这四个函数均是异步函数,对应的同步函数为:spawnSync、execSync、execFileSync,其中 fork 没有对应的 forkSync

spawn是其他函数的基础,其他三个函数是在spawn上不同程度的封装,exec调用execFile,而execFile调用spawn,fork调用spawn

因此了解了spawn方法的使用,其他三个类似

spawn

先看一下定义如下:

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

command <string>: 运行的命令
args <string[]>: 运行命令所需的参数数组
options <Object>: 可选项
    cwd <string> | <URL>: 子进程的工作目录
    env <Object>: 环境变量键值对
    argv0 <string>: 显式设置发送给子进程的 argv[0] 的值
    stdio <Array> | <string>: 子进程标准输出流配置(详看:https://nodejs.org/api/child_process.html#optionsstdio)
    detached <boolean>: 是否独立与主进程
    uid <number>: 用户id
    gid <number>: 用户组id
    shell <boolean> | <string>: 命令是否在shell中运行
    signal <AbortSignal>: 允许使用信号量终止子进程
    timeout <number>: 子进程允许允许的最大时间
    killSignal <string> | <integer>: 超时或被杀死时设置的信号值,默认是'SIGTERM'

Returns: <ChildProcess> 子进程对象

调用一个python脚本示例如下:

const ls = spawn('ls', ['-lh', '/usr']);

// 获取标准输出流
subProcess.stdout.on('data', (data) => {
    console.log('标准输出 ---->  ', data.toString('utf8'));
})

// 获取标准错误输出流
subProcess.stderr.on('data', data => {
    console.log('标准错误输出 ---->  ', data.toString('utf8'));
});

// 子进程退出事件
subProcess.on('exit', (code, signal) => {
    console.log('子进程已退出,code:' + code + ', signal: ', signal);
});

// 子进程输出流关闭事件
subProcess.on('close', (code, signal) => {
    console.log('子进程输出流关闭,code:' + code + ', signal: ',signal);
});

execFile

参数构成:child_process.execFile(file[, args][, options][, callback])

与exec类似,但默认不会启动一个shell去执行命令,即直接创建子进程运行可执行文件,因此比exec稍微更高效

const child = execFile('ls', ['-l'], (error, stdout, stderr) => {
  if (error) {
    throw error;
  }
  console.log(stdout);
});

exec

参数构成:child_process.exec(command[, options][, callback])

创建子进程时,会开启一个shell,并在shell里运行命令,缓冲任何生成的输出。

执行的命令和参数直接构成一个字符串,不需要像spawn、execFile那样命令参数分开

简单示例:

exec('ls -lh /usr', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
});

exec() 内部实际是调用 execFile() 。默认会创建shell并在其中执行命令。这在windows更友好,原因是 windows下,.bat和.cmd文件必须依靠于一个shell才可以允许运行。

fork

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

基于spawn,专门用于构建nodejs子进程。

返回的 ChildProcess 对象将有一个额外的内置通信通道,允许消息在父进程和子进程之间来回传递

通常下,生成的 Node.js 子进程独立于父进程,但若在两者之间建立了 IPC 通信通道除外。

每个子进程都有自己的内存,有自己的 V8 实例,由于需要额外的资源分配,因此不建议生成大量子 Node.js 进程

使用自定义 execPath 启动的 Node.js 进程将使用子进程上的环境变量 NODE_CHANNEL_FD 标识的文件描述符 (fd) 与父进程通信

const child = child_process.fork('index.js', [''], {})
child.stdout.on('data', (data) => {
    console.log('data ---->  ', data)
});
### 如何在 Node.js 中进行子进程调度 在 Node.js 中,可以利用 `child_process` 模块来实现子进程创建和调度。通过这个模块,父进程能够启动新的子进程,并与其交互,例如发送消息、接收数据或者终止子进程。 以下是具体的使用方法及其示例: #### 创建子进程 Node.js 的 `child_process` 模块提供了多种方式来创建子进程,其中最常用的是 `spawn` 和 `fork` 方法。下面分别介绍这两种方法的使用场景和代码示例。 ##### 使用 `spawn` 方法 `spawn` 是一种通用的方法,用于启动外部可执行文件或脚本作为子进程。它适合于需要实时处理标准输入/输出流的情况。 ```javascript // parent.js const { spawn } = require('node:child_process'); // 启动一个新的子进程,运行 child.js 文件 const child = spawn('node', ['child.js']); // 监听子进程的标准输出 child.stdout.on('data', (data) => { console.log(`子进程输出: ${data}`); }); // 监听子进程的标准错误输出 child.stderr.on('data', (data) => { console.error(`子进程错误: ${data}`); }); // 当子进程退出时触发 child.on('close', (code) => { console.log(`子进程已退出,退出码为 ${code}`); }); ``` ```javascript // child.js process.stdin.setEncoding('utf8'); process.stdin.on('data', (chunk) => { console.log(`接收到的数据: ${chunk}`); }); console.log('我是子进程!'); setTimeout(() => { process.exit(0); }, 3000); ``` 上述代码展示了如何通过 `parent.js` 来启动 `child.js` 并监听其输出[^1]。 ##### 使用 `fork` 方法 `fork` 是 `spawn` 的特化版本,专门用来启动另一个 Node.js 脚本作为子进程。相比 `spawn`,`fork` 提供了更高级的功能,比如内置的消息传递机制。 ```javascript // parent.js const { fork } = require('node:child_process'); // 启动一个新的子进程,运行 child.js 文件 const child = fork('./child.js'); // 发送消息给子进程 child.send({ hello: 'world' }); // 接收来自子进程的消息 child.on('message', (msg) => { console.log('从子进程中接收到:', msg); }); // 当子进程退出时触发 child.on('exit', (code) => { console.log(`子进程已退出,退出码为 ${code}`); }); ``` ```javascript // child.js process.on('message', (msg) => { console.log('接收到消息:', msg); // 给父进程发回一条消息 process.send({ reply: 'acknowledged!' }); }); console.log('我是子进程!'); ``` 这段代码演示了父子进程之间的双向通信能力。 #### 控制子进程生命周期 除了创建子进程外,还需要掌握控制其生命周期的能力,包括向子进程发送信号以及优雅地关闭它们。 - **发送信号** 可以通过调用 `kill` 方法向子进程发送信号,默认情况下会发送 `SIGTERM` 信号通知子进程准备结束。 ```javascript child.kill('SIGHUP'); // 发送 SIGHUP 信号 ``` - **捕获信号** 子进程应注册相应的事件处理器以便响应这些信号并清理资源后再退出。 ```javascript process.on('SIGTERM', () => { console.log('接收到 SIGTERM 信号...'); cleanupResources(); process.exit(0); }); ``` 以上操作确保了即使遇到异常情况也能安全释放占用的系统资源。 #### 总结 借助 Node.js 的 `child_process` 模块,开发者不仅可以轻松地管理多个并发任务,还能充分利用多核 CPU 架构的优势提升应用性能。无论是简单的命令行工具还是复杂的分布式计算框架,都可以基于此构建高效的解决方案[^2]。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值