关闭

女兔帮

Node.js 进程

更新时间:2025-02-19 08:56:43 浏览:

进程

本节介绍Node.js的(过程)对象,它提供有关当前Node.js过程的信息和控制。

是全局对象,能够在任意位置对其进行访问,而无需使用(),是的实例。

退出状态码

当不需要处理新的异步的操作时,Node正常情况下退出时会返回状态码0。下面提供了一些表示其他状态的状态码:

事件: 'exit'

当进程准备退出时触发。此时已经没有办法阻止从事件循环中推出。因此,你必须在处理函数中执行同步操作。这是一个在固定事件检查模块状态(比如单元测试)的好时机。回调函数有一个参数,它是进程的退出代码。

监听exit事件的例子:

process.on('exit', function(code) {
  // do *NOT* do this
  setTimeout(function() {
    console.log('This will not run');
  }, 0);
  console.log('About to exit with code:', code);
});

事件: ''

当node清空事件循环,并且没有其他安排时触发这个事件。通常来说,当没有进程安排时node退出,但是''的监听器可以异步调用,这样node就会继续执行。

''并不是明确退出的条件,.exit()或异常捕获才是,所以不要把它当做'exit'事件。除非你想安排更多的工作。

事件: ''

当一个异常冒泡回到事件循环,触发这个事件。如果给异常添加了监视器,默认的操作(打印堆栈跟踪信息并退出)就不会发生。

监听的例子:

process.on('uncaughtException', function(err) {
  console.log('Caught exception: ' + err);
});
setTimeout(function() {
  console.log('This will still run.');
}, 500);
// Intentionally cause an exception, but don't catch it.
nonexistentFunc();
console.log('This will not run.');

注意:是非常简略的异常处理机制。

尽量不要使用它,而应该用 。如果你用了,每次未处理异常后,重启你的程序。

不要使用node.js里诸如On Error Next这样操作。每个未处理的异常意味着你的程序,和你的node.js扩展程序,一个未知状态。盲目的恢复意味着任何事情都可能发生

你在升级的系统时拉掉了电源线,然后恢复了。可能10次里有9次没有问题,但是第10次,你的系统可能就会挂掉。

事件

当进程接收到信号时就触发。信号列表详见标准的POSIX信号名,如、等。

监听的例子:

// Start reading from stdin so we don't exit.
process.stdin.resume();
process.on('SIGINT', function() {
  console.log('Got SIGINT.  Press Control-D to exit.');
});

在大多数终端程序里,发送信号的简单方法是按下信号-C。

注意:

不支持发送信号,但是node提供了很多.kill()和.kill()的模拟:

.

一个 执向(fd1).

例如:.log的定义:

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

.和.和 node 里的其他流不同,他们不会被关闭(end()将会被抛出),它们不会触发事件,并且写是阻塞的。

检查Node是否运行在TTY上下文中,从.,.或.stdin里读取isTTY属性。

$ node -p "Boolean(process.stdin.isTTY)"
true
$ echo "foo" | node -p "Boolean(process.stdin.isTTY)"
false
$ node -p "Boolean(process.stdout.isTTY)"
true
$ node -p "Boolean(process.stdout.isTTY)" | cat
false

更多信息参见the tty docs。

.

一个指向 (fd2)的可写流。

.和.和node里的其他流不同,他们不会被关闭(end()将会被抛出),它们不会触发事件,并且写是阻塞的。

.stdin

一个指向stdin (fd0)的可读流。

以下例子:打开标准输入流,并监听两个事件:

process.stdin.setEncoding('utf8');
process.stdin.on('readable', function() {
  var chunk = process.stdin.read();
  if (chunk !== null) {
    process.stdout.write('data: ' + chunk);
  }
});
process.stdin.on('end', function() {
  process.stdout.write('end');
});

.stdin可以工作在老模式里,和v0.10之前版本的node代码兼容。

更多信息参见 .

在老的流模式里,stdin流默认暂停,必须调用.stdin.()读取。可以调用.stdin.()切换到老的模式。

如果开始一个新的工程,最好选择新的流,而不是用老的流。

.argv

包含命令行参数的数组。第一个元素是'node',第二个参数是文件的名字,第三个参数是任意的命令行参数。

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

将会生成:

$ node process-2.js one two=three four
0: node
1: /Users/mjr/work/node/process-2.js
2: one
3: two=three
4: four

.

开启当前进程的执行文件的绝对路径。

例子:

/usr/local/bin/node

.

启动进程所需的 node 命令行参数。这些参数不会在.argv里出现,并且不包含node执行文件的名字,或者任何在名字之后的参数。这些用来生成子进程,使之拥有和父进程有相同的参数。

例子:

$ node --harmony script.js --version

. 的参数:

['--harmony']

.argv 的参数:

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

.abort()

这将导致node触发abort事件。会让node退出并生成一个核心文件。

.chdir()

改变当前工作进程的目录,如果操作失败抛出异常。

console.log('Starting directory: ' + process.cwd());
try {
  process.chdir('/tmp');
  console.log('New directory: ' + process.cwd());
}
catch (err) {
  console.log('chdir: ' + err);
}

.cwd()

返回当前进程的工作目录:

console.log('Current directory: ' + process.cwd());

.env

包含用户环境的对象,参见(7).

这个对象的例子:

{ TERM: 'xterm-256color',
  SHELL: '/usr/local/bin/bash',
  USER: 'maciej',
  PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
  PWD: '/Users/maciej',
  EDITOR: 'vim',
  SHLVL: '1',
  HOME: '/Users/maciej',
  LOGNAME: 'maciej',
  _: '/usr/local/bin/node' }

你可以写入这个对象,但是不会改变当前运行的进程。以下的命令不会成功:

node -e 'process.env.foo = "bar"' && echo $foo

这个会成功:

process.env.foo = 'bar';
console.log(process.env.foo);

.exit([code])

使用指定的code结束进程。如果忽略,将会使用code 0

使用失败的代码退出:

process.exit(1);

Shell将会看到退出代码为1.

.

进程退出时的代码,如果进程优雅的退出,或者通过.exit()退出,不需要指定退出码。

设定.exit(code)将会重写之前设置的.。

.()

注意:这个函数仅在POSIX平台上可用(例如,非和)。

获取进程的群组标识(参见(2))。获取到得时群组的数字id,而不是名字。

if (process.getgid) {
  console.log('Current gid: ' + process.getgid());
}

.(id)

注意:这个函数仅在POSIX平台上可用(例如,非 和 )。

设置进程的群组标识(参见(2))。可以接收数字ID或者群组名。如果指定了群组名,会阻塞等待解析为数字ID 。

if (process.getgid && process.setgid) {
  console.log('Current gid: ' + process.getgid());
  try {
    process.setgid(501);
    console.log('New gid: ' + process.getgid());
  }
  catch (err) {
    console.log('Failed to set gid: ' + err);
  }
}

.()

注意:这个函数仅在POSIX平台上可用(例如,非和)。

获取进程的用户标识(参见(2))。这是数字的用户id,不是用户名:

if (process.getuid) {
  console.log('Current uid: ' + process.getuid());
}

.(id)

注意:这个函数仅在POSIX平台上可用(例如,非和)。

设置进程的用户标识(参见(2))。接收数字ID或字符串名字。果指定了群组名,会阻塞等待解析为数字ID。

if (process.getuid && process.setuid) {

Node.js 进程(图1)

console.log('Current uid: ' + process.getuid()); try { process.setuid(501); console.log('New uid: ' + process.getuid()); } catch (err) { console.log('Failed to set uid: ' + err); } }

.()

注意:这个函数仅在POSIX平台上可用(例如,非和)。

返回进程的群组iD数组。POSIX系统没有保证一定有,但是node.js保证有。

.()

注意:这个函数仅在POSIX平台上可用(例如,非和)。

设置进程的群组ID。这是授权操作,所有你需要有root权限,或者有能力。

列表可以包含群组IDs,群组名,或者两者都有。

.(user, )

注意:这个函数仅在POSIX平台上可用(例如,非和)。

读取/etc/group ,并初始化群组访问列表,使用成员所在的所有群组。这是授权操作,所有你需要有root权限,或者有能力。

user是用户名或者用户ID,是群组名或群组ID。

当你在注销权限 ( ) 的时候需要注意. 例子:

console.log(process.getgroups());         // [ 0 ]
process.initgroups('bnoordhuis', 1000);   // switch user
console.log(process.getgroups());         // [ 27, 30, 46, 1000, 0 ]
process.setgid(1000);                     // drop root gid
console.log(process.getgroups());         // [ 27, 30, 46, 1000 ]

.

一个编译属性,包含。

console.log('Version: ' + process.version);

.

一个属性,包含了node的版本和依赖。

console.log(process.versions);

打印出来:

{ http_parser: '1.0',
  node: '0.10.4',
  v8: '3.14.5.8',
  ares: '1.9.0-DEV',
  uv: '0.10.3',
  zlib: '1.2.3',
  modules: '11',
  openssl: '1.0.1e' }

.

一个包含用来编译当前node执行文件的配置选项的对象。它与运行./ 脚本生成的".gypi"文件相同。

一个可能的输出:

{ target_defaults:
   { cflags: [],
     default_configuration: 'Release',
     defines: [],
     include_dirs: [],
     libraries: [] },
  variables:
   { host_arch: 'x64',
     node_install_npm: 'true',
     node_prefix: '',
     node_shared_cares: 'false',
     node_shared_http_parser: 'false',
     node_shared_libuv: 'false',
     node_shared_v8: 'false',
     node_shared_zlib: 'false',
     node_use_dtrace: 'false',
     node_use_openssl: 'true',
     node_shared_openssl: 'false',
     strict_aliasing: 'true',
     target_arch: 'x64',
     v8_use_snapshot: 'true' } }

.kill(pid[, ])

发送信号给进程。pid是进程id,并且是发送的信号的字符串描述。信号名是字符串,比如''或''。如果忽略,信号会是''。更多信息参见和kill(2) .

如果进程没有退出,会抛出错误。信号0可以用来测试进程是否存在。

注意,虽然这个这个函数名叫.kill,它真的仅是信号发射器,就像kill系统调用。信号发射可以做其他事情,不仅是杀死目标进程。

例子, 给自己发信号:

process.on('SIGHUP', function() {
  console.log('Got SIGHUP signal.');
});
setTimeout(function() {
  console.log('Exiting.');
  process.exit(0);
}, 100);
process.kill(process.pid, 'SIGHUP');

注意:当Node.js接收到信号,它会开启调试模式, 参见.

.pid

当前进程的PID:

console.log('This process is pid ' + process.pid);

.title

获取/设置(/) 'ps'中显示的进程名。

使用时,字符串的长度由系统指定,可能会很短。

在Linux和OS X上,它受限于名称的长度加上命令行参数的长度,因为它会覆盖参数内存(argv )。

v0.8版本允许更长的进程标题字符串,也支持覆盖环境内存,但是存在潜在的不安全和混乱(很难说清楚)。

.arch

当前CPU的架构:'arm'、'ia32'或者'x64'。

console.log('This processor architecture is ' + process.arch);

.

运行程序所在的平台系统'','','linux','sunos'或者'win32'

console.log('This platform is ' + process.platform);

.()

返回一个对象,描述了Node进程所用的内存状况,单位为字节。

var util = require('util');
console.log(util.inspect(process.memoryUsage()));

将会生成:

{ rss: 4935680,
  heapTotal: 1826816,
  heapUsed: 650472 }

和指V8的内存使用情况。

.()

一旦当前事件循环结束,调用回到函数。

这不是(fn, 0)的简单别名,这个效率更高。在任何附加I/O事件在子队列事件循环中触发前,它就会运行。

console.log('start');
process.nextTick(function() {
  console.log('nextTick callback');
});
console.log('scheduled');
// Output:
// start
// scheduled
// nextTick callback

在对象构造后,在I/O事件发生前,你又想改变附加事件处理函数时,这个非常有用。

function MyThing(options) {
  this.setupOptions(options);
  process.nextTick(function() {
    this.startDoingStuff();
  }.bind(this));
}
var thing = new MyThing();
thing.getReadyForStuff();
// thing.startDoingStuff() gets called now, not before.

要保证你的函数一定是100%同步执行,或者100%异步执行。例子:

// WARNING!  DO NOT USE!  BAD UNSAFE HAZARD!
function maybeSync(arg, cb) {
  if (arg) {
    cb();
    return;
  }
  fs.stat('file', cb);
}

这个API非常危险. 如果你这么做:

maybeSync(true, function() {
  foo();
});
bar();

不清楚foo()或bar()哪个先执行。

更好的方法:

function definitelyAsync(arg, cb) {
  if (arg) {
    process.nextTick(cb);
    return;
  }
  fs.stat('file', cb);
}

注意:队列会在完全执行完毕之后才调用I/O操作。因此,递归设置的回调就像一个while(true);循环一样,将会阻止任何I/O操作的发生。

.umask([mask])

设置或读取进程文件的掩码。子进程从父进程继承掩码。如果mask参数有效,返回旧的掩码。否则,返回当前掩码。

var oldmask, newmask = 0022;
oldmask = process.umask(newmask);
console.log('Changed umask from: ' + oldmask.toString(8) +
            ' to ' + newmask.toString(8));

.()

返回Node已经运行的秒数。

.()

返回当前进程的高分辨时间,形式为[, ]数组。它是相对于过去的任意事件。该值与日期无关,因此不受时钟漂移的影响。主要用途是可以通过精确的时间间隔,来衡量程序的性能。

你可以将之前的结果传递给当前的.(),会返回两者间的时间差,用来基准和测量时间间隔。

var time = process.hrtime();
// [ 1800216, 25 ]
setTimeout(function() {
  var diff = process.hrtime(time);
  // [ 1, 552 ]
  console.log('benchmark took %d nanoseconds', diff[0] * 1e9 + diff[1]);
  // benchmark took 1000000527 nanoseconds
}, 1000);

.

.main的备选方法。不同点,如果主模块在运行时改变,.main可能会继续返回老的模块。可以认为,这两者引用了同一个模块。

该.属性提供了一种替代的检索方式.main。不同之处在于,如果主模块在运行时发生更改,.main可能仍会引用发生更改之前所需模块中的原始主模块。通常,假设这两个参照相同的模块是安全的。

和.main一样, 如果没有入口脚本,将会返回。

你可能感兴趣的