Node.js 的 child_process 模块,一篇来龙去脉全解析

阅读时长 7 分钟读完

在 Node.js 中,child_process 模块被用来启动和控制子进程。Node.js 是单线程的,但是可以通过创建子进程来扩展其能力。child_process 模块提供了函数,可以在新的进程中运行 shell 命令或其他进程,并在 Node.js 主进程中控制其输入输出和生命周期。

本文将对 child_process 模块的用法进行详细解析,包括启动进程、输入输出控制、进程通信、集群和异常处理。

启动进程

child_process 模块提供了 4 个函数可以启动新的进程:

  • exec() - 启动一个 shell 并运行命令,等待它执行完毕,并返回所有的输出结果。
  • execFile() - 直接运行一个文件,而不是通过 shell 进行解释。
  • spawn() - 启动一个新的进程。与 exec() 不同,它不等待命令完成并立即返回一个 ChildProcess 对象。
  • fork() - 创建一个与当前进程相同的进程,并在新的进程中运行另一个模块(Node.js 文件)。与 spawn() 不同,它不需要指定命令和选项。

下面是一些简单的例子:

exec()

-- -------------------- ---- -------
----- - ---- - - -------------------------
-------- ----- ------- ------- ------- -- -
  -- ------- -
    -------------------- -----------
    -------
  -
  -------------------- ------------
  -------------------- ------------
---

这个例子中,我们使用 exec() 启动了一个 shell 并运行了 ls -lh 命令。当该命令执行完成时,我们会得到一个回调,并且可以查看该命令的输出结果。

spawn()

-- -------------------- ---- -------
----- - ----- - - -------------------------
----- -- - ----------- ------- ---------

-------------------- ---- -- -
  -------------------- ----------
---

-------------------- ---- -- -
  ---------------------- ----------
---

-------------- ---- -- -
  -------------------- ----------
---

这个例子中,我们启动了 ls -lh /usr 命令。我们可以监听 stdoutstderr 事件来获取输出信息,并监听 close 事件来得知子进程何时退出。

输入输出控制

子进程的输入和输出可以通过 stdin/stdout 和 stderr 句柄进行控制。下面是示例代码:

-- -------------------- ---- -------
----- - ----- - - -------------------------
----- -- - ----------- ------- ---------

--------------------- ---------
---------------

-------------------- ---- -- -
  -------------------- ----------
---

-------------------- ---- -- -
  ---------------------- ----------
---

-------------- ---- -- -
  -------------------- ----------
---

在这个例子中,我们向子进程的标准输入流(stdin)写入了字符串,并通过 end() 终止了输入流。然后,我们监听了 stdoutstderr 事件。

进程通信

子进程和主进程之间可以通过 stdin/stdout 和 stderr 句柄进行通信。下面是一个示例:

main.js:

-- -------------------- ---- -------
----- - ----- - - -------------------------
----- ----- - ------------- ------------- -
  ------ -------- ------- ---------------
---

----------------------
----------------------- ---- -- -
  ------------------- ----------
---

----------------------- ---- -- -
  --------------------- ----------
---

child.js:

在这个例子中,我们通过 spawn() 启动了一个 child.js 子进程,并在主进程中监听了其 stdoutstderr 事件。在子进程中,我们为 stdin 句柄添加了一个事件监听器,并在接收到数据后向 stdout 句柄写入了相同的数据。

集群

Node.js 可以通过 cluster 模块创建集群。cluster 模块使用 child_process 上的 fork() 方法来实现多个 Node.js 进程间的通信。以下是一个集群的例子:

-- -------------------- ---- -------
----- ------- - -------------------
----- ---- - ----------------
----- ------- - ----------------------------

-- ------------------ -
  ---------------- -------------- -------

  -- ------
  --- ---- - - -- - - -------- ---- -
    ---------------
  -

  ------------------ -------- ----- ------- -- -
    ----------------- --------------------- ------
  ---
- ---- -
  -- ---------- --- --
  -- --------- ---- ---
  ----------------------- ---- -- -
    -------------------
    ------------------
  ----------------

  ----------------- -------------- ------
-

在这个例子中,我们使用 cluster.isMaster 属性来决定进程是主进程还是工作进程。主进程负责启动工作进程,而工作进程则启动一个简单的 HTTP 服务器。从工作进程中可以使用 cluster.worker.id 属性获取其 ID。

异常处理

child_process 启动进程的时候,可能会抛出异常。这些异常可以通过 try-catch 块或者 error 事件来捕获。

下面是一个示例:

-- -------------------- ---- -------
----- - ----- - - -------------------------
----- -- - ----------- ------- --------- -- --------------

-------------- ----- -- -
  ---------------------- -----------
---

-------------------- ---- -- -
  -------------------- ----------
---

-------------------- ---- -- -
  ---------------------- ----------
---

-------------- ---- -- -
  -------------------- ----------
---

在这个例子中,我们将输入一个不存在的路径,将会抛出一个错误。通过监听 error 事件的方式,我们就可以在这种情况下执行额外的代码。

结论

child_process 模块是 Node.js 中非常重要的模块之一,可以实现很多有趣的功能,如多进程计算、集群等。在实践中需要仔细考虑子进程和主进程之间的通信,并确保正确处理异常。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67525c5f8bd460d3ad934e38

纠错
反馈