Node.js进程管理之子进程详解

Node.js进程管理之子进程详解

一、理论

之前看多进程这一章节时发现这块东西挺多,写Process模块的时候也有提到,今天下午午休醒来静下心来好好的看了一遍,发现也不是太难理解。

Node.js是单线程的,对于现在普遍是多处理器的机器是一种浪费,怎么能利用起来呢?于是child_process模块出现了。child_process模块可以在其他进程上产生、派生,并执行工作。

child_process模块提供了一个ChildProcess的新类,它可以作为从父进程访问子进程的表示形式。Process模块也是ChildProcess对象。当你从父模块访问process时,它是父ChildProcess对象,当你从子进程访问Process是,它是ChildProcess对象

了解一个对象无外乎事件、方法、属性。ChildProcess也是一样。下面列出一些常用的事件、方法和属性。

事件:

message:当ChildProcess对象调用send()方法来发送数据时触发。

error:在工作进程中出现错误时发出。该处理程序接收一个错误对象作为唯一的参数。

exit:当工作进程结束时发出。该处理程序接收两个参数,code,signal.

close:当工作进程的所有stdio流都已经终止的时候发出。与exit不同的是,因为多个进程可以共享相同的stdio流。

disconnect:当disconnect()在一个工作进程上被调用时发出。

方法:

kill([signal]):导致操作系统发送一个kill信号给子进程。默认是SIGTERM.

send(message,[sendHandle]):将消息发送到句柄。消息可是字符串或对象。sendhandle可以把TCP Server或socket对象发送到客户端。这允许客户端进程共享相同的端口和地址。

disconnect():关闭父进程与子进程之间的进程通信(或IPC)通道,并把父进程和子进程的连接标志都设置为false。

属性:

stdin:输入Writable流。

stdout:标准输出Readable流。

strerr:用于输出错误的标准输出Readable流。

pid:进程的ID。

connected:一个布尔值。在disconnect()被调用后,它被设置为false,当是false时,就不能将消息发送给子进程。

二、实践 1.exec()在另一进程执行一个系统命令

exec()函数在一个子shell中执行系统命令。几乎可以执行能从控制台提示符下执行的任何东西,如二进制可执行文件、shell脚本、Python脚本或批处理文件。

exec(command,[options],callback)函数返回一个ChildProcess对象

command:字符串,指定在子shell中执行的命令。

options:对象,指定执行命令时使用的设置。选项如下:

cwd:指定子进程执行的当前工作目录

env:一个对象,指定property:value作为环境的键/值对

encoding:指定存储命令的输出时输出缓冲区使用的编码

maxBuffer:指定stdout、stderror输出缓冲区的大小。默认200*1024.

timeout:指定父进程在杀掉子进程之前,如果子进程未完成等待的毫秒数。默认0

killSignal:指定终止子进程时使用的kill信号。默认SIGTERM。

callback:接收error、stdout、stderr3个参数。

var childProcess = require('child_process'); var options = {maxBuffer:100*1024, encoding:'utf8', timeout:5000}; var child = childProcess.exec('dir /B', options, function (error, stdout, stderr) { if (error) { console.log(error.stack); console.log('Error Code: '+error.code); console.log('Error Signal: '+error.signal); } console.log('Results: \n' + stdout); if (stderr.length){ console.log('Errors: ' + stderr); } }); child.on('exit', function (code) { console.log('Completed with code: '+code); });

输出结果:

"C:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe" F:\nodejs\node.exe child_process_exec.js Completed with code: 0 Results: chef.js child_fork.js child_process_exec.js child_process_exec_file.js child_process_spawn.js cluster_client.js cluster_server.js cluster_worker.js file.txt process_info.js Process finished with exit code 0 2.execFile()在另一个进程上执行一个可执行文件

它与exec()相似,不同的是execFile()没有使用子shell,执行的命令必须是一个二进制可执行文件Linux的shell脚本和Windows的批处理文件不能使用ecexFile().

execFile(file,args,options,callback)也是返回一个ChildProcess。

file:字符串,执行要执行的可执行文件的路径。

args:数组,指定传递给可执行文件的命令行参数。

options:参考exec()的。

callback:参考exec().

var childProcess = require('child_process'); var options = {maxBuffer:100*1024, encoding:'UTF-16', timeout:5000}; var child = childProcess.execFile('ping.exe', ['-n', '1', 'baidu.com'], options, function (error, stdout, stderr) { if (error) { console.log(error.stack); console.log('Error Code: '+error.code); console.log('Error Signal: '+error.signal); } console.log('Results: \n' + stdout.toString()); if (stderr.length){ console.log('Errors: ' + stderr.toString()); } }); child.on('exit', function (code) { console.log('Child completed with code: '+code); }); 3.spawn()在另一个Node.js实例中产生一个进程

spawn(cmd,[args],[options])函数产生一个进程,连接它们之间的stdio、stdout、stderr的管道,然后在新的线程中使用spawn()执行文件。它和上面两个的主要区别是产生的进程中的stdin可以进行配置,并且stdout、stderr都是父进程中的Readable流。这意味着exec()、execFile()必须先执行完成,才能读取缓冲区输出,但一旦一个spawn()进程的输出数据已被写入就可以读取它(这个可以从它们3个的输出结果的顺序可以看出,上面两个都是先执行exit事件,而spawn()exit处理是在后面)。

cmd、args和上面两个的一样。options也可以设置cwd、env,还可以设置detached、stdio。

detached:布尔值,true时使子进程成为新进程组的组长,即使父进程退出,也会继续,可以使用child_unref()使得父进程退出之前不等待子进程

stdio:定义子进程stdio配置([stdin,stdout,stderr]).默认[0,1,2].此字符串定义每个输入输出流的配置。

var spawn = require('child_process').spawn; var options = { env: {user:'brad'}, detached:false, stdio: ['pipe','pipe','pipe'] }; var child = spawn('netstat', ['-e']); child.stdout.on('data', function(data) { console.log(data.toString()); }); child.stderr.on('data', function(data) { console.log(data.toString()); }); child.on('exit', function(code) { console.log('Child exited with code', code); }); 4.实现子派生

Node.js提供了另外一种进程产生方式——派生。它主要是执行在一个单独的处理器上运行另外一个V8引擎实例中的Node.js模块代码。可以用派生来并行运行多个服务。不过这需要时间来运转V8的一个新实例,每个实例需要大约10M的内存,所以应该把派生的进程设计为存活期更长的,不需要大量派生的进程。与spawn不同的是,它不能为子进程配置stdio。可以使用ChildProcess对象中的send()机制在父进程与子进程间通信。

fork(modulePath,[args],[options])对象也是返回一个ChildProcess对象。

modulePath:字符串,指定被新的Node.js实例启动的JavaScript文件路径。

args:数组,指定传递给node命令的命令行参数。

options:参数对象,指定执行命令时使用的设置。

cwd、env上面有。

encoding:指定数据写入输出流时和穿越send()IPC机制时使用的编码

execPath:指定用于创建产生Node.js进程的可执行文件。

silent:一个布尔值,true时将导致派生的进程中的stdout和stderr不与父进程相关联,默认false。

Child.send()父进程向子进程发送消息,Process.send()是子进程向父进程发送消息。

var child_process = require('child_process'); var options = { env:{user:'Brad'}, encoding:'utf8' }; function makeChild(){ var child = child_process.fork('chef.js', [], options); child.on('message', function(message) { console.log('Served: ' + message); }); return child; } function sendCommand(child, command){ console.log("Requesting: " + command); child.send({cmd:command}); } var child1 = makeChild(); var child2 = makeChild(); var child3 = makeChild(); sendCommand(child1, "makeBreakfast"); sendCommand(child2, "makeLunch"); sendCommand(child3, "makeDinner"); process.on('message', function(message, parent) { var meal = {}; switch (message.cmd){ case 'makeBreakfast': meal = ["ham", "eggs", "toast"]; break; case 'makeLunch': meal = ["burger", "fries", "shake"]; break; case 'makeDinner': meal = ["soup", "salad", "steak"]; break; } process.send(meal); });

输出结果:

"C:\Program Files (x86)\JetBrains\WebStorm 11.0.3\bin\runnerw.exe" F:\nodejs\node.exe child_fork.js Requesting: makeBreakfast Requesting: makeLunch Requesting: makeDinner Served: ham,eggs,toast Served: burger,fries,shake Served: soup,salad,steak

上面的代码是在主进程中创建3个子进程,父进程给子进程发消息,子进程接收并给父进程发消息。

到此这篇关于Node.js进程管理之子进程的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持易知道(ezd.cc)。

推荐阅读

    js设置div的边框|怎样给div设置边框

    js设置div的边框|怎样给div设置边框,,1. 怎样给div设置边框1、首先新建一个html文件,输入基本的内容,这里设置一个div,并把它的class设置为de

    js设置样式|js设置样式类

    js设置样式|js设置样式类,,js设置样式    javascript改变CSS样式分为局部和全局,分别如下:  一、局部改变样式    有三种方法:直接

    js用代码实现简单购物车

    js用代码实现简单购物车,,图: 选择所有按钮: 复制代码代码如下所示: 选择 笔记本电脑:3000元 笔记本电脑:3000元 笔记本电脑:3000元 笔记本电脑:3

    js设置背景色|js设置颜色

    js设置背景色|js设置颜色,,js设置背景色首先通过js定位到div的子元素,再通过setatteibute方法给属性添加背景色。js设置颜色js改变字体的颜

    Safari调试iOS中的js

    Safari调试iOS中的js,页面,设备,概述对于HTML5的开发,大家都知道Chrome的DevTools工具有强大的功能和友好的用户体验,不仅能快速方便调试Jav

    Bootstrap的js插件之模态框|modal

    Bootstrap的js插件之模态框|modal,模态,饭盒,.modal——指明div元素包裹模态框;.fade——给模态框添加淡入淡出效果;.modal-dialog——包裹

    js默认事件汇总

    js默认事件汇总,事件,表单,默认事件   就是浏览器通过HTML标签或DOM元素提供的一些功能性的默认行为。比如在a标签href属性上的跳转,右键

    js获取元素宽度

    js获取元素宽度,内联,样式,js获取元素宽度1、使用内联样式,即直接把CSS写在HTML元素的style属性中<div > </div>复制代码通过以下js代码

    SQLite使用JSON扩展

    SQLite使用JSON扩展,插件,加载,一、介绍 SQLite3.9.0之后的版本,添加了JSON扩展。在表中可以保存JSON类型。实际上SQLite将JSON类型的

    jscript.dll是什么

    jscript.dll是什么,系统,文件,论坛,显示,扫描,修复,  jscript.dll是Microsoft JavaScript脚本支持相关文件。属于: Microsoft JScript系统 DLL