Nodejs中,process是一个全局对象,它提供了与当前进程和运行时环境交互的方法和属性。通过process对象,我们可以访问进程的信息、控制流程和进行进程间通信,这些都是服务端语言应该具备的能力。本文将全面介绍process对象的使用场景,从基础概念到高级应用,带有代码示例,让您深入了解它的功能与用途。

公众号:Code程序人生,个人网站:https://creatorblog.cn

简单使用

首先,我们来看一些简单的process对象的基础用法。

获取命令行参数

通过process.argv属性可以获取命令行参数,其中argv[0]Nodejs可执行文件的路径,argv[1]是当前执行的脚本文件路径,后续元素是传递给脚本的命令行参数。

// process.js
console.log(process.argv);

执行以下命令:

node process.js arg1 arg2 arg3

输出结果:

详解Nodejs中的Process对象_后端

结果分析:

[
  'D:\\Nodejs\\node-v16.20.1-win-x86\\node.exe', // Nodejs可执行文件路径
  'D:\\代码\\code-test\\process.js',  // 当前执行的脚本路径
  'arg1', // 命令行参数
  'arg2',
  'arg3'
]

获取环境变量

通过process.env属性可以获取当前进程的环境变量,这在配置不同环境下的应用程序时非常有用。

写入环境变量的方式有很多很多,在前端通常在脚手架里通过cross-env来控制传入环境变量,今天我们写一个最容易演示的,直接在js文件里写入。

// env.js
process.env.NODE_ENV = 'production';
// process.js
require('./env');
console.log(process.env);
console.log(process.env.NODE_ENV);

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_node.js_02

在正式的项目里,咱们可以通过判断环境变量所处的环境,比如开发环境、测试环境、生产环境,来做不同的应对,比如对请求后端接口的前置路径的控制等。

退出进程

通过process.exit()方法可以使进程退出,接收一个可选的退出码参数。

// process.js
console.log("退出前");
process.exit(0);
console.log("退出后"); // 不会执行到这里

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_优先级_03

结果分析:

从结果上来看,在输出 “退出前” 之后,通过process提供的exit方法退出此进程,导致后续并没有输出 “退出后”。

信号处理

通过process.on('SIGINT', callback)方法可以捕获SIGINT信号(通常由Ctrl+C触发),从而实现对进程的优雅退出。

// process.js
process.on('SIGINT', () => {
    console.log("接收到SIGINT信号。正在退出...");
    process.exit(0);
});
console.log("正在等待SIGINT信号...");

setTimeout(() => {

}, 1000000);

因为要复现通过Ctrl + C实现捕获SIGINT信号的方式结束进程,所以我们需要让进程一直运行中,方式有很多,比如起一个web服务等方式,最简单粗暴的,肯定还是使用定时器,给一个很大的延迟秒数,促使此进程不会很快结束,让我们可以手动通过Ctrl + C捕获信号的形式来执行回调函数的内容。

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_后端_04

通过实际操作,可以复现既定的效果,让我们在进程结束之前通过回调函数做很多需要做的事情

进程间通信

Nodejs中,我们可以通过process对象实现进程间通信,这对于父子进程之间的协作或者多个进程之间的数据传递都很有用。Nodejs提供了child_process模块来实现与子进程的交互。

子进程的创建与通信

通过spawn()方法创建一个子进程,并通过stdinstdoutstderr来进行通信。

// process.js
const { spawn } = require('child_process');

const command = process.platform === 'win32' ? 'cmd.exe' : 'ls';
const args = process.platform === 'win32' ? ['/c', 'dir', '/b'] : ['-l'];

const childProcess = spawn(command, args);

childProcess.stdout.on('data', (data) => {
  console.log(`子进程输出:\n${data}`);
});

childProcess.stderr.on('data', (data) => {
  console.error(`子进程异常:\n${data}`);
});

childProcess.on('close', (code) => {
  console.log(`子进程已退出,返回代码:${code}`);
});

在不同的操作系统和不同的系统位数中,相关处理可能不同,所以我们做了兼容。

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_后端_05

在上述示例中,我们创建了一个子进程来执行一些输出目录信息的命令,并通过stdoutstderr事件捕获子进程的输出和错误信息。close事件在子进程退出时触发。

父进程与子进程之间的消息传递

除了通过标准输入输出进行通信外,父进程和子进程还可以通过消息传递的方式进行通信,Nodejs提供了fork()方法来创建具有IPC通信的子进程。

// process.js
const { fork } = require('child_process');

const childProcess = fork('./child.js');

childProcess.on('message', (message) => {
  console.log(`父进程收到消息: ${message}`);
});

childProcess.send('Hello,我是父进程!');
// child.js
process.on('message', (message) => {
    console.log(`子进程收到消息: ${message}`);
    process.send('你好,我是子进程!');
});

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_前端_06

进程信号与事件

Nodejs中的process对象提供了许多事件和信号,用于监听和处理进程相关的状态和事件。

exit事件

exit事件在进程即将退出时触发,可以用来执行一些清理工作。

// process.js
process.on('exit', (code) => {
  console.log(`进程将退出,返回的代码是: ${code}`);
});

console.log("开始!");

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_优先级_07

uncaughtException事件

uncaughtException事件用于捕获未被捕获的异常,但注意它不能替代正常的异常处理,只应该用于记录异常并尽量优雅地退出进程。

// process.js
process.on('uncaughtException', (err) => {
    console.error(`未被捕获的异常: ${err.message}`);
    // 这里可以进行一些异常处理逻辑
});

console.log("开始!");

// 模拟未被捕获的异常
throw new Error("出了问题");
console.log("这里不会被输出");

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_子进程_08

warning事件

warning事件用于捕获一些废弃的API使用或其它可能导致问题的警告信息。

// process.js
process.on('warning', (warning) => {
    console.warn(`警告: ${warning.message}`);
});

// 模拟发出一个废弃API的警告
process.emitWarning("这是不推荐使用的API用法,不推荐使用警告");

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_node.js_09

beforeExit事件

beforeExit事件在进程即将退出之前触发,可以用于执行一些异步操作,但不能阻止进程的退出。

process.on('beforeExit', (code) => {
    console.log(`进程将退出,返回的代码是: ${code}`);
});

console.log("开始!");

// 模拟异步操作
setTimeout(() => {
    console.log("已执行异步操作");
}, 1000);

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_子进程_10

SIGINT信号

SIGINT之前已经介绍过一次了。SIGINT信号通常由Ctrl+C触发,用于请求进程终止。我们可以捕获该信号,并实现优雅地退出进程。

// process.js
process.on('SIGINT', () => {
    console.log("接收到SIGINT信号。正在退出...");
    process.exit(0);
});

console.log("等待SIGINT信号...");

setTimeout(() => {

}, 1000000);

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_子进程_11

SIGHUP、SIGTERM、SIGQUIT信号

除了SIGINT信号,还有一些其他信号可以用于控制进程的行为,例如SIGHUPSIGTERMSIGQUIT等。可以使用类似的方式捕获这些信号并实现相应的处理,这几个信号对于大部分人来说可能不常用,下面我简单叙述一下:

SIGHUP信号

SIGHUP(Hang Up)信号通常在以下情况下发送给进程:

  1. 当终端连接(例如SSH会话)关闭时,与该终端关联的所有进程会收到SIGHUP信号。
  2. 如果操作系统出现某些问题,导致终端会话意外终止,进程也可能收到SIGHUP信号。

默认情况下,对于大多数终端连接,SIGHUP会终止进程。但是,您可以在Nodejs中通过监听process对象的SIGHUP事件来处理这个信号,并在进程终止之前执行一些清理操作。

以下是一个简单的代码示例:

process.on('SIGHUP', () => {
  console.log('收到SIGHUP信号。正在执行清理...');
  // 执行清理操作,如关闭数据库连接、保存数据等
  process.exit(0); // 可以选择退出进程,或执行其他操作
});

SIGTERM信号

SIGTERM信号是由系统管理员或其他进程发送给进程,用于请求进程优雅地终止。SIGTERM通常用于正常关闭进程,允许进程完成正在进行的操作并进行清理,然后自行终止。

Nodejs中,您可以通过监听process对象的SIGTERM事件来处理SIGTERM信号,并在进程终止之前执行清理操作。

以下是一个简单的代码示例:

process.on('SIGTERM', () => {
  console.log('收到SIGTERM信号。正在执行清理...');
  // 执行清理操作,如关闭数据库连接、保存数据等
  process.exit(0); // 可以选择退出进程,或执行其他操作
});

SIGQUIT信号

SIGQUIT信号也是由系统管理员或其他进程发送给进程,用于请求进程终止,但与SIGTERM不同的是,SIGQUIT会产生core dump文件,用于进程调试和故障排除。

Nodejs中,可以通过监听process对象的SIGQUIT事件来处理SIGQUIT信号,并在进程终止之前执行一些清理操作。

以下是一个简单的代码示例:

process.on('SIGQUIT', () => {
  console.log('收到SIGQUIT信号。正在执行清理...');
  // 执行清理操作,如关闭数据库连接、保存数据等
  process.exit(0); // 可以选择退出进程,或执行其他操作
});

请注意,这些信号的处理方式可以根据应用程序的需求进行自定义。对于SIGTERMSIGQUIT信号,您可以在收到信号后执行清理操作,并自行决定是否退出进程。对于SIGHUP信号,默认行为是终止进程,但您可以通过监听SIGHUP信号并处理它来更改这种行为。

进程资源与性能

process对象还提供了一些方法,用于获取当前进程的资源使用情况和性能指标。

获取内存使用情况

// process.js
const used = process.memoryUsage();

console.log(`Memory Usage:`);
console.log(`  - RSS: ${used.rss} bytes`);
console.log(`  - Heap Total: ${used.heapTotal} bytes`);
console.log(`  - Heap Used: ${used.heapUsed} bytes`);
console.log(`  - External: ${used.external} bytes`);

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_前端_12

获取CPU使用情况

// process.js
const startTime = process.hrtime();

setTimeout(() => {
  const endTime = process.hrtime(startTime);
  console.log(`CPU Usage:`);
  console.log(`  - Execution time: ${endTime[0]}s ${endTime[1] / 1000000}ms`);
}, 1000);

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_前端_13

设置进程标题与优先级

设置进程标题

// process.js

// 设置进程标题
process.title = "My Node.js App";

// 输出进程标题
console.log(process.title);

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_子进程_14

设置进程优先级

Nodejs中,可以使用os模块来设置进程的优先级。具体来说,可以使用os.priority()方法来设置进程的调度优先级。

// process.js
const os = require('os');

// 设置进程的调度优先级为高
os.setPriority(os.constants.priority.PRIORITY_HIGH);

// 获取进程的调度优先级
const priority = os.getPriority();
console.log(`进程优先级: ${priority}`);

执行以下命令:

node process.js

输出结果:

详解Nodejs中的Process对象_优先级_15

注意

Nodejs中,os.getPriority()方法返回的数值表示进程的调度优先级。不同的操作系统可能有不同的标准来表示进程优先级,但通常情况下,较小的负数值表示较高的优先级。

Windows系统中,优先级值的范围是 -15 到 15,其中 -15 表示最高优先级,15 表示最低优先级。因此,我在Nodejs中使用os.getPriority()方法返回值为 -14,那么在Windows系统中这个值表示的是接近最高优先级的状态。

需要注意的是,在不同的操作系统上,os.getPriority()方法返回的值可能会有所不同。例如,Linux操作系统上的优先级值范围可能是不同的,具体取决于操作系统的调度策略。

要实现跨平台的代码,最好避免硬编码特定操作系统的优先级值,而是根据需要使用更具有可移植性的方法和方式来设置进程优先级。如果你的应用程序需要使用特定优先级,请确保在不同操作系统上进行适当的测试和调整。

总结

process对象是Nodejs中非常重要的全局对象,提供了许多与进程和运行时环境交互的方法和属性。

在本文中,我们从基础的命令行参数获取和环境变量访问开始,逐步深入到进程间通信、信号处理、进程资源与性能等高级用法。

希望这篇博文能够帮助大家全面了解并灵活应用process对象在Nodejs应用程序开发中。


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: NodeJS