Node.js中的全局对象之process进程对象

 2015年06月16日    3669     声明


process对象是一个Global全局对象,你可以在任何地方使用它,而无需require。process是EventEmitter的一个实例,所以process中也有相关事件的监听。使用process对象,可以方便处理进程相关操作。

  1. process中的事件
  2. process中的标准流对象
  3. process中的属性
  4. process中的方法


1. process中的事件

processEventEmitter的一个实例,所以也具有事件监听器的特征。process中的事件监听器有:'exit''uncaughtException'、各种Signal

1.1 退出事件: 'exit'

'exit'事件会在进程退出时触发。'exit'事件的监听器可以用来检查进程退出的状态,在其回调函数中会有一个进程退出的状态码。有一点要注意,'exit'事件触发后事件循环将会停止,记时器等也会失效。示例如下:

process.on('exit', function(code) {
  // 进程退出后,其后的事件循环将会结束,计时器也不会被执行
  setTimeout(function() {
    console.log('This will not run');
  }, 0);
  console.log('进程退出码是:', code);
});

//进程退出
process.exit();
//进程正常退出,其退出码为:0

1.2 未处理异常: 'uncaughtException'

当进程异常退出时,会触发'uncaughtException'事件,当此引发此事件的异常一般并不明确,因此不建议使用,推荐使用domains模块进行异常处理。使用示例:

//异常捕获
process.on('uncaughtException', function(exception) {
  console.log('捕获到的异常是:', exception);
});
//一个未定义的方法,用来制造异常
nonexistentFunc();

//输出
捕获到的异常是: [ReferenceError: nonexistentFunc is not defined]

信号相关事件

信号相关事件会在进程接收到POSIX标准信号时触发。监听的事件名为POSIX信号名,如:SIGINT、SIGUSR1 等。示例如下:

process.stdin.resume();

//使用Control+C键,可以触发SIGINT信号
process.on('SIGINT', function() {
  console.log('收到SIGINT信号,按Control+D键可以退出进程');
});


2. process中的标准流对象

process中有三个标准备流的操作,与Streams流操作不同的是,process中流操作是阻塞的。

标准输出流:process.stdout

process.stdout是一个指向标准输出流的可写流Writable Streamconsole.log就是通过process.stdout实现的,其实现代码如下:

console.log = function(d) {
  process.stdout.write(d + '\n');
};

标准错误流:process.stderr

process.stderr是一个指向标准错误流的可写流Writable Streamconsole.error就是通过process.stderr实现的。

标准输入流:process.stdin

process.stdin是一个指向标准输入流的可读流 Readable Stream。标准输入流默认是暂停 (pause) 的,所以必须要调用 process.stdin.resume() 来恢复 (resume) 接收。使用示例如下:

process.stdin.on('end', function() {
  process.stdout.write('end');
});

//一个读取输入流的方法
function gets(cb){
  process.stdin.resume();
  process.stdin.setEncoding('utf8');

  process.stdin.on('data', function(chunk) {
     process.stdin.pause();
     cb(chunk);
  });
}

gets(function(reuslt){
  console.log("["+reuslt+"]");
});


3. process中的属性

process有一些属性,可以用来查看进程的相关参数,如:命令参数、进程ID、执行环境等。

3.1 进程命令行参数的数组:process.argv

process.argv是一个当前执行进程折参数组,第一个参数是node,第二个参数是当前执行的.js文件名,之后是执行时设置的参数列表。

例如,当前文件名是process.js,其代码如下:

process.argv.forEach(function(val, index, array) {
  console.log(index + ': ' + val);
});

node process.js执行后,其输出如下:

0: node
1: /Users/liuht/code/itbilu/demo/process.js

增加两个参数node process.js arg1 arg2执行后,其输出如下:

0: node
1: /Users/liuht/code/itbilu/demo/process.js
2: arg1
3: arg2

3.2 启动进程程序的路径:process.execPath

process.execPath属性会返回启动进程程序的路戏,例如:node process.js会返回,/usr/local/bin/node,即:node的安装路径。process.js代码如下:

console.log(process.execPath);

3.3 Node的命令行参数数组:process.execArgv

process.execArgv属性会返回Node的命令行参数数组。代码如下:

$ node --harmony script.js --version 

process.execArgv返回

['--harmony'] 

process.argv返回

['/usr/local/bin/node', 'script.js', '--version']

3.4 运行环境对象:process.env

process.env属性会返回用户运行环境对象。示例如下:

console.log(process.env);

//返回值
  TERM: 'xterm-256color',
  SHELL: '/bin/bash',
  TMPDIR: '/var/folders/1k/86kq55_n4_q2tckwz9mb5wyr0000gn/T/',
  Apple_PubSub_Socket_Render: '/private/tmp/com.apple.launchd.88pzu6r2kn/Render',
  TERM_PROGRAM_VERSION: '343.7',
  NODE_DEBUG: 'dev',
  TERM_SESSION_ID: 'CDD038DB-67CC-4472-BB47-6C43D507FBC5',
  USER: 'liuht',
  SSH_AUTH_SOCK: '/private/tmp/com.apple.launchd.t9kw8kqKw3/Listeners',
  __CF_USER_TEXT_ENCODING: '0x1F5:0x19:0x34',
  PATH: '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/git/bin:/usr/local/homebrew/bin',
  PWD: '/Users/liuht/code/itbilu/demo',
  LANG: 'zh_CN.UTF-8',
  XPC_FLAGS: '0x0',
  NODE_ENV: 'development',
  XPC_SERVICE_NAME: '0',
  HOME: '/Users/liuht',
  SHLVL: '1',
  LOGNAME: 'liuht',
  _: '/usr/local/bin/node' }

3.5 进程退出码:process.exitCode

process.exitCode属性会返回进程默认退出码,或process.exit(code)方法指定的退出码。

3.6 Node编译时的版本:process.version

process.version属性会返回Node编译时的版本号,版本号保存于Node的内置变量NODE_VERSION中。示例如下:

console.log(process.version);

//输出 v0.10.36

3.7 Node以及其依赖包版本信息:process.versions

process.versions属性会返回Node以及其依赖包版本信息。示例如下:

console.log(process.versions);

//输出如下
{ http_parser: '1.0',
  node: '0.10.36',
  v8: '3.14.5.9',
  ares: '1.9.0-DEV',
  uv: '0.10.30',
  zlib: '1.2.8',
  modules: '11',
  openssl: '1.0.1l' }

3.8 Node编译时的配置信息:process.config

process.config属性会返回Node编译时的配置信息,返回内容与运行./configure脚本生成的 "config.gypi"文件相同。

3.9 指向启动脚本的模块:process.mainModule

process.mainModule属性会返回指向启动脚本的模块,与require.main类似。示例如下:

console.log(process.mainModule);

//输出如下
{ id: '.',
  exports: {},
  parent: null,
  filename: '/Users/liuht/code/itbilu/demo/process.js',
  loaded: false,
  children: [],
  paths: 
   [ '/Users/liuht/code/itbilu/demo/node_modules',
     '/Users/liuht/code/itbilu/node_modules',
     '/Users/liuht/code/node_modules',
     '/Users/liuht/node_modules',
     '/Users/node_modules',
     '/node_modules' ] }

3.10 当前进程的PID:process.pid

process.pid属性会返回当前进程的PID。示例如下:

console.log('process PID: %d', process.pid);

//process PID: 10078

3.11 'ps'中显示的进程名:process.title

process.title属性会返回'ps'中显示的进程名。示例如下:

console.log('process title: %s', process.title);

//process title: node

3.12 当前CPU的架构:process.arch

process.arch属性会返回执行当前进程的CPU架构信息。示例如下:

console.log('process CPU: %s', process.arch);

//process CPU: x64

3.13 当前进程的运行平台:process.platform

process.platform属性会返回执行当前进程的运行平台信息。示例如下:

console.log('process platform: %s', process.platform);

//process platform: darwin


4. process中的方法

4.1 触发一个abort事件:process.abort()

process.abort()方法会导致Node解发一个abort事件并结束进程。示例如下:

process.abort();  //Abort trap: 6

4.2 工作目录切换:process.chdir(directory)、process.cwd()

process.chdir()方法用于改变当前进程的工作目录。process.cwd()方法返回进程当前的工作目录。示例如下:

console.log('当前目录:' + process.cwd());
try {
  process.chdir('/tmp');
  console.log('新目录:' + process.cwd());
}
catch (err) {
  console.log('chdir: ' + err);
}

//输出如下
当前目录:/Users/liuht/code/itbilu/demo
新目录:/private/tmp

4.3 终止当前进程:process.exit([code])

process.exit()方法终止当前进程,此方法可接收一个退出状态的可选参数code,不传入时,会返回表示成功的状态码0。示例如下:

process.on('exit', function(code) {
  console.log('进程退出码是:%d', code); // 进程退出码是:1
});

process.exit(1);

4.4 获取/设置进程的GID:process.getgid()、process.setgid(id)

这两个方法仅适用于POSIX标准的系统。process.getgid()方法用于获取进程的GID,process.setgid(pid)方法设置进程的GID,参数可以是一个数字ID或者群组名。示例如下:

if (process.getgid && process.setgid) {
  console.log('当前 GID: ' + process.getgid());
  try {
    process.setgid(501);
    console.log('新 GID: ' + process.getgid());
  }
  catch (err) {
    console.log('设置 GID 失败: ' + err);
  }
}

//输出如下
当前 GID: 0
新 GID: 501

4.5 获取/设置进程的UID:process.getuid()、process.setuid(id)

这两个方法仅适用于POSIX标准的系统。process.getuid()方法用于获取进程的UID,process.setuid(id)方法设置进程的UID,参数可以是一个数字ID或者用户名。示例如下:

if (process.getuid && process.setuid) {
  console.log('当前 UID: ' + process.getuid());
  try {
    process.setuid(501);
    console.log('新 UID: ' + process.getuid());
  }
  catch (err) {
    console.log('设置 UID 失败: ' + err);
  }
}

//输出如下
当前 UID: 0
新 UID: 501

4.6 获取/设置对当前进程有操作权限GID数组:process.getgroups()、process.setgroups(groups)

这两个方法仅适用于POSIX标准的系统。process.getgroups()方法用于对当前进程有操作权限GID数组,process.setgroups(groups)方法设置对当前进程有操作权限GID数组,数组值可以是一个数字ID或者用户组名。示例如下:

if (process.getgroups && process.getgroups) {
  console.log('当前 groups: ' + process.getgroups());
  try {
    process.setgroups(29,61,80);
    console.log('新 groups: ' + process.getgroups());
  }
  catch (err) {
    console.log('设置 groups 失败: ' + err);
  }
}

//输出如下
当前 UID: 0,1,2,3,4,5,8,9,12,20,29,61,80
新 UID: 29,61,80

4.7 初始化group分组访问列表:process.initgroups(user, extra_group)

这个方法仅适用于POSIX标准的系统。process.initgroups()初始化group分组访问列表,参数可以是一个数字ID或者组名。

4.8 向指定进程发送一个信号:process.kill(pid[, signal])

process.kill()方法用于向指进程发送一个信号,需要注意的是kill方法不仅是用来杀死指定进程的,可以是任何POSIX标准信息。示例如下:

process.stdin.resume();
process.on('SIGTERM', function() {
  console.log('收到了 SIGTERM 信号');
});

process.kill(process.pid, 'SIGTERM');

4.10 返回内存使用情况:process.memoryUsage()

process.memoryUsage()方法用于内存使用情况。示例如下:

console.log(process.memoryUsage());  //{ rss: 13701120, heapTotal: 4083456, heapUsed: 2149016 }

4.11 延迟方法执行:process.nextTick()

process.nextTick(callback[, arg][, ...])

process.nextTick()方法用于延迟回调函数的执行, nextTick方法会将callback中的回调函数延迟到事件循环的下一次循环中,与setTimeout(fn, 0)相比nextTick方法效率高很多,该方法能在任何 I/O 事前之前调用我们的回调函数。示例如下:

console.log('开始');
process.nextTick(function() {
  console.log('nextTick 回调');
});
console.log('已设定');

//输出如下
开始
已设定
nextTick 回调

4.12 设置或读取进程文件的权限掩码:process.umask([mask])

process.umask()方法用于设置或读取进程文件的权限掩码,子进程从父进程中继承这个掩码。如果设定了参数 mask 那么返回旧的掩码,否则返回当前的掩码。示例如下:

var oldmask, newmask = 0022;

oldmask = process.umask(newmask);
console.log('原掩码: ' + oldmask.toString(8) + '\n'
            '新掩码: ' + newmask.toString(8));

4.14 返回当前时间高精度时间:process.hrtime()

process. hrtime()方法用于返回当前时间高精度时间。示例如下:

setTimeout(function(){
	console.log(process.uptime());   //1
}, 1000)

4.13 返回Node程序已运行的秒数:process.uptime()

process.uptime()方法用于返回Node程序已运行的秒数,返回形式为[秒,毫秒]数组。它是相对于在过去的任意时间,与日期无关,因此不受时钟漂移的影响。主要用途是可以通过精确的时间间隔,来衡量程序的性能。你可以将前一个 process.uptime() 的结果传递给当前的 process.uptime()函数,结果会返回一个比较值,用于比较时间间隔。示例如下:

var time = process.hrtime();

setTimeout(function() {
  var diff = process.hrtime(time);

  console.log('共耗时 %d 毫秒', diff[0] * 1e9 + diff[1]);
  // 共耗时 1006913817 毫秒
}, 1000);