path:路径处理

import path from 'path';

// 拼接(跨平台)
path.join('a', 'b', 'c');                  // 'a/b/c'(Linux)或 'a\\b\\c'(Windows)
path.join(__dirname, 'data', 'config.json');

// 解析(绝对路径)
path.resolve('a', 'b');                     // /cwd/a/b
path.resolve('/foo', 'bar');                // /foo/bar
path.resolve('./relative');                 // /cwd/relative

// 拆解
const p = '/home/wadely/project/index.js';
path.basename(p)                            // 'index.js'
path.basename(p, '.js')                     // 'index'
path.dirname(p)                             // '/home/wadely/project'
path.extname(p)                             // '.js'

// 解构所有
path.parse(p)
// { root: '/', dir: '/home/wadely/project', base: 'index.js', ext: '.js', name: 'index' }

// 反向(拼回字符串)
path.format({ dir: '/home', name: 'a', ext: '.txt' })   // '/home/a.txt'

// 相对路径
path.relative('/data/a', '/data/b/c');     // '../b/c'

path.posix vs path.win32

path.posix.join('a', 'b');                  // 'a/b'(永远用 /)
path.win32.join('a', 'b');                  // 'a\\b'(永远用 \)

os:系统信息

import os from 'os';

os.platform()                               // 'linux' / 'darwin' / 'win32'
os.arch()                                    // 'x64' / 'arm64'
os.release()                                 // 系统内核版本
os.hostname()                                // 主机名

os.cpus()                                    // CPU 信息数组
os.cpus().length                             // 核数

os.totalmem()                                // 总内存(字节)
os.freemem()                                 // 空闲内存
os.loadavg()                                 // [1分,5分,15分] 负载(Linux/macOS)

os.uptime()                                  // 系统开机秒数
os.userInfo()                                // { username, uid, gid, shell, homedir }
os.tmpdir()                                  // 临时目录 /tmp 或 C:\Users\..\Temp
os.homedir()                                 // 家目录
os.networkInterfaces()                       // 网卡列表

os.EOL                                       // 换行符(\n 或 \r\n)
os.constants.signals                         // SIGTERM = 15 等

实战:

// 多核应用根据核数起子进程
const workers = Math.max(1, os.cpus().length - 1);

// 跨平台换行
const lines = data.split(os.EOL);

// 跨平台临时文件
import { join } from 'path';
const tmpFile = join(os.tmpdir(), 'myapp.tmp');

process:进程对象

process.argv                                 // 启动参数数组
process.env                                  // 环境变量对象
process.env.NODE_ENV                         // 常用
process.env.HOME                              // 跨平台用 os.homedir()

process.cwd()                                // 当前工作目录
process.chdir('/tmp')                        // 切目录

process.pid                                  // 当前 PID
process.ppid                                 // 父进程 PID

process.platform                              // 同 os.platform()
process.arch                                  // 同 os.arch()
process.version                               // Node 版本

process.uptime()                             // 进程跑了多久(秒)
process.memoryUsage()                        // 内存:rss / heapTotal / heapUsed / external
process.cpuUsage()                           // CPU 时间

process.exit(0)                              // 退出(小心用,跳过清理)
process.exitCode = 1                          // 设退出码但等自然退出

信号处理

process.on('SIGINT', () => {                 // Ctrl+C
    console.log('Got SIGINT, cleaning up...');
    process.exit(0);
});

process.on('SIGTERM', () => {                // kill 信号
    server.close(() => process.exit(0));
});

process.on('uncaughtException', (err) => {
    console.error('Uncaught:', err);
    process.exit(1);
});

process.on('unhandledRejection', (reason) => {
    console.error('Unhandled rejection:', reason);
    process.exit(1);
});

process.on('exit', (code) => {
    // 同步清理(异步在这里不可靠)
    console.log(`Exiting with code ${code}`);
});

标准输入输出

process.stdin                                // ReadStream
process.stdout                                // WriteStream
process.stderr                                // WriteStream

process.stdout.write('hello');               // 无换行(console.log 有)
process.stderr.write('error');               // 写到 stderr

实战:优雅退出

const server = http.createServer(...);
server.listen(8080);

let shuttingDown = false;
async function shutdown(signal) {
    if (shuttingDown) return;
    shuttingDown = true;
    console.log(`${signal} received, shutting down...`);
    server.close();
    await db.close();
    process.exit(0);
}

process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));

  • process.exit(0) 不会等待 Promise / pending I/O—— 用 process.exitCode = 0 自然退出
  • 环境变量永远是字符串(不是 boolean / number)—— process.env.DEBUG === 'true' 才行
  • Windows 没 SIGTERM 信号——跨平台脚本要小心
  • process.argv[0] 是 node 路径,[1] 是脚本路径,用户参数从 [2]

下一篇:Stream。