# Node子进程

tags: Nodejs Created time: July 21, 2022 8:10 PM emoji: <https://nodejs.org/static/images/favicons/favicon.png>

Nodejs有四种方式创建子进程

* `spawn`
* `exec`
* `fork`
* `execFile`

## spawn

spawn使用示例

```jsx
const childProcess = require("child_process")

var spawn = childProcess.spawn('ipconfig')
var spawn = childProcess.spawn('ipconfig'， [a])  // 参数
var spawn = childProcess.spawn('ipconfig'， [a]， {})  // 配置
```

spawn的第二个参数是一个数组，用于传递子进程命令参数。

第三个参数是一个配置对象，里面比较常用的属性有：

* cwd： 子进程当前工作目录
* shell： 是否在shell中执行命令，默认是false

**如果启用了 `shell` 选项，请不要将未经清理的用户输入传递给此函数。任何包含 shell 字符的输入都可用于触发任意命令执行。**

spawn函数的返回值有三个流，由这三个流来获取子进程的输入输出和异常

* stdout
* stdin
* stderr

```jsx
spawn.stdout.pipe(process.stdout)
spawn.stderr.pipe(process.stdout)
spawn.stdin.pipe(process.stdin)
// 也可以使用事件
spawn.stdout.on('data'(data)=>{
	console.log(data)
})
```

## exec

exec的执行方式和spawn不同

```jsx
const exec = childProcess.exec("node a.js a",(err,stdout,stderr)=>{
    console.log(stdout);
})
// 可以接收一个配置对象
const exec = childProcess.exec("node a.js a",{
    "cwd": "./"
},(err,stdout,stderr)=>{
    console.log(stdout);
})
```

区别有

* **默认开启shell**
* 参数写在code(第一个参数)里，用空格分隔
* 输入输出流在回调中

> **切勿将未经清理的用户输入传递给此函数。任何包含 shell 元字符的输入都可用于触发任意命令执行。**

exec的回调第一个参数是异常对象，第二个是输出流，第三个是异常流。

exec可以接收一个配置对象，常用的属性有：

* encoding ：默认'utf8’
* shell： 默认开启
* cwd： 当前工作目录

## execFile

该函数类似于`[child_process.exec（）](https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback)`只是默认情况下它不会生成 shell。相反，指定的可执行文件直接作为新进程生成，使其比`[child_process.exec（）](https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback)`稍微高效一些。

execFile可以执行可执行文件，第一个参数传入要运行的可执行文件的名称或路径。

```jsx
childProcess.execFile("node ./a.js",{
    shell: true
},(err,stdout,stderr)=>{
    if(err){ 
        console.error(err);
        return err;
    }

    console.log(stdout);
})
```

## fork

该方法是`[child_process.spawn（）](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options)`的特殊情况，专门用于生成新的Node.js进程。与`[child_process.spawn（）](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options)` 一样，返回一个 `[ChildProcess](https://nodejs.org/api/child_process.html#class-childprocess)`对象。**返回的`[子进程](https://nodejs.org/api/child_process.html#class-childprocess)`将具有一个内置的附加通信通道，该通道允许在父级和子级之间来回传递消息。**

请记住，生成的 Node.js子进程独立于父进程，但在两者之间建立的 IPC 通信通道除外。每个进程都有自己的内存，有自己的 V8 实例。由于需要额外的资源分配，因此不建议生成大量子Nodejs进程。

```jsx
if (process.argv[2] === "child") {
  setTimeout(() => {
    console.log(`Hello from ${process.argv[2]}!`);
  }, 1_000);
  process.send('hello 123')
} else {
  const { fork } = require("node:child_process");
  const controller = new AbortController();
  const { signal } = controller;
  const child = fork(__filename, ["child"], { signal });
  child.on("message", (data) => { 
    console.log("收到的消息：" + data);
  });
	//   controller.abort(); // 停止子进程
}
```

fork生成的子进程与父进程之间会建立好一条通信通道，可以通过`process.send`发送信息，另一方通过监听`message`事件获取。

## 如何停止子进程

上诉的几种创建子进程的方式的配置对象中都有一个`signal` 属性，用于接收一个Abort控制器，可以这种方式停止子进程。

```jsx
const { fork } = require("node:child_process");
const controller = new AbortController();
const { signal } = controller;
const child = fork(__filename, ["child"], { signal });
child.on("message", (data) => { 
  console.log("收到的消息：" + data);
});
controller.abort(); // 停止子进程
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://1425816423.gitbook.io/my-knowledge-base/fu-wu-qi-duan/nodejs/node-zi-jin-cheng.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
