Node基础篇之进程process
Opened this issue · 0 comments
简介
通过process能够获得node进程相关的信息,比如node运行时的命令行参数,当前环境变量等,在编写cli脚手架时特别有用。
process.env
一般在部署node项目时,不同的环境需要配置不同的环境变量,常用的是:
NODE_ENV=development
然后在业务逻辑中可以使用process.env获取到环境变量,进行不同的处理:
if(process.env.NODE_ENV === 'development') ...
process.nextTick(fn)
process.nextTick(fn) 跟 setTimeout(fn, 0) 很像,但实际有实现及性能上的差异:
- process.nextTick(fn) 将 fn 放到 node 事件循环的 下一个tick 里;
- process.nextTick(fn) 比 setTimetout(fn, 0) 性能高;
process.argv
process.argv 返回一个数组,数组元素分别如下:
- 元素1:node运行路径
- 元素2:可执行文件的绝对路径
- 元素x:其他,比如参数等
在 G:\node-l目录先编写argv.js
process.argv.forEach((val, index, array) => {
console.log('参数' + index + ': ' + val);
});
终端执行 node argv.js aaa bbb,结果如下:
process.cwd() vs process.chdir(directory)
- process.cwd():返回当前工作路径
- process.chdir(directory):切换当前工作路径
对于process.chdir(),一般在编写cli脚手架时,很多时候需要动态切换到别的目录作为当前的node进程目录,然后执行比如 npm install等。
IPC相关
- process.connected:如果当前进程是子进程,且与父进程之间通过IPC通道连接着,则为true;
- process.disconnect():断开与父进程之间的IPC通道,此时会将 process.connected 置为false;
首先是 connected.js,通过 fork 创建子进程(父子进程之间创建了IPC通道)
var child_process = require('child_process');
child_process.fork('./connectedChild.js', {
stdio: 'inherit'
});
然后,在 connectedChild.js 里面。
console.log( 'process.connected: ' + process.connected );
process.disconnect();
console.log( 'process.connected: ' + process.connected );
// 输出:
// process.connected: true
// process.connected: false
process.stdin、process.stdout、process.stderr
分别代表进程的标准输入、标准输出、标准错误输出.
例子一: 输出用户输入的数据
process.stdin.setEncoding('utf8');
process.stdin.on('readable', () => {
var chunk = process.stdin.read();
if (chunk !== null) {
process.stdout.write(`data: ${chunk}`);
}
});
process.stdin.on('end', () => {
process.stdout.write('end');
});
在终端启动 node std.js, 然后输入 hello, 将打印 data: hello。
例子二: 输出用户输入的a+b结果
// 默认情况下输入流是关闭的,要监听输入流数据,首先要开启输入流
process.stdin.resume();
var a;
var b;
process.stdout.write("请输入a的值:");
process.stdin.on('data',function(chunk){
//判断用户输入的是a的值还是b的值
if(!a){
a = Number(chunk);
process.stdout.write("请输入b的值:");
}else{
b = Number(chunk);
process.stdout.write("结果等于"+(a+b));
}
})
进程的输入输出方法
process.on('exit', function(code) { console.log(code) });
process.stdin.setEncoding('utf8');
process.stdout.write("......\n");
process.stdout.write("确认执行吗(y/n)?");
process.stdin.on('data',(input)=>{
input = input.toString().trim();
if (['Y', 'y', 'YES', 'yes'].indexOf(input) > -1) { console.log('console log -- yes')};
if (['N', 'n', 'NO', 'no'].indexOf(input) > -1) process.exit(0);
})
node可执行程序相关信息
-
process.version:返回当前node的版本,比如'v6.1.0'。
进程运行所在环境
- process.arch:返回当前系统的处理器架构(字符串),比如'arm', 'ia32', or 'x64'。
- process.platform:返回关于平台描述的字符串,比如 darwin、win32 等。
终止进程:process.exit([exitCode])、process.exitCode
- process.exit([exitCode]) 可以用来立即退出进程。即使当前有操作没执行完,比如 process.exit() 的代码逻辑,或者未完成的异步逻辑。
- 写数据到 process.stdout 之后,立即调用 process.exit() 是不保险的,因为在node里面,往 stdout 写数据是非阻塞的,可以跨越多个事件循环。于是,可能写到一半就跪了。比较保险的做法是,通过process.exitCode设置退出码,然后等进程自动退出。
- 如果程序出现异常,必须退出不可,那么,可以抛出一个未被捕获的error,来终止进程,这个比 process.exit() 安全。
master-worker 多进程端口不会占用原理
node的cluster模块在fork代码时,不会报端口被占用,这是什么原因呢?
答案是:master进程监听了端口,而内部根据当前进程是否是worker把worker的listen给hack掉了,因为请求会先到达master,此时master把改请求根据负载均衡传递给某个worker,达到最终的效果。
模拟代码:
//master.js
onst fork = require('child_process').fork;
const cpus = require('os').cpus();
const server = require('net').createServer();
server.listen(3000);
process.title = 'node-master'
for (let i=0; i<cpus.length; i++) {
const worker = fork('worker.js');
// 重点是把master的server句柄传给了子进程
worker.send('server', server);
}
// worker.js
const http = require('http');
const server = http.createServer((req, res) => {
res.end('I am worker, pid: ' + process.pid + ', ppid: ' + process.ppid);
});// 注意:这里没有监听任何端口
let worker;
process.title = 'node-worker'
process.on('message', function (message, sendHandle) {
if (message === 'server') {
worker = sendHandle;
// 使用master传过来的server,监听其请求,然后代理到子进程的server,就将该请求传给了该子进程
worker.on('connection', function(socket) {
server.emit('connection', socket);
});
}
});
net.Server都有connection事件,每次请求过来时,都会响应connection。