Node.js进程管理详解:process模块与子进程创建

作者:服务小站时间:2026-10-21 23:52:13浏览:367

本文深入解析Node.js中的process全局对象及其事件机制,包括exit和uncaughtException的处理。详细列举process模块的关键属性,如版本、平台、内存及PID等。重点对比child_process.exec与spawn方法,讲解如何创建子进程以利用多核CPU资源,并介绍相关配置选项与隔离性回调。

Node.js进程概述

尽管Node.js对操作系统进行了大量抽象封装,开发者仍可直接与其交互,例如与系统中已存在的进程通信或创建工作子进程。Node.js基于事件循环机制运行,但允许在事件循环之外创建其他进程(或线程)来分担工作负载。

进程模块

进程模块

process模块提供了获取或修改当前Node.js进程设置的功能。与其他模块不同,process是一个全局对象(代表Node主进程),开发者可以直接通过process变量访问它,无需额外引入。

process实现了EventEmitter接口,其exit事件会在进程退出时触发。需要注意的是,进程一旦退出便不再执行事件循环,因此只有那些没有回调函数的同步代码才会被执行。在下面的示例中,setTimeout内的语句将无法执行。


process.on('exit', function () {
  setTimeout(function () {
    console.log('This will not run');
  }, 100);
  console.log('Bye.');
});

在接触Node.js的过程中,你会发现影响主事件循环的异常会导致整个Node进程崩溃,这是一个严重的问题。为此,process提供了uncaughtException事件来处理此类异常,允许开发者捕获并处理这些错误,从而避免进程直接宕机。


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.');

参考上述示例,我们注册了uncaughtException事件来捕捉系统异常。当代码执行到未定义的nonexistentFunc()时,会抛出异常。由于JavaScript是解释型语言,nonexistentFunc()之前的语句不受影响,但其后的语句不会执行。因此,输出结果如下:

Caught exception: ReferenceError: nonexistentFunc is not defined

This will still run.

再看一个具体的应用例子。


var http = require('http');
var server = http.createServer(function(req,res) {
  res.writeHead(200, {});
  res.end('response');
  badLoggingCall('sent response');
  console.log('sent response');
});
process.on('uncaughtException', function(e) {
  console.log(e);
});
server.listen(8080);

在此示例中,我们创建了一个Web服务器。在处理完请求后,代码尝试执行不存在的badLoggingCall()方法,从而抛出异常。由于我们注册了uncaughtException事件来处理该异常,服务器不会受到影响,得以继续运行,并在服务器端记录错误日志。

[ReferenceError: badLoggingCall is not defined]

与当前进程交互

与当前进程交互

Node.js提供了一系列process属性,供开发者查询或设置进程状态,具体如下:

process.version:包含当前Node.js实例的版本号;

process.installPrefix:包含Node.js的安装路径;

process.platform:显示Node运行的操作系统环境,仅返回内核相关信息,例如linux2、darwin,而不会显示“Redhat ES3”、“Windows 7”或“OSX 10.7”等具体版本标识;

process.uptime():返回当前进程运行的时长(单位:秒);

process.getgid()和process.setgid():分别用于获取或设置进程组ID(group id);

process.getuid()和process.setuid():分别用于获取或设置用户ID(user id);

process.pid:获取当前进程的ID;

process.title:设置或获取进程名称;

process.execPath:返回当前Node.js进程的可执行文件路径,例如/usr/local/bin/node;

process.cwd():返回当前工作目录;

process.memoryUsage():报告Node.js进程的内存使用情况。其中rss代表物理内存(RAM)的使用情况,vsize代表总虚拟内存使用大小,包括RAM和交换空间(swap);

process.heapTotal和process.heapUsed:分别代表V8引擎分配的堆内存总量和当前正在使用的堆内存大小。

事件循环和ticker

事件循环和ticker

Node.js提供了process.nextTick()方法,允许开发者访问事件循环并延迟执行工作。它类似于setTimeout(),但会在下一次tick时立即执行,且每隔一段时间会执行一次。这里有一个示例:


var http = require('http');
var s = http.createServer(function(req, res) {
  res.writeHead(200, {});
  res.end('foo');
  console.log('http response');
  process.nextTick(function(){console.log('tick')});
});
s.listen(8000);

当有请求到来时,会依次记录日志“http response”和“tick”;当没有请求时,每隔一段时间执行事件循环,会输出“tick”。

此外,通过nextTick创建的回调函数具有隔离性,它们之间不会相互影响。


process.on('uncaughtException', function(e) {
  console.log(e);
});
process.nextTick(function() {
  console.log('tick');
});
process.nextTick(function() {
  iAmAMistake();
  console.log('tock');
});
process.nextTick(function() {
  console.log('tick tock');
});
console.log('End of 1st loop');

在下面的示例中,首先输出“End of 1st loop”,然后按顺序执行nextTick的回调函数。第一个回调正常输出“tick”;第二个回调故意设置了一个异常,会输出异常信息,因此不会输出“tock”。得益于nextTick回调函数的隔离性,第三个回调仍会正常输出“tick tock”。运行结果如下:

End of 1st loop tick [ReferenceError: iAmAMistake is not defined] tick tock

子进程

子进程

Node.js提供了child_process模块,允许为主进程创建子进程,从而利用更多的服务器资源和CPU核心。这些概念在前面的章节中已有介绍。Node.js提供了child_process.spawn()和child_process.exec()两个方法来实现这一功能,下面将分别详细介绍。

child_process.exec( )

child_process.exec( )

来看exec的一个简单示例。它创建了一个子进程,第一个参数是Shell命令,第二个参数是回调函数,用于处理返回结果。


var cp = require('child_process');
cp.exec('ls -l', function(e, stdout, stderr) {
  if(!e) {
    console.log(stdout);
    console.log(stderr);
  }
});

exec()方法还可以接收options参数进行配置:


var options = { 
 encoding: 'utf8',
 timeout: 0,
 maxBuffer: 200 * 1024,
 killSignal: 'SIGTERM',
 setsid: false,
 cwd: null,
 env: null 
};
var cp = require('child_process');
cp.exec('ls -l', options, function(e, stdout, stderr) {
  if(!e) {
    console.log(stdout);
    console.log(stderr);
  }
});

encoding:I/O流的编码格式;

timeout:进程超时时间;

killSignal:当时间或缓冲区超限时终止进程的信号;

maxBuffer:stdout或stderr可增长的最大值;

setsid:决定在进程中是否创建一个新的会话;

cwd:进程的初始工作目录,为null时表示使用Node.js的当前工作目录;

env:进程的环境变量。

child_process.spawn( )

child_process.spawn( )

child_process.spawn()比child_process.exec()更加强大和灵活,具体示例如下:


var cp = require('child_process');
var cat = cp.spawn('cat');
cat.stdout.on('data', function(d) {
  console.log(d.toString());
});
cat.on('exit', function() {
  console.log('kthxbai');
});
cat.stdin.write('meow');
cat.stdin.end();

以上所述是小编给大家介绍的nodejs中的process进程,希望对大家有所帮助!

作者最新文章