子进程是Nodejs的核心Api,如果你会shell命令,它会有非常大的帮助,或者你喜欢编写前端工程化工具之类,它也有很大的用处,以及处理CPU密集型应用。
创建子进程
Nodejs创建子进程共有7个API,带Sync的是同步API,不加的是异步API:
spwan
:执行命令exec
:执行命令execFile
:执行可执行文件fork
:创建node子命令execSync
:执行命令 同步执行execFileSync
:执行可执行文件 同步执行spawnSync
:执行命令 同步执行exec()
是异步的方法 可以帮我们执行shell命令 或者跟软件交互 回调函数返回一个buffer。
我们首先介绍exec()
和execSync()
命令的第一个用途:执行shell命令
我们尝试使用exec()
执行shell命令输出node版本
const { exec } = require("child_process");
exec("node -v", (err, stdout, stderr) => {
if (err) {
console.log(err);
return;
}
// 返回的是buffer 转成字符后输出
console.log("exec", stdout.toString()); // v16.17.0
});
execSync()
是同步的方法 一般同步的用的比较多 异步写法太麻烦了。
这两种方法都比较适合执行较小的shell命令 想要立马拿到结果的shell命令。
但是这两种方法有个缺点:返回的字节上限200kb 超出就会报错。
使用execSync()
执行shell命令输出node版本
const { execSync } = require("child_process");
const nodeVersion = execSync("node -v");
console.log("execSync", nodeVersion.toString()); // v16.17.0
使用execSync()
创建文件夹test:因为mkdir
命令没有返回值,因此不用接收结果
execSync("mkdir test"); // 可以看到当前目录中多了一个test文件夹
下面我们再介绍exec()
和execSync()
命令的第二个用途:跟软件交互
这里就以execSync()
为例,尝试打开chrome的百度页面:
execSync("start chrome http://www.baidu.com");
运行此代码可以成功百度页,下面我们再试试使用execSync()
启动电脑上的steam,我们需拿到steam运行程序的路径:
execSync("D:\\Steam\\Steam.exe");
运行代码后等待一会【启动应用程序需要时间】可以看到steam成功启动,需要注意的是:commonjs
规范下路径需要双反斜杠进行转码。
spawn()
和spawnSync()
也是用来执行shell命令,并且返回的字节大小没有上限 因为返回的是个流 并且是实时返回的,而exec()
和execSync()
需要等待shell命令运行结束,拿到所有的返回结果的才算结束。
spawnSync()
用的比较少。
这里我们扩展一下netStat
的相关知识:
shell命令netStat
是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。
下面我们先使用execSync()
执行shell命令netStat
获取本机网络状态。
const { execSync } = require("child_process");
const netstat = execSync("netstat");
console.log(netstat.toString()); // 需要等待运行完才输出
可以看到网络状态并不会实时的一条一条的输出,下面我们使用spawn()
执行shell命令netStat
获取本机网络状态。
spwan()
的用法和exec()
差异不小,它需要从返回结果中解构出stdout
,并使用on
监听返回的数据,并且每一条数据都是buffer类型,需要转字符输出才能看得懂,另外,spwan()
不仅能实时输出运行结果,使用on
还能监听命令运行结束,这是exec
所不具有的。
const { spawn } = require("child_process");
const { stdout } = spawn("netstat");
stdout.on("data", (data) => {
console.log(data.toString());
});
stdout.on("close", () => {
console.log("结束了");
});
可以看到控制台实时输出了每一个网络的当前状态。
增加shell命令参数的格式和exec()
不同,exec()
是直接在shell命令后面增加,就和在命令行输入一样,spawn()
增加shell命令参数的格式如下:
const { spawn } = require("child_process");
const { stdout } = spawn("netstat", ["-a"]); // 增加shell命令参数
stdout.on("data", (data) => {
console.log(data.toString());
});
stdout.on("close", () => {
console.log("结束了");
});
参考博客: