目录
学习路径
官方文档
中文版:http://nodejs.cn/api/child_process.html
什么是进程
进程 Process 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
进程的概念主要有两点:
·第一:进程是一个实体。每一个进程都有它自己的地址空间。
·第二:进程是一个“执行中的程序”,存在嵌套关系。
node多进程核心其实就是创建一个子进程,这个子进程会依附在当前node进程下面。node多进程开发中核心应用的类是child_process内置库。我们在child_process中创建的进程就是Node.js的子进程。
ps -ef 把所有当前操作系统中的进程全部打开
| grep node 筛选node进程
| grep 26309 筛选26309进程
UID 当前用户获得权限的ID
PID 进程ID
PPID 父进程ID
/sbin/launchd 桌面应用程序 PID为 1
child_process 用法
异步:
exec 执行shell脚本,和普通命令相比 可以是一个连续的语句
execFile 执行一个文件,可传入 命令入参['xx']
fork 用在断点续传、下载复杂场景上面。可以双向通讯,上面两个单向。
spawn
同步:
execSync 简单命令通常会使用。可能会拼接进风险命令。
execFileSync 安全角度考虑比execSync好点
spawnSync 会返回一个对象
小知识点:
path.resolve() 中使用相对路径 ./ ,效果是相对命令执行的路径(在哪个目录下执行的命令)。用__dirname,效果是代码文件所在的路径。path.resolve() 会注入两个全局变量__filename、__dirname。
chmod +x bin/process/test.shell 给文件加个可执行权限
exec & execFile 用法
const cp = require('child_process')
const path = require('path')
cp.exec(path.resolve(__dirname, 'test.shell'), {
cwd: path.resolve('..'), //在此路径下执行命令
timeout: 0
}, function(err, stdout, stderr) {
console.log(err),
console.log(stdout),
console.log(stderr)
})
cp.execFile(path.resolve(__dirname, 'test.shell'), ['-al', '-bl'], function(err, stdout, stderr) {
console.log(err),
console.log(stdout),
console.log(stderr)
})
# test.shell 文件内容
ls -al
echo $1
echo $2
spawn 用法以及与exec & execFile的区别
const child = cp.spawn(path.resolve(__dirname, 'test.shell'), ['-al','-bl'], {
cwd: path.resolve('..')
})
console.log(child.pid, process.pid)
child.stdout.on('data', function(chunk) {
console.log(chunk.toString())
})
//会输出:-al -bl
child.stderr.on('data', function(chunk) {
console.log(chunk.toString())
})
//会输出:lss: command not found
spawn 通过一种流的方式,不断地接受进程传来的执行结果,并且可以对它进行打印。
spawn:适合耗时任务(比如:npm install),需要不断日志。
const child = cp.spawn('cnpm', ['install'], {
cwd: path.resolve('/Users/sam/Desktop/vue-test/imooc-test-lib')
})
child.stdout.on('data', function(chunk) {
console.log(chunk.toString())
})
child.stderr.on('data', function(chunk) {
console.log(chunk.toString())
})
exec / execFile:适合开销比较小的任务,没有一次一行日志,只有最终一起返回日志。
cp.exec('npm install', {
cwd: path.resolve('/Users/sam/Desktop/vue-test/imooc-test-lib')
}, function(err, stdout, stderr) {
console.log(err),
console.log(stdout),
console.log(stderr)
})
原理:/usr/bin/env npm 先去找npm文件,找到之后再去执行install。
fork用法及父子进程通信机制讲解
用来创建子进程,使用node进行执行
// child.js 文件内容
console.log('child process')
console.log('child pid', process.pid)
process.on('message', (msg) => {
console.log(msg);
});
process.send('hello main process');
// fork: Node(main) -> Node(child)
const child = cp.fork(path.resolve(__dirname, 'child.js'))
child.send('hello child process!', () => {
//child.disconnect(); // 断开,否则两边会处于等待的状态,等待对方向我发送信息。
});
child.on('message', (msg) => {
console.log(msg);
});
console.log('main pid:', process.pid)
// 会打印
// main pid: 28236
// child process
// child pid: 28237
// hello child process!
// hello main process
// fork 本质上也是调用了 spawn,spawn会创建一个子进程对象。
// 通过child可以实现主进程与子进程之间的通信。
// fork 是异步的。类似于require。注意代码执行顺序。
fork应用场景:
比较耗时的操作,而且耗时操作是通过nodejs实现的,比如下载文件。下载文件时可以不断地向主进程中传递消息。甚至通过fork可以实现多进程下载的功能。
child_process同步方法使用教程
......