目录
○ Event: ‘exit‘
○ Event: ‘uncaughtException‘
○ Signal Events
○ process.stdout
○ process.stderr
进程
Event: ‘exit‘
监听 exit 的例子:
1 process.on(‘exit‘, function(code) { 2 // do *NOT* do this 3 setTimeout(function() { 4 console.log(‘This will not run‘); 5 }, 0); 6 console.log(‘About to exit with code: ‘, code); 7 });
Event: ‘uncaughtException‘
监听 uncaughtException 的例子:
1 process.on(‘uncaughtException‘, function(err) { 2 console.log(‘Caught exception: ‘ + err); 3 }); 4 5 setTimeout(function() { 6 console.log(‘This will still run.‘); 7 }, 500); 8 9 // Intentionally cause an exception, but don‘t catch it 10 nonexitstentFunc(); 11 console.log(‘This will not run.‘);
注意 uncaughtException 是一种非常粗鲁的异常捕获途径且有可能在将来移除。
不要使用它,使用 domains 取代。如果你使用了它,在每个没被正常捕获的异常后重启你的应用程序。
不要使用它因为 node.js 相当于出了错待会恢复重新开始。一个未捕获的异常意味着你的应用程序——推而广之 node.js 本身处于未知状态。盲目地恢复意味着什么事情都有可发生。
假想当你正在升级系统时拔了电源线,然后恢复了。十次有九次都没事发生——但在第十次,你的系统就崩了。
你已经被警告过。
Signal Events
监听 SIGINT 的例子:
1 // Start reading from stdin so we don‘t exit. 2 process.stdin.resume(); 3 4 process.on(‘SIGINT‘, function() { 5 console.log(‘Got SIGINT. Press Control-D to exit.‘); 6 });
在大多数的终端程序中一个简单的发送 SIGINT 信号的方法是使用 Control-C。
注意:
- SIGUSR1 被 node.js 保留用以启动 debugger。可以创建一个监听器但那不会停止 debugger 的启动。
- SIGTERM 和 SIGINT 在非 Windows 平台下有默认的监听器,退出并在退出前重置终端 mode 为128加信号数值。如果这两信号之一创建了监听器,它们的默认操作将会被移除(node 将永不退出)。
- SIGPIPE 默认被忽略,他可以创建监听器。
- SIGHUP 在 Windows 下当控制台窗口被关闭时产生,在其他平台各个类似的条件下,参看 signal(7)。它可以创建监听器,然而 node 将在大约10秒后被 Windows 无条件终止。在非 Windows 平台下,SIGHUP 的默认行为是终止 node,但一旦创建了监听器默认的行为将被移除。
- SIGTERM 在 Windows 下不支持,可以被监听。
- SIGINT 从终端发送该信号能被所有平台支持,且通常可以用 CTRL+C 产生(即使这是可配置的)。当终端 raw 模式启动时它不能被产生。
- SIGBREAK 在 Windows 下当按下 CTRL+BREAK 时产生,在非 Windows 平台下可以别监听,但没有途径可以发送或产生它。
- SIGWINCH 当控制台改变大小时产生。在 Windows 下,这只会发生在鼠标正在移动时向控制台输入,或刻度的 tty 在 raw 模式下使用。
- SIGKILL 不可被监听,在任何平台下 node 都将无条件终止。
- SIGSTOP 不可被监听。
注意 Windows 不支持发送信号,但 node 使用 process.kill() 和 child_process.kill() 提供了一些模拟:——发送信号0可以用来查找进程是否存在——发送 SIGINT,SIGTERM 和 SIGKILL 让目标进程无条件退出。
process.stdout
例子:console.log 的定义
1 console.log = function(d) { 2 process.stdout.write(d + ‘\n‘); 3 };
process.stderr 和 process.stdout 和 Node 中的其他流不同,向它们写入通常是阻塞的。
- 当它们指向普通文件或 TTY 文件描述符时它们是阻塞的。
- 当它们指向管道:
○ 在 Linux/Unix 下是阻塞的。
○ 在 Windows 下与其他流一样是非阻塞的。
$ 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
更多信息参看 tty 文档。
process.stderr
写向标准错误输出的可写流。process.stderr 和 process.stdout 和 Node 中的其他流不同,向它们写入通常是阻塞的。
- 当它们指向普通文件或 TTY 文件描述符时它们是阻塞的。
- 当它们指向管道:
○ 在 Linux/Unix 下是阻塞的。
○ 在 Windows 下与其他流一样是非阻塞的。
process.stdin
打开标准输入并监听两个事件的例子:
1 process.stdin.setEncoding(‘utf8‘); 2 3 process.stdin.on(‘readable‘, function() { 4 var chunk = process.stdin.read(); 5 if (chunk !== null) { 6 process.stdout.write(‘data ‘ + chunk); 7 } 8 }); 9 10 process.stdin.on(‘end‘, function() { 11 process.stdout.write(‘end‘); 12 });
作为一个流,process.stdin 也可以用于“老”模式,那是为了兼容使用 v0.10 之前的 node 所写的代码。更多信息参看流兼容性。
在“老”模式下标准输入流默认是暂停的,所以必须调用 process.stdin.resume() 来从从里面读取。而且需要注意调用 process.stdin.resume() 本身会将流选择为“老”模式。
如果你正在启动一个新项目,你应该选择更现代的“新”流模式而不是“老”的。
process.argv
1 // print process.argv 2 process.argv.forEach(function(val, index, array) { 3 console.log(index + ‘: ‘ + val); 4 });
输出将会是:
$ node process-2.js one two=three four 0: node 1: /User/mjr/work/node/process-2.js 2: one 3: two=three 4: four
process.execPath
例子:
/usr/local/bin/node
process.execArgv
$ node --harmony script.js --version
process.execArgv 的结果:
[‘--harmony‘]
process.argv 的结果:
[‘/usr/local/bin/node‘, ‘script.js‘, ‘--version‘]
process.abort()
这会导致 node 发射一个 abort。这回引起 node 退出并创建一个核心文件。
process.chdir(directory)
1 console.log(‘Starting directory: ‘ + process.cwd()); 2 try { 3 process.chdir(‘/tmp‘); 4 console.log(‘New directory: ‘ + process.cwd()); 5 } 6 catch (err) { 7 console.log(‘chdir: ‘ + err); 8 }
process.cwd()
1 console.log(‘Current directory: ‘ + process.cwd());
process.env
process.exit([code])
1 process.exit(1);
执行 node 的 shell 将看到1作为退出码。
process.getgid()
1 if (process.gid) { 2 console.log(‘Current gid: ‘ + process.getgid()); 3 }
process.setgid(id)
1 if (process.getgid && process.setgid) { 2 console.log(‘Current gid: ‘ + process.getgid()); 3 try { 4 process.setgid(501); 5 console.log(‘New gid: ‘ + process.getgid()); 6 } 7 catch (err) { 8 console.log(‘Failed to set gid: ‘ + err); 9 } 10 }
process.getuid()
1 if (process.getuid) { 2 console.log(‘Current uid: ‘ + process.getuid()); 3 }
process.setuid(id)
1 if (process.getuid && porcess.setuid) { 2 console.log(‘Current uid: ‘ + process.getuid()); 3 try { 4 process.setuid(501); 5 console.log(‘New uid: ‘ + process.getuid()); 6 } 7 catch (err) { 8 console.log(‘Failed to set uid: ‘ + err); 9 } 10 }
process.getgroups()
process.setgroups(groups)
process.initgroups(user, extra_group)
1 console.log(process.getgroups()); // [ 0 ] 2 process.initgroups(‘bnoordhuis‘, 1000); // switch user 3 console.log(process.getgroups()); // [ 27, 30, 46, 1000, 0 ] 4 process.setgid(1000); // drop root gid 5 console.log(process.getgroups()); // [ 27, 30, 40, 1000 ]
process.version
1 console.log(‘Version: ‘ + process.version);
process.versions
1 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‘ }
process.config
{ 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‘ } }
process.kill(pid, [signal])
1 process.on(‘SIGHUP‘, function() { 2 console.log(‘Got SIGHUP signal.‘); 3 }); 4 5 setTimeout(function() { 6 console.log(‘Existing.‘); 7 process.exit(0); 8 }, 100); 9 10 process.kill(process.pid, ‘SIGHUP‘);
注意:当 Node.js 接收到 SIGUSR1 它会启动调试器,参看 Signal Events。
process.pid
1 console.log(‘This process is pid ‘ + process.pid);
process.title
process.arch
1 console.log(‘This processor architecture is ‘ + process.arch);
process.platform
1 console.log(‘This platform is ‘ + process.platform);
process.memoryUsage()
1 var util = require(‘util‘); 2 3 console.log(util.inspect(process.memoryUsage()));
这将打印:
{ rss: 4935680, heapTotal: 1826816, heapUsed: 650472 }
heapTotal 和 heapUsed 表示 V8 的内存使用。
process.nextTick(callback)
1 process.nextTick(function() { 2 console.log(‘nextTick callback‘); 3 });
在开发 API 时若你想给用户机会去在对象被创建之后但在任何 I/O 发生之前分配事件监听器,这个函数是很重要的。
1 function MyThing(options) { 2 this.setupOptions(options); 3 4 process.nextTick(function() { 5 this.startDoingStuff(); 6 }.bind(this)); 7 } 8 9 var thing = new MyThing(); 10 thing.getReadyForStuff(); 11 12 // thing.startDoingStuff() gets called now, not before.
保证 API 是100%同步的或100%异步的是非常重要的。考虑下面的例子:
1 // WARNING! DO NOT USE! BAD UNSAFE HAZARD! 2 function maybeSync(arg, cb) { 3 if (arg) { 4 cb(); 5 return; 6 } 7 8 fs.stat(‘file‘, cb); 9 }
这个 API 是冒险的。如果你执行下面:
1 maybeSync(true, function() { 2 foo(); 3 }); 4 bar();
那么不清楚到底 foo() 还是 bar() 先被执行。
这个方法会更好:
1 function definitelyAsync(arg, cb) { 2 if (arg) { 3 process.nextTick(cb); 4 return; 5 } 6 7 fs.stat(‘file‘, cb); 8 }
process.maxTickDepth
1 process.nextTick(function foo() { 2 process.nextTick(foo); 3 });
为了避免 Node 被一系列递归 nextTick 无限循环锁阻塞,它会延迟来让一些 I/O 每隔一段时间被执行。
process.maxTickDepth 的值是 nextTick 调用 nextTick 回调函数的最大深度,以在允许其他形式的 I/O 发起前进行评估。
process.umask([mask])
1 var oldmask, newmask = 0644; 2 3 oldmask = process.umask(newmask); 4 console.log(‘Changed umask from: ‘ + oldmask.toString(8) + 5 ‘ to ‘ + newmask.tostring(8));
process.uptime()
process.hrtime()
1 var time = process.hrtime(); 2 // [ 1800216, 25 ] 3 4 setTimeout(function() { 5 var diff = process.hrtime(time); 6 // [ 1, 552] 7 8 console.log(‘benchmark took %d nanoseconds‘, diff[0] * 1e9 + diff[1]); 9 // benchmark took 1000000527 nanaseconds 10 }, 1000);