node.js整理 05进程管理
2015-04-06 15:18
465 查看
简介
NodeJS可以感知和控制自身进程的运行环境和状态,也可以创建子进程并与其协同工作,这使得NodeJS可以把多个程序组合在一起共同完成某项工作,并在其中充当胶水和调度器的作用常用API
Process
任何一个进程都有启动进程时使用的命令行参数,有标准输入标准输出,有运行权限,有运行环境和运行状态。在NodeJS中,可以通过
process对象感知和控制NodeJS自身进程的方方面面。另外需要注意的是,
process不是内置模块,而是一个全局对象,因此在任何地方都可以直接使用。
Child Process
使用child_process模块可以创建和控制子进程。该模块提供的API中最核心的是
.spawn,其余API都是针对特定使用场景对它的进一步封装,算是一种语法糖。
Cluster
cluster模块是对
child_process模块的进一步封装,专用于解决单进程NodeJS Web服务器无法充分利用多核CPU的问题。
使用该模块可以简化多进程服务器程序的开发,让每个核上运行一个工作进程,并统一通过主进程监听端口和分发请求。
应用场景
如何获取命令行参数
可以通过process.argv获取命令行参数。但node执行程序路径和主模块文件路径固定占据了argv[0]和argv[1]两个位置,而第一个命令行参数从argv[2]开始。
function main(argv) { // ... } main(process.argv.slice(2));
如何退出程序
通常一个程序做完所有事情后就正常退出了,这时程序的退出状态码为0。或者一个程序运行时发生了异常后就挂了,这时程序的退出状态码不等于0。
如果在代码中捕获了某个异常,但是觉得程序不应该继续运行下去,需要立即退出,并且需要把退出状态码设置为指定数字,比如1,就可以按照以下方式:
try { // ... } catch (err) { // ... process.exit(1); }
如何控制输入输出
NodeJS程序的标准输入流(stdin)、一个标准输出流(stdout)、一个标准错误流(stderr)分别对应process.stdin、
process.stdout和
process.stderr,
第一个是只读数据流,后边两个是只写数据流,对它们的操作按照对数据流的操作方式即可。
function log() { process.stdout.write( util.format.apply(util, arguments) + '\n'); }
如何降权
在Linux系统下,需要使用root权限才能监听1024以下端口。但是一旦完成端口监听后,继续让程序运行在root权限下存在安全隐患,因此最好能把权限降下来。
http.createServer(callback).listen(80, function () { var env = process.env, uid = parseInt(env['SUDO_UID'] || process.getuid(), 10), gid = parseInt(env['SUDO_GID'] || process.getgid(), 10); process.setgid(gid); process.setuid(uid); });
如果是通过
sudo获取
root权限的,运行程序的用户的
UID和
GID保存在环境变量
SUDO_UID和
SUDO_GID里边。
如果是通过
chmod +s方式获取
root权限的,运行程序的用户的
UID和
GID可直接通过
process.getuid和
process.getgid方法获取;
process.setuid和
process.setgid方法只接受number类型的参数。
降权时必须先降
GID再降
UID,否则顺序反过来的话就没权限更改程序的
GID了。
如何创建子进程
var child = child_process.spawn('node', [ 'xxx.js' ]); child.stdout.on('data', function (data) { console.log('stdout: ' + data); }); child.stderr.on('data', function (data) { console.log('stderr: ' + data); }); child.on('close', function (code) { console.log('child process exited with code ' + code); });
使用了
.spawn(exec, args, options)方法,该方法支持三个参数。
第一个参数是执行文件路径,可以是执行文件的相对或绝对路径,也可以是根据PATH环境变量能找到的执行文件名。
第二个参数中,数组中的每个成员都按顺序对应一个命令行参数。
第三个参数可选,用于配置子进程的执行环境与行为。
上例中虽然通过子进程对象的
.stdout和
.stderr访问子进程的输出,但通过
options.stdio字段的不同配置,可以将子进程的输入输出重定向到任何数据流上,或者让子进程共享父进程的标准输入输出流,或者直接忽略子进程的输入输出。
进程间如何通讯
在Linux系统下,进程之间可以通过信号互相通信/* parent.js */ var child = child_process.spawn('node', [ 'child.js' ]); child.kill('SIGTERM'); /* child.js */ process.on('SIGTERM', function () { cleanUp(); process.exit(0); });
上例中,父进程通过
.kill方法向子进程发送SIGTERM信号,子进程监听
process对象的SIGTERM事件响应信号。
不要被.kill方法的名称迷惑了,该方法本质上是用来给进程发送信号的,进程收到信号后具体要做啥,完全取决于信号的种类和进程自身的代码。
如果父子进程都是NodeJS进程,就可以通过IPC(进程间通讯)双向传递数据
/* parent.js */ var child = child_process.spawn('node', [ 'child.js' ], { stdio: [ 0, 1, 2, 'ipc' ] }); child.on('message', function (msg) { console.log(msg); }); child.send({ hello: 'hello' }); /* child.js */ process.on('message', function (msg) { msg.hello = msg.hello.toUpperCase(); process.send(msg); });
父进程在创建子进程时,在
options.stdio字段中通过ipc开启了一条IPC通道,之后就可以监听子进程对象的
message事件接收来自子进程的消息,并通过
.send方法给子进程发送消息。
在子进程这边,可以在
process对象上监听
message事件接收来自父进程的消息,并通过
.send方法向父进程发送消息。数据在传递过程中,会先在发送端使用
JSON.stringify方法序列化,再在接收端使用
JSON.parse方法反序列化。
如何守护子进程
守护进程一般用于监控工作进程的运行状态,在工作进程不正常退出时重启工作进程,保障工作进程不间断运行/* daemon.js */ function spawn(mainModule) { var worker = child_process.spawn('node', [ mainModule ]); worker.on('exit', function (code) { if (code !== 0) { spawn(mainModule); } }); } spawn('worker.js');
工作进程非正常退出时,守护进程立即重启工作进程
相关文章推荐
- 关于node.js的进程管理
- Node.js进程管理之进程集群
- node.js学习第二天--进程管理
- Node.js进程管理之Process模块
- Node.js中创建和管理外部进程详解
- Node.js中创建和管理外部进程详解
- Node.js进程管理之子进程
- 深入理解Node.js中的进程管理
- Atitit js nodejs下的进程管理wmic process进程管理
- node.js进程管理 PM2 && forever
- node.js在windows下的学习笔记(8)---进程管理Process
- Node.js 进程管理工具
- Node.js中创建和管理外部进程详解
- 关于node.js的进程管理
- node.js学习-整理
- npm 是node.js提供的包管理工具
- Node.js学习资料整理
- 管理 Node.js 多版本共存: nvm
- node.js的模块管理
- node.js网上学习资源整理(持续整理中...)