child_process 模块提供了衍生子进程的能力。 此功能主要由 child_process.spawn() 函数提供
以下是使用一些api的小栗子,看不懂也没关系。
const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`子进程退出,退出码 ${code}`);
});
默认情况下, stdin、 stdout 和 stderr 的管道会在父 Node.js 进程和衍生的子进程之间建立。
child_process.spawn() 方法会异步地衍生子进程,且不阻塞 Node.js 事件循环。
child_process.spawnSync() 函数则以同步的方式提供了等效的功能。
为方便起见, child_process 模块提供了 child_process.spawn() 和 child_process.spawnSync()的一些同步和异步的替代方法。
这些替代方法中的每一个都是基于 child_process.spawn() 或 child_process.spawnSync() 实现的。
这么看起来就是子进程“万物基于spawn”的意思了嘛
我们来看看其中的一些替代方法。
-
child_process.exec(): 衍生 shell 并且在 shell 中运行命令,当完成时则将 stdout 和 stderr 传给回调函数。
-
child_process.execFile(): 类似于 child_process.exec(),但是默认情况下它会直接衍生命令而不先衍生 shell。
-
child_process.fork(): 衍生新的 Node.js 进程,并调用指定的模块,该模块已建立了 IPC(操作系统知识) 通信通道,可以在父进程与子进程之间发送消息。
以下是不太重要的:
-
child_process.execSync(): child_process.exec() 的同步版本,会阻塞 Node.js 事件循环。
-
child_process.execFileSync(): child_process.execFile() 的同步版本,会阻塞 Node.js 事件循环。
总结起来感觉好像也没多少内容是不是?
汇总:
- child_process.spawn()
- child_process.exec()
- child_process.execFile()
- child_process.fork()
一个爸爸方法生出三个儿子方法,大家都是子进程内容。都要记住。
每个方法都返回一个 ChildProcess 实例。
这些实例继承了events模块,父进程注册监听器,子进程的生命周期中当发生某些事件时会触发。
child_process.exec() 和 child_process.execFile() 方法还允许指定可选的 callback 函数,当子进程终止时会被调用。
-
蛋疼的操作系统我还不会
child_process.exec() 和 child_process.execFile() 之间区别的重要性可能因平台而异。
在 Unix 类型的操作系统(Unix、Linux、macOS)上,child_process.execFile() 可以更高效,因为默认情况下它不会衍生 shell。
但是在 Windows 上, .bat 和 .cmd 文件在没有终端的情况下不能自行执行,因此无法使用 child_process.execFile() 启动。
当在 Windows 上运行时,要调用 .bat 和 .cmd 文件,可以使用设置了 shell 选项的 child_process.spawn()、或 child_process.exec()、或衍生 cmd.exe 并将 .bat 或 .cmd 文件作为参数传入(也就是 shell 选项和 child_process.exec() 所做的)。 在任何情况下,如果脚本的文件名包含空格,则需要加上引号。
本来我几乎看不懂,官方这次给的例子非常人道,秒懂了。 直接体验就好了:
// 仅在 Windows 上。
const { spawn } = require('child_process'); 引入子进程的爸爸模块
const bat = spawn('cmd.exe', ['/c', 'my.bat']); // 哦,原来如此,上面那句话就是这个意思去使用。这里返回了个子进程实例
bat.stdout.on('data', (data) => {
console.log(data.toString());
});
bat.stderr.on('data', (data) => {
console.error(data.toString());
});
bat.on('exit', (code) => {
console.log(`子进程退出,退出码 ${code}`);
});
// 上下都可以在windows上很好使用
const { exec, spawn } = require('child_process');
exec('my.bat', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
-----------------------------------------------------------
// 当文件名中包含空格的脚本时,需要多加引号哦:
const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true });
// 或:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
// ...
});
-
child_process.exec(command[, options][, callback])
- command: 要执行的命令这个我觉得不用多加解释。
- options(object)这里就不罗列字典了。
- callback 当进程终止时调用并传入输出
- error
- stdout
- stderr
衍生 shell,然后在 shell 中执行 command,并缓冲任何产生的输出(不用流)。 传给 exec 函数的 command 字符串会被 shell 直接处理。
传给回调的 stdout 和 stderr 参数会包含子进程的 stdout 和 stderr 输出。 默认情况下,Node.js 会将输出解码为 UTF-8 并将字符串传给回调。
const { exec } = require('child_process');
exec('cat *.js 文件 | wc -l', (error, stdout, stderr) => {
if (error) {
console.error(`执行的错误: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.error(`stderr: ${stderr}`);
});
-
child_process.execFile(file[, args][, options][, callback])
- file 要运行的可执行文件的名称或路径。
- args 字符串参数的列表。
- options (Object)
- callback
- error
- stdout
- stderr
child_process.execFile() 函数类似于 child_process.exec(),但默认情况下不会衍生 shell进程。 指定的可执行文件 file 会被直接衍生作为新的进程,使其比 child_process.exec() 稍微更高效。
const { execFile } = require('child_process');
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
-
child_process.fork(modulePath[, args][, options])
- modulePath 要在子进程中运行的模块。
- args 字符串参数的列表。
- options
child_process.fork() 方法是 child_process.spawn() 的特例,专门用于衍生新的 Node.js 进程。
与 child_process.spawn() 一样返回 ChildProcess 对象。 区别在于其以及与父进程创建好了信道了。 衍生的 Node.js 子进程独立于父进程,但两者之间建立的 IPC 通信通道除外。
每个进程都有自己的内存,带有自己的 V8 实例。 由于需要额外的资源分配,因此不建议衍生大量的 Node.js 子进程。
一时半会也写不完,有缘再改