26

当我的Express.js服务停止时,我需要做一些有用的事情SIGINT。使用 Express.js 版本 3.0.6,我知道这应该可以工作:

var express = require('express');

var app = express();
var server = app.listen(3000);

process.on('SIGINT', function() {
  console.log('Do something useful here.');
  server.close();
});

SIGINT但是,除非我发出( Control- C) 两次,否则该过程不会给我返回 Bash 提示:

$ node problem.js 
^CDo something useful here.
^CDo something useful here.

net.js:1046
    throw new Error('Not running');
          ^
Error: Not running
    at Server.close (net.js:1046:11)
    at process.<anonymous> (/path/to/problem.js:8:10)
    at process.EventEmitter.emit (events.js:93:17)
    at SignalWatcher.startup.processSignalHandlers.process.on.process.addListener.w.callback (node.js:486:45)
$

还有一个警告。如果我启动此 Express.js 服务并且不发送任何请求,则SIGINT正确终止。

显然,我在这里缺少一些基本的东西?

4

3 回答 3

35

通过捕获SIGINT处理程序,您可以防止默认行为,即退出进程。当您Ctrl+C第二次使用时,进程会因为server.close抛出未捕获的异常而终止。

process.exit()只需在处理程序的末尾添加 a即可SIGINT优雅地退出该过程。

于 2013-01-17T04:47:10.423 回答
12

复活一个老歌,因为这个问题没有完全(或正确)回答,人们可能仍然会找到这个答案。

您问题的重要部分是:

还有一个警告。如果我启动这个 Express.js 服务并且不发送任何请求,那么 SIGINT 会正确终止。显然,我在这里缺少一些基本的东西?

您缺少的是默认情况下 express 保持连接打开(HTTP keep-alive)以供重用。所以,当有一个(最近的)请求时,事件循环中仍然有一些东西,这就是你的应用程序没有关闭的原因。

使用process.exit()会起作用,但就像发送另一个^C,并且可能隐藏仍然有其他东西打开(例如数据库连接)的事实。当事件循环中没有任何内容时,您的应用程序应该关闭。

因此,我修改了您的示例,在连接上设置了 5 秒保持活动状态,以便在合理的时间内正常关闭。

var express = require('express');

var serverPort = 3000;
var app = express();
var server = app.listen(serverPort);


// HTTP Keep-Alive to a short time to allow graceful shutdown
server.on('connection', function (socket) {
  socket.setTimeout(5 * 1000);
});

// Handle ^C
process.on('SIGINT', shutdown);

// Do graceful shutdown
function shutdown() {
  console.log('graceful shutdown express');
  server.close(function () {
    console.log('closed express');
  });
}

console.log('running server: http://localhost:' + serverPort);

于 2017-06-28T05:18:11.240 回答
8

我正在使用这段代码:

server.close(() => {
  process.exit(0)
})
于 2017-04-26T14:19:40.910 回答