如何正确使用Express.js处理SIGINT?
当我的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(); });
但是这个过程不会让我回到Bash提示符,除非我发出SIGINT
( Control – C )两次:
$ 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
正常终止。
显然,我在这里错过了一些基本的东西?
通过捕获SIGINT
处理程序,您正在阻止默认行为 ,即退出该进程。 当您第二次使用Ctrl+C
时,该进程死亡,因为server.close
抛出一个未捕获的exception。
只要将一个process.exit()
添加到SIGINT
处理程序的结尾即可正常退出该进程。
我正在使用这个变种:
server.close(() => { process.exit(0) })
由于这个问题并没有完全(或正确)回答,所以人们可能仍然会find这个答案。
你的问题的重要部分是:
还有一个警告。 如果我启动这个Express.js服务并且不发送任何请求,那么SIGINT正常终止。 显然,我在这里失去了一些基本的东西?
你缺less的是默认的快速保持连接打开(HTTP保持活动)重用。 所以,当有一个(最近的)请求时,事件循环中还有一些东西,这就是你的应用程序没有closures的原因。
使用process.exit()
可以工作,但是就像发送另一个^ C一样,并且可能会隐藏还有其他东西被打开的事实(例如数据库连接)。 当事件循环中没有任何东西时,您的应用程序应该closures。
所以,我修改了你的例子,在连接上设置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);