> For the complete documentation index, see [llms.txt](https://easonwang.gitbook.io/web_advance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://easonwang.gitbook.io/web_advance/chapter1/cluster-and-childprocess.md).

# Cluster and Child\_process

<https://nodejs.org/api/cluster.html>

因為Nodejs為單進程，所以預設只會用一個ＣＰＵ執行程式，所以我們可以用Cluster來讓他可以跑多個CPU

1.以下為讓每個cpu都跑一個process的範例(根據cpu數量)

```javascript
var cluster = require('cluster');
var os = require('os');

if (cluster.isMaster){
  for (var i = 0, n = os.cpus().length; i < n; i += 1){
    cluster.fork();
  }
} else {
  http.createServer(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
  }).listen(8000);
}
```

2.以下為讓子進程與主進程溝通的範例

```javascript
var cluster = require('cluster');
var http = require('http');
var numReqs = 0;
var workers = [];

if (cluster.isMaster) {
  // Broadcast a message to all workers
  var broadcast = function() {
    for (var i in workers) {
      var worker = workers[i];
      worker.send({ cmd: 'broadcast', numReqs: numReqs }); //send裡面可以隨便放
    }
  }

  // Fork workers.
  for (var i = 0; i < 2; i++) {
    var worker = cluster.fork();

    worker.on('message', function(msg) {
      if (msg.cmd) {
        switch (msg.cmd) {
          case 'notifyRequest':
            numReqs++;
          break;
          case 'broadcast':
            broadcast();
          break;
        }
    });

    // Add the worker to an array of known workers
    workers.push(worker);
  }

  setInterval(function() {
    console.log("numReqs =", numReqs);
  }, 1000);
} else {
  // React to messages received from master
  process.on('message', function(msg) {
    switch(msg.cmd) {
      case 'broadcast':
        if (msg.numReqs) console.log('Number of requests: ' + msg.numReqs);
      break;
    }
  });

  // Worker processes have a http server.
  http.Server(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
    // Send message to master process
    process.send({ cmd: 'notifyRequest' });
    process.send({ cmd: 'broadcast' });
  }).listen(8000);
}
```

但是

> master 進程創建 socket，綁定到某個地址以及PORT後，自身不調用 listen 來監聽連接以及 accept 連接，而是將該 socket 的 fd(file descriptor) 傳遞到 fork 出來的 worker 進程，worker 接收到 fd 後再調用 listen，accept 新的連接。但實際一個新到來的連接最終只能被某一個 worker 進程 accpet 再做處理。
>
> 所以會造成子進程產生競爭現象
>
> 可參考：<http://taobaofed.org/blog/2015/11/03/nodejs-cluster/>

## 執行shell指令

> 可以使用spawn或是exec

## Exec

```javascript
  const { exec } = require('child_process');
  exec(`
  mkdir ${location}
  cd ${location}
  openssl genrsa -out ${keyName}_private.pem
  openssl rsa -in ${keyName}_private.pem -out ${keyName}_public.pem -outform PEM -pubout
  `, (error, stdout, stderr) => {
      if (error) {
        console.error(`exec error: ${error}`);
        return;
      }
      console.log(`${stdout}`);
      console.log(`${stderr}`);
    });
```

## Spawn

> spawn會需要將參數寫成如下

```javascript
const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-lh', '/usr']);
```

如果有輸出log

```javascript
const { exec } = require('child_process');
const cmdInfo = exec(`ls -lh`);
ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.log(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://easonwang.gitbook.io/web_advance/chapter1/cluster-and-childprocess.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.
