Node.js 中 child_process 模块教程

Node.js 中 child_process 模块教程

简介

Node.js 的 child_process 模块提供了在 Node.js 应用程序中创建和管理子进程的能力。这个功能对于执行系统命令、运行外部程序、以及充分利用多核 CPU 资源都非常有用。

主要方法

1. spawn()

spawn() 方法用于启动一个新进程来执行命令。它是异步的,适合处理大量数据的场景。

javascript 复制代码
const { spawn } = require('child_process');

// 执行 ls 命令
const ls = spawn('ls', ['-l']);

// 处理输出
ls.stdout.on('data', (data) => {
  console.log(`输出:${data}`);
});

// 处理错误
ls.stderr.on('data', (data) => {
  console.error(`错误:${data}`);
});

// 进程结束
ls.on('close', (code) => {
  console.log(`子进程退出码:${code}`);
});

2. exec()

exec() 方法会创建一个 shell 来执行命令,并缓冲产生的输出。适合执行简单的命令。

javascript 复制代码
const { exec } = require('child_process');

exec('ls -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`执行出错: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.error(`stderr: ${stderr}`);
});

3. execFile()

execFile() 直接执行一个可执行文件,不创建 shell。这使得它比 exec() 更高效。

javascript 复制代码
const { execFile } = require('child_process');

execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    console.error(`执行出错: ${error}`);
    return;
  }
  console.log(`Node 版本: ${stdout}`);
});

4. fork()

fork()spawn() 的特殊形式,专门用于创建 Node.js 进程。它会自动建立与子进程的 IPC 通道。

javascript 复制代码
const { fork } = require('child_process');

// 启动子进程
const child = fork('child.js');

// 向子进程发送消息
child.send({ hello: 'world' });

// 接收子进程消息
child.on('message', (message) => {
  console.log('收到子进程消息:', message);
});

进程间通信(IPC)

父进程和子进程之间可以通过 IPC 通道进行通信:

javascript 复制代码
// 父进程 (parent.js)
const { fork } = require('child_process');
const child = fork('child.js');

child.send({ type: 'greeting', data: 'Hello from parent' });
child.on('message', (message) => {
  console.log('Parent received:', message);
});

// 子进程 (child.js)
process.on('message', (message) => {
  console.log('Child received:', message);
  process.send({ type: 'response', data: 'Hello from child' });
});

错误处理和进程管理

错误处理

javascript 复制代码
const child = spawn('nonexistent-command');

child.on('error', (error) => {
  console.error('Failed to start child process:', error);
});

child.stderr.on('data', (data) => {
  console.error(`子进程错误输出:${data}`);
});

进程终止

javascript 复制代码
const child = spawn('long-running-process');

// 优雅地终止进程
child.kill('SIGTERM');

// 确保进程被终止
child.on('exit', (code, signal) => {
  console.log(`进程退出,退出码:${code},信号:${signal}`);
});

最佳实践

  1. 选择合适的方法

    • 使用 spawn() 处理大量数据
    • 使用 exec() 执行简单命令
    • 使用 execFile() 执行文件
    • 使用 fork() 运行 Node.js 模块
  2. 资源管理

    javascript 复制代码
    const child = spawn('some-process');
    
    // 设置超时
    const timeout = setTimeout(() => {
      child.kill();
    }, 5000);
    
    child.on('exit', () => {
      clearTimeout(timeout);
    });
  3. 错误处理

    javascript 复制代码
    const child = spawn('command');
    
    child.on('error', handleError);
    child.stdout.on('error', handleError);
    child.stderr.on('error', handleError);
    
    function handleError(err) {
      console.error('Error:', err);
      child.kill();
    }

进阶特性

1. 环境变量设置

javascript 复制代码
const child = spawn('node', ['script.js'], {
  env: { ...process.env, NODE_ENV: 'production' }
});

2. 工作目录设置

javascript 复制代码
const child = spawn('command', [], {
  cwd: '/custom/working/directory'
});

3. 管道和流

javascript 复制代码
const { spawn } = require('child_process');
const fs = require('fs');

const child = spawn('grep', ['pattern']);
const inputFile = fs.createReadStream('input.txt');
const outputFile = fs.createWriteStream('output.txt');

inputFile.pipe(child.stdin);
child.stdout.pipe(outputFile);

调试和监控

1. 状态监控

javascript 复制代码
const child = spawn('long-process');

child.on('spawn', () => {
  console.log('进程已启动');
});

child.on('disconnect', () => {
  console.log('IPC 通道已断开');
});

child.on('exit', (code, signal) => {
  console.log(`进程已退出:code ${code}, signal ${signal}`);
});

2. 性能监控

javascript 复制代码
const child = spawn('process');

const startTime = Date.now();
let bytesProcessed = 0;

child.stdout.on('data', (data) => {
  bytesProcessed += data.length;
});

child.on('exit', () => {
  const duration = Date.now() - startTime;
  console.log(`处理了 ${bytesProcessed} 字节,用时 ${duration}ms`);
});

注意事项

  1. 始终处理错误事件
  2. 注意设置适当的超时机制
  3. 合理管理子进程资源
  4. 避免启动过多子进程
  5. 谨慎处理用户输入
  6. 注意跨平台兼容性

安全考虑

  1. 输入验证

    javascript 复制代码
    const userInput = '...'; // 用户输入
    if (!/^[a-zA-Z0-9_-]+$/.test(userInput)) {
      throw new Error('Invalid input');
    }
  2. 权限控制

    javascript 复制代码
    const child = spawn('command', [], {
      uid: nonRootUser,
      gid: nonRootGroup
    });
相关推荐
Q_Q51100828514 小时前
python基于web的汽车班车车票管理系统/火车票预订系统/高铁预定系统 可在线选座
spring boot·python·django·flask·node.js·汽车·php
浪裡遊16 小时前
Nivo图表库全面指南:配置与用法详解
前端·javascript·react.js·node.js·php
weixin_4050233718 小时前
包资源管理器NPM 使用
前端·npm·node.js
Q_Q5110082851 天前
python+django/flask婚纱摄影拍照管理系统
spring boot·python·django·flask·node.js·php
长空任鸟飞_阿康1 天前
Node.js 核心模块详解:fs 模块原理与应用
前端·人工智能·ai·node.js
CS Beginner1 天前
【node】运行windows7下的高版本node.js
node.js
水冗水孚1 天前
fastify-sse-v2搭配EventSource实现SSE中的AI流式回复打字机效果&Fetch+ReadableStream+Chunked分块也可实现
node.js
小于小于09121 天前
npx 与 npm 区别
前端·npm·node.js
Shi_haoliu1 天前
Vue2 + Office Add-in关于用vue项目于加载项控制excel单元格内容(Demo版)
前端·javascript·vue.js·node.js·html·excel·office
aesthetician1 天前
Node.js v25 重磅发布!革新与飞跃:深入探索 JavaScript 运行时的未来
javascript·node.js·vim