nodejs事件循环与多进程(四)——Process进程-Node全局对象&child_process子进程-exec、execSync、execFile、spawn、fork & Cluster集群

nodejs事件循环与多进程(四)——Process进程-Node全局对象&child_process子进程-exec、execSync、execFile、spawn、fork & Cluster集群

cluster相关API

Process 进程 、child_process 子进程 、Cluster 集群

process进程

process 对象是 Node 的一个全局对象,提供当前 Node 进程的信息,他可以在脚本的任意位置使用,不必通过 require 命令加载。

属性

  1. process.argv 属性,返回一个数组,包含了启动 node 进程时的命令行参数
  2. process.env 返回包含用户环境信息的对象,可以在 脚本中对这个对象进行增删改查的操作
  3. process.pid 返回当前进程的进程号
  4. process.platform 返回当前的操作系统
  5. process.version 返回当前 node 版本

方法

  1. process.cwd() 返回 node.js 进程当前工作目录
  2. process.chdir() 变更 node.js 进程的工作目录
  3. process.nextTick(fn) 将任务放到当前事件循环的尾部,添加到 ‘next tick’ 队列,一旦当前事件轮询队列的任务全部完成,在 next tick 队列中的所有 callback 会被依次调用
  4. process.exit() 退出当前进程,很多时候是不需要的
  5. process.kill(pid[,signal]) 给指定进程发送信号,包括但不限于结束进程

事件

  1. beforeExit 事件,在 Node 清空了 EventLoop 之后,再没有任何待处理任务时触发,可以在这里再部署一些任务,使得 Node 进程不退出,显示的终止程序时(process.exit()),不会触发

  2. exit 事件,当前进程退出时触发,回调函数中只允许同步操作,因为执行完回调后,进程金辉退出

  3. uncaughtException 事件,当前进程抛出一个没有捕获的错误时触发,可以用它在进程结束前进行一些已分配资源的同步清理操作,尝试用它来恢复应用的正常运行的操作是不安全的

    重点关注

  4. warning 事件,任何 Node.js 发出的进程警告,都会触发此事件

child_process

nodejs中用于创建子进程的模块,node中大名鼎鼎的cluster是基于它来封装的。

  1. exec()

异步衍生出一个 shell,然后在 shell 中执行命令,且缓冲任何产生的输出,运行结束后调用回调函数

var exec = require('child_process').exec;

var ls = exec('ls -c', function (error, stdout, stderr) {
    
    
  if (error) {
    
     // 错误处理和 业务代码一样重要
    console.log(error.stack);
    console.log('Error code: ' + error.code);
  }
  console.log('Child Process STDOUT: ' + stdout);
});

由于标准输出和标准错误都是流对象(stream),可以监听data事件,因此上面的代码也可以写成下面这样。

var exec = require('child_process').exec;
var child = exec('ls');

child.stdout.on('data', function(data) {
    
    
  console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
    
    
  console.log('stdout: ' + data);
});
child.on('close', function(code) {
    
    
  console.log('closing code: ' + code);
});

上面的代码还有一个好处。监听data事件以后,可以实时输出结果,否则只有等到子进程结束,才会输出结果。所以,如果子进程运行时间较长,或者是持续运行,第二种写法更好。

实例
var exec  = require('child_process').exec;

// 回调
// exec('ls', (err, stdout, stderr) => {
    
    
//     if (err) { // 错误处理和 业务代码一样重要
//         console.log('stderr', stderr)
//     } 
//     console.log('stdout', stdout)
// })

//  通过流的方式去接收结果,类似文件读取,
// rm -rf 删除
var path = '../ \ rm -rf';
var child = exec(`ls -c ${
      
      path}`);
child.stdout.on('data', (data) => {
    
    
    console.log('data', data)
});

child.stderr.on('data', (err) => {
    
    
    // 打印err
})

console.log('11111');
  1. execSync()

exec()的同步版本

  1. execFile()

execFile方法直接执行特定的程序shell,参数作为数组传入,不会被bash解释,因此具有较高的安全性。

const {
    
    execFile} = require('child_process');
execFile('ls',['-c'], (error, stdout, stderr) => {
    
     // execFile会自动过滤一些敏感的 字符串 比如'\ ;'
    console.log('stdout', stdout)
	if(error) {
    
    
		console.error(`exec error: ${
      
      error}`);
		return;
	}
	console.log(`${
      
      stdout}`);
	console.log(`${
      
      stderr}`);
});
  1. spawn()

spawn方法创建一个子进程来执行特定命令shell,用法与execFile方法类似,但是没有回调函数,只能通过监听事件,来获取运行结果。它属于异步执行,适用于子进程长时间运行的情况。

const {
    
     spawn } = require('child_process');

var child = spawn('ls', ['-c'],{
    
    
    encoding: 'UTF-8'
});

child.stdout.on('data', function(data) {
    
      // spawn的data输出的是buffer对象
    console.log('data', data.toString('utf8'))
});
child.on('close',function(code) {
    
    
    console.log('closing code: ' + code);
  });

spawn返回的结果是Buffer需要转换为utf8

  1. fork()

fork方法直接创建一个子进程,执行Node脚本,fork('./child.js') 相当于 spawn('node', ['./child.js']) 。与spawn方法不同的是,fork会在父进程与子进程之间,建立一个通信管道pipe,用于进程之间的通信,也是IPC通信的基础。

main.js

var child_process = require('child_process');
var path = require('path');

// mian里面去创建一个子进程 child
var child = child_process.fork(path.resolve(__dirname, './child.js'));// 稳定性
child.on('message', function(m) {
    
     // main去监听child的消息
  console.log('主线程收到消息', m);
  // console.log('父亲接收到数据', data);
});
child.send({
    
     hello: 'world' });
// child.send('儿子,爸爸给你发消息了');

child.js

process.on('message', function (m) {
    
    
    console.log('子进程收到消息', m);
    // console.log('儿子接收到的消息', data)
});

// 给父亲发送
process.send({
    
     foo: 'bar' });
// process.send('爸爸你好');

打开终端,执行命令

node .\main.js

两个文件的console内容都能打印

猜你喜欢

转载自blog.csdn.net/weixin_44867717/article/details/131546454