一、理论

之前看多进程这一章节时发现这块东西挺多,写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进程管理之子进程的更多相关文章

  1. Node.js进程管理之Process模块

    在前面Node.js事件运行机制也有提到,Node.js应用在单个线程运行,但是现在大部分服务器都是多处理器,为了方便使用多个进程,Node.js提供了3个模块.Process模块提供了访问正在运行的 ...

  2. Node.js进程管理之进程集群

    一.cluster模块 Node.js是单线程处理,对于高并发的请求怎么样能增加吞吐量呢?为了提高服务器的利用率,能不能多核的来处理呢?于是就有了cluster模块. cluster模块可以轻松实现运 ...

  3. Node.js进程通信模块child_process

    前言 Node.js是一种单线程的编程模型,对Node.js的赞美和诟病的也都是因为它的单线程模型,所有的任务都在一个线程中完成(I/O等例外).单线程模型,不仅让代码非常简洁,更是直接避免了线程调度 ...

  4. 深入理解 Node.js 进程与线程

    原文链接: https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651557398&idx=1&sn=1fb991da ...

  5. Node.js包管理器Yarn的入门介绍与安装

    FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT. 就在昨天, Facebook 发布了新的 node.js 包管理器 Yarn 用以替代 npm .咱 ...

  6. Node.js包管理器:

    Node.js包管理器: 当我们要把某个包作为工程运行的一部分时,通过本地模式获取,如果要在命令行下使用,则使用全局模式安装 使用全局模式安装的包并不能直接在JavaScript文件中用require ...

  7. 避免uncaughtException错误引起node.js进程崩溃

    uncaughtException 未捕获的异常, 当node.js 遇到这个错误,整个进程直接崩溃. 或许这俩个人上辈子一定是一对冤家. 或许这俩个人经历了前世500次的回眸才换来了今生的相遇,只可 ...

  8. Node.js NPM 管理包

    章节 Node.js NPM 介绍 Node.js NPM 作用 Node.js NPM 包(Package) Node.js NPM 管理包 Node.js NPM Package.json 根据安 ...

  9. Node.js 进程

    process 是全局对象,能够在任意位置访问,是 EventEmitter 的实例. 退出状态码 当没有新的异步的操作等待处理时,Node 正常情况下退出时会返回状态码 0 .下面的状态码表示其他状 ...

随机推荐

  1. Windows2012 显示我的电脑删除群集

    rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0 在正常删除Cluster 节点之后,再添加节点时,报“节点已经加入群集”,无法加入,注册表信息删 ...

  2. 【cocos2d-x 3.0-Mac配置篇】

    就在昨天触控正式发布了3.0正式版本... 在这个喜大普奔的日子里,我们又开始了新一轮的革命,先不说其他的,再来看看3.0目录文件里面有什么? 首先是精简了很多,无论是从目录结构,和所用到的工具类,都 ...

  3. PageAdmin CMS网站建设教程:如何实现信息的定时发布

    PageAdmin Cms发布文章时候有一个上线时间设置和下线时间设置,网站编辑人员可以利用这个功能来实现定时发布,在信息发布界面,如下图: 设置后就会自动加入定时任务中,注意这个功能需要再系统设置& ...

  4. Servlet实现session读写

    前言     一个女人让他的程序员丈夫去商店买东西:你去附近的商店买些面包,如果有鸡蛋的话,买6个回来,这个丈夫买了6个面包回来,他的妻子大吃一惊:你为什么买了6个面包?! 程序员丈夫回答:因为他们有 ...

  5. linux 中定时执行python脚本

    一.让Python随Linux开机自动运行 准备好要自启的脚本auto.py 用root权限编辑以下文件 sudo vim /ect/rc.local 在exit 0上面编辑启动脚本的命令(编辑rc. ...

  6. JavaScript基础DOM介绍和常用操作(5)

    day53 参考:https://www.cnblogs.com/liwenzhou/p/8011504.html JavaScript引入方式 location对象 window.location ...

  7. 对一致性hash原理的理解

    一致性hash算法解决的核心问题是,当solt数发生变化的时候能够尽量少的移动数据.该算法最早在<Consistent Hashing and Random Trees:Distributed ...

  8. gulp-load-task 解决 gulpfile.js 过大的问题

    当我们在项目中使用gulp来实现前端自动化时,常常因任务太多导致gulpfile.js越来越臃肿,增加后期维护/变更成本.在计算机科学领域中,分治可以将我们的项目变得井然有序.所以,我们利用这个理念, ...

  9. Mongoose 分页查询优化、获取数据总长度

    无论是传统网页还是 ajax api,我们都不得不进行数据分页,一来节省带宽二来提升页面响应速度.作为一个数据完备的 web 应用,做好分页功能能极大提升用户体验. 简单的分页查询 在 mongoos ...

  10. [SqlServer] Error: 15023

    Use DataBaseName go sp_change_users_login 'update_one', 'UserName', 'UserName' 恢复数据库后,添加用户,报错号15023 ...