现在位置: 首页 > Node.js 教程 > 正文

Node.js child_process 模块

Java FileNode.js 内置模块


Node.js 是一个单线程的 JavaScript 运行时环境,但有时候我们需要执行一些系统命令或运行其他程序。这时就需要用到 child_process 模块。

child_process 模块允许 Node.js 应用程序创建子进程,这些子进程可以执行系统命令、运行其他脚本或程序,并与父进程进行通信。


为什么需要 child_process?

  1. 执行系统命令:比如执行 lsgit 等命令行工具
  2. 运行 CPU 密集型任务:避免阻塞 Node.js 主线程
  3. 与其他语言编写的程序交互:比如调用 Python 或 C++ 程序
  4. 提高应用性能:通过多进程充分利用多核 CPU

创建子进程的四种方法

1. exec() - 执行简单命令

exec() 方法用于执行简单的 shell 命令,并缓冲输出结果。

实例

const { exec } = require('child_process');

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

特点

  • 适合执行简单的命令
  • 返回完整的缓冲输出
  • 有最大缓冲区限制(默认 200KB)

2. execFile() - 执行可执行文件

execFile() 类似于 exec(),但直接执行文件而不是通过 shell。

实例

const { execFile } = require('child_process');

execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    throw error;
  }
  console.log(stdout);
});

特点

  • exec() 更安全(不通过 shell)
  • 执行效率更高
  • 不能使用 shell 特性(如管道、通配符等)

3. spawn() - 流式处理子进程

spawn() 方法使用流式接口处理子进程的输入输出。

实例

const { spawn } = require('child_process');

const ls = spawn('ls', ['-lh', '/usr']);

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

ls.stderr.on('data', (data) => {
  console.error(`标准错误输出: ${data}`);
});

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

特点

  • 适合处理大量输出
  • 流式处理,内存效率高
  • 可以实时处理输出

4. fork() - 创建 Node.js 子进程

fork()spawn() 的特例,专门用于创建新的 Node.js 进程。

实例

const { fork } = require('child_process');

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

child.on('message', (msg) => {
  console.log('来自子进程的消息:', msg);
});

child.send({ hello: 'world' });

特点

  • 创建新的 Node.js 实例
  • 内置 IPC(进程间通信)通道
  • 适合 CPU 密集型任务

进程间通信 (IPC)

父进程和子进程可以通过 send()message 事件进行通信。

父进程 (parent.js):

实例

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

child.on('message', (msg) => {
  console.log('父进程收到:', msg);
});

child.send({ parent: 'Hello from parent' });

子进程 (child.js):

实例

process.on('message', (msg) => {
  console.log('子进程收到:', msg);
  process.send({ child: 'Hello from child' });
});

错误处理

正确处理子进程错误非常重要:

实例

const { spawn } = require('child_process');
const child = spawn('some_command');

child.on('error', (err) => {
  console.error('启动子进程失败:', err);
});

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

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

最佳实践

  1. 安全性:避免直接将用户输入传递给子进程
  2. 资源管理:及时清理已完成的子进程
  3. 错误处理:始终处理错误事件和退出事件
  4. 性能考虑:对于频繁创建的子进程,考虑使用进程池
  5. 跨平台兼容性:注意不同操作系统的命令差异

总结

child_process 模块是 Node.js 中处理子进程的核心模块,提供了四种创建子进程的方法:

  1. exec() - 适合简单命令
  2. execFile() - 适合执行可执行文件
  3. spawn() - 适合流式处理
  4. fork() - 适合创建 Node.js 子进程

根据具体需求选择合适的方法,并注意错误处理和资源管理,可以充分发挥 Node.js 的多进程能力。

Java FileNode.js 内置模块