1.7 process

 process 

在 Node.js 里,process 属于全局对象,它能够提供与当前 Node.js 进程相关的各种信息和控制功能。借助 process 对象,你可以对环境变量进行访问、接收命令行参数、管理进程生命周期,还能与标准输入输出流进行交互:

1. 访问命令行参数

命令行参数可通过 process.argv 获取,这是一个包含所有命令行参数的数组。其中,argv[0] 是 Node.js 可执行文件的路径,argv[1] 是正在执行的 JavaScript 文件路径,从 argv[2] 开始才是真正传递给脚本的参数。

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

// 执行命令:node args.js hello world
// 输出:['/usr/bin/node', '/path/to/args.js', 'hello', 'world']

2. 环境变量获取

通过 process.env 可以访问系统的环境变量,这在获取配置信息时非常有用。

// 获取环境变量 NODE_ENV
const env = process.env.NODE_ENV || 'development';
console.log(`当前环境是: ${env}`);

3. 进程信息与控制

  • process.pid:用于获取当前进程的 ID。
  • process.ppid:可获取父进程的 ID。
  • process.exit([code]):能终止当前进程,并可选择返回退出码,默认退出码为 0。
  • process.kill(pid, [signal]):向指定 PID 的进程发送信号,这里的信号通常是字符串,像 'SIGTERM' 就是常见的信号之一。
console.log(`当前进程 ID 是: ${process.pid}`);

// 2 秒后终止进程
setTimeout(() => {
  process.exit(1); // 退出码 1 表示异常退出
}, 2000);

4. 标准输入输出流

  • process.stdout:这是标准输出流,类似于 console.log,但它是原始流。
  • process.stderr:作为标准错误流,用于输出错误信息。
  • process.stdin:是标准输入流,可用于读取用户输入。
// 从标准输入读取数据
process.stdin.setEncoding('utf8');

process.stdin.on('readable', () => {
  const chunk = process.stdin.read();
  if (chunk !== null) {
    process.stdout.write(`你输入的内容是: ${chunk}`);
  }
});

process.stdin.on('end', () => {
  process.stdout.write('结束输入\n');
});

5. 事件监听

process 对象可以监听多种事件,下面为你介绍几个重要事件:

  • beforeExit:在 Node.js 事件循环队列为空,且没有异步操作挂起时触发。
  • exit:在进程即将退出前触发,此时无法再注册新的监听器。
  • uncaughtException:当未被捕获的异常冒泡到事件循环时触发。
  • SIGINT:在进程接收到 Ctrl+C 信号时触发。
// 监听未捕获的异常
process.on('uncaughtException', (err) => {
  console.error('捕获到未处理的异常:', err);
  process.exit(1);
});

// 监听 Ctrl+C 信号
process.on('SIGINT', () => {
  console.log('接收到 SIGINT 信号,正在优雅地退出...');
  process.exit(0);
});

6. 资源使用情况

借助 process.memoryUsage() 可以获取进程的内存使用信息,该方法会返回一个包含以下字段的对象:

  • rss(常驻内存集):是进程占用的总内存。
  • heapTotal:是 V8 堆的总大小。
  • heapUsed:是 V8 堆已使用的大小。
  • external:是 V8 外部资源(如 Node.js 绑定的 C++ 对象)使用的内存。
console.log('内存使用情况:', process.memoryUsage());
// 输出示例:
// {
//   rss: 27705344,
//   heapTotal: 6291456,
//   heapUsed: 4154224,
//   external: 90594
// }

7. 执行平台信息

  • process.platform:可返回运行 Node.js 的平台,例如 'win32' 'linux' 'darwin' 等。
  • process.arch:能返回 CPU 架构,像 'x64' 'arm' 等。
console.log(`运行平台: ${process.platform}`);
console.log(`CPU 架构: ${process.arch}`);

8. 进程钩子

  • process.nextTick(callback):将回调函数放在当前事件循环的末尾执行,其优先级高于 setImmediate 和 setTimeout(0)
  • setImmediate(callback):在当前 I/O 阶段完成后执行回调函数。
process.nextTick(() => {
  console.log('nextTick 回调函数执行');
});

setImmediate(() => {
  console.log('setImmediate 回调函数执行');
});

console.log('主线程代码执行');

// 输出顺序:
// 主线程代码执行
// nextTick 回调函数执行
// setImmediate 回调函数执行

总结

process 对象是 Node.js 中极为重要的一个全局对象,它为开发者提供了进程级别的控制和系统信息访问能力。无论是处理命令行参数、与标准输入输出流交互,还是管理进程生命周期,process 对象都发挥着关键作用。

process.env 详解

在 Node.js 里,process.env 是一个至关重要的全局对象,它主要用于存储和访问环境变量。环境变量作为操作系统提供给进程的键值对,在应用程序的配置过程中起着关键作用,像数据库连接字符串、API 密钥以及应用运行环境等配置信息,都可以通过环境变量来设置。下面将对 process.env 进行详细的分析。

1. 基本概念

环境变量是操作系统中存储的动态命名值,不同的操作系统,其环境变量的设置方式也有所不同。

  • Windows:可以使用 set 命令来设置环境变量,例如 set NODE_ENV=development
  • Linux/macOS:使用 export 命令设置环境变量,如 export NODE_ENV=development

在 Node.js 应用程序中,可以通过 process.env 对象来获取这些环境变量的值,获取方式为 process.env.VARIABLE_NAME

2. 常见应用场景

2.1 应用环境配置

在开发过程中,我们常常需要区分不同的运行环境,如开发环境、测试环境和生产环境。通过 process.env.NODE_ENV 就可以轻松实现这一区分。

const env = process.env.NODE_ENV || 'development';
if (env === 'production') {
  // 生产环境配置
  console.log('应用运行在生产环境');
} else if (env === 'development') {
  // 开发环境配置
  console.log('应用运行在开发环境');
}
2.2 敏感信息存储

为了保证应用程序的安全性,像数据库密码、API 密钥这类敏感信息不应该直接硬编码在代码中,而是应该通过环境变量来存储。

const dbConfig = {
  host: process.env.DB_HOST || 'localhost',
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
};
2.3 端口配置

应用程序监听的端口也可以通过环境变量来设置,这样在不同的环境中就可以灵活调整端口号。

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`服务器运行在端口 ${port}`);
});

3. 环境变量的设置方法

3.1 命令行临时设置

在启动 Node.js 应用程序时,可以在命令行中临时设置环境变量,这种方式设置的环境变量仅在当前命令执行期间有效。

  • Windowsset VAR_NAME=value && node app.js
  • Linux/macOSVAR_NAME=value node app.js
# Linux/macOS
NODE_ENV=production PORT=8080 node app.js

# Windows PowerShell
$env:NODE_ENV="production"; $env:PORT="8080"; node app.js
3.2 系统环境变量设置

可以在操作系统中永久设置环境变量,这样所有的应用程序都可以访问这些环境变量。

  • Windows:通过系统属性 -> 高级系统设置 -> 环境变量进行设置。
  • Linux/macOS:在 ~/.bashrc~/.bash_profile 或 ~/.zshrc 文件中添加 export VAR_NAME=value
3.3 使用 .env 文件(推荐做法)

在开发环境中,推荐使用 .env 文件来管理环境变量。需要安装 dotenv 包,它可以将 .env 文件中的变量加载到 process.env 中。

npm install dotenv

在项目根目录下创建 .env 文件:

DB_HOST=localhost
DB_USER=root
DB_PASSWORD=secret
DB_NAME=mydb
API_KEY=your_api_key_here

在应用程序中加载 .env 文件:

require('dotenv').config();

// 现在可以访问 .env 文件中的变量
console.log(process.env.DB_HOST); // 输出: localhost

4. 特性与注意事项

4.1 数据类型

需要注意的是,process.env 中的所有值都是字符串类型。如果需要使用其他数据类型,如数字、布尔值等,需要进行显式的类型转换。

const port = parseInt(process.env.PORT, 10) || 3000;
const debug = process.env.DEBUG === 'true'; // 将字符串转换为布尔值
4.2 优先级

环境变量的设置存在一定的优先级顺序,从高到低依次为:命令行设置 > 系统环境变量 > .env 文件。如果同一个环境变量在多个地方都有设置,那么优先级高的设置会覆盖优先级低的设置。

4.3 安全性考量
  • 敏感信息,如密码、密钥等,绝对不能提交到版本控制系统中。为了避免这种情况,应该在 .gitignore 文件中添加 .env 文件。
  • 在生产环境中,建议通过部署平台的安全机制来设置环境变量,而不是依赖 .env 文件。
4.4 运行时特性

process.env 是在运行时动态加载的,这意味着在应用程序运行期间对环境变量所做的修改会直接反映在 process.env 中。不过,一旦 Node.js 进程启动,通过代码对 process.env 所做的修改不会影响操作系统的环境变量。

// 修改运行时的环境变量
process.env.NEW_VAR = 'new_value';
console.log(process.env.NEW_VAR); // 输出: new_value

5. 最佳实践

5.1 使用默认值

为了保证应用程序的健壮性,在使用环境变量时,应该为其提供默认值。

const env = process.env.NODE_ENV || 'development';
const port = process.env.PORT || 3000;
5.2 统一配置管理

将所有的环境变量配置集中管理,避免在代码中分散引用 process.env,这样可以提高代码的可维护性。

// config.js
module.exports = {
  env: process.env.NODE_ENV || 'development',
  database: {
    host: process.env.DB_HOST || 'localhost',
    port: parseInt(process.env.DB_PORT, 10) || 5432,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    name: process.env.DB_NAME
  },
  apiKey: process.env.API_KEY
};
5.3 开发环境与生产环境分离

在开发环境中,可以使用 .env.development.env.production 等文件来区分不同环境的配置。在加载时,根据 NODE_ENV 来选择加载相应的配置文件。

const env = process.env.NODE_ENV || 'development';
require('dotenv').config({ path: `.env.${env}` });

6. dotenv

  • dotenv:这是一个非常流行的模块,用于从 .env 文件加载环境变量。

dotenv 的注入机制本质上是:

  • 读取文件 → 2. 解析内容 → 3. 合并到 process.env
  1. 从指定路径读取 .env 文件
  2. 将文件内容解析为键值对
  3. 将键值对注入到 process.env 中(默认不覆盖已存在的变量)
简单模拟
2.1 读取文件内容

使用 Node.js 的 fs 模块同步读取 .env 文件:

const fs = require('fs');
const path = require('path');

// 读取 .env 文件内容(默认路径为项目根目录)
const filePath = path.resolve(process.cwd(), '.env');
const content = fs.readFileSync(filePath, 'utf8');
解析键值对

将文件内容按行分割并解析为键值对:

function parse(src) {
  const obj = {};
  
  // 按行分割并处理
  src.toString().split('\n').forEach(line => {
    const match = line.match(/^([^=]+)=(.*)$/);
    if (match) {
      const key = match[1].trim();
      // 处理引号包裹的值
      let value = match[2].trim();
      const maybeQuote = value[0];
      if (maybeQuote === '"' || maybeQuote === "'") {
        value = value.slice(1, -1);
      }
      obj[key] = value;
    }
  });
  
  return obj;
}

const envConfig = parse(content);
注入到 process.env

将解析后的键值对合并到 process.env 中:

function config(options) {
  try {
    const parsed = parse(content);
    
    // 合并到 process.env
    Object.keys(parsed).forEach(key => {
      // 只在变量未定义时注入(可通过 options.override 覆盖)
      if (!process.env[key]) {
        process.env[key] = parsed[key];
      }
    });
    
    return { parsed };
  } catch (e) {
    return { error: e };
  }
}
常见问题与注意事项
类型问题
  • process.env 中的值始终是字符串。例如:
    const debug = process.env.DEBUG; // 'true'(字符串)
    const isDebug = process.env.DEBUG === 'true'; // 需显式转换为布尔值
    
加载顺序
  • dotenv 必须在使用环境变量之前加载:
    // 错误:先使用后加载
    console.log(process.env.DB_HOST); // 可能为 undefined
    require('dotenv').config();
    
    // 正确:先加载后使用
    require('dotenv').config();
    console.log(process.env.DB_HOST); // 正确输出
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chxii

小小打赏,大大鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值