Как оповестить дочерний процесс от вечного монитора на SIGINT в родительском процессе? - PullRequest
0 голосов
/ 10 мая 2018

Я использую forever-monitor в Windows, где дочерние процессы отключены по умолчанию.

В моем приложении у меня есть файл monitor.js, который отслеживает файл server.js, и я хочу иметь возможность уведомлять server.js, когда я закрываю свое приложение, выходя из monitor.js (нажав Ctrl + C по команде- линия).

Вот мой демонстрационный код:

monitor.js

const path = require('path');
const forever = require('forever-monitor');

let child;

function exit() {
  console.error('Received exit signal on main process.');
  if (child) {
    // TODO: Here I want to notify the "child", so that it can gracefully shutdown my server
    child.stop();
  }
  process.exit(0);
}

['SIGINT', 'SIGKILL', 'SIGTERM'].forEach(signal => process.on(signal, exit));

child = new forever.Monitor(path.join(__dirname, 'server.js'));
child.start();

server.js

const express = require('express');

const app = express();
const port = process.env.PORT || 8080;

let server;

function stopServer() {
  if (server) {
    console.log('Shutting down server...');
    server.close();
  }
}

app.get('/', (request, response) => response.send('Hello'));
server = app.listen(port, () => console.log(`Server is running on port "${port}".`));

Как мне позвонить stopServer в server.js, когда monitor.js получает SIGINT?

1 Ответ

0 голосов
/ 10 мая 2018

Секретный соус - запустить дочерний процесс с опцией «fork».

Использование опции "fork" позволяет отправлять сообщения от родительского процесса дочернему процессу, вызывая child.send. Это дает возможность прослушивать в дочернем процессе пользовательское сообщение close от родительского процесса, чтобы дочерний процесс мог остановить сервер и выйти с пользовательским кодом выхода 1337.

Когда родительский / основной процесс понимает, что дочерний процесс был закрыт с кодом 1337, тогда основной процесс также выключается.

Вот мое решение:

monitor.js

const path = require('path');
const forever = require('forever-monitor');

let child;

function exit(signal) {
  console.error(`Received "${signal}" signal on main process.`);
  if (child) {
    child.send({action: 'close'});
  }
}

['SIGINT', 'SIGKILL', 'SIGTERM'].forEach(signal => process.on(signal, () => exit(signal)));

process.on('exit', (code) => console.log(`Stopped main process with code "${code}".`));

const options = {fork: true};

child = new forever.Monitor(path.join(__dirname, 'server.js'), options);

child.on('exit:code', (code) => {
  if (code === 1337) {
    if (child) {
      child.stop();
      console.log('Successfully stopped child process.');
    }
    console.log('Stopping main process ...');
    process.exit(0);
  }
});

child.start();

server.js

const express = require('express');

const app = express();
const port = process.env.PORT || 8080;

let server;

if (process.send) {
  process.on('message', function (message) {
    console.log(`Received "${message.action}" message from main process.`);
    if (message.action === 'close') {
      stopServer();
    }
  });
}

function stopServer() {
  if (server) {
    console.log('Stopping server in child process ...');
    server.close(() => {
      console.log('Stopped server in child process.');
      process.exit(1337);
    });
  }
}

app.get('/', (request, response) => response.send('Hello'));
server = app.listen(port, () => console.log(`Server is running on port "${port}".`));
...