2013-01-17 86 views
14

當我的Express.js服務被SIGINT停止時,我需要做一些有用的事情。使用Express.js版本3.0.6,據我所知,這應該工作:如何正確使用Express.js處理SIGINT?

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控制 - Ç)兩次:

$ 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正確終止。

顯然有一些基本的東西我在這裏失蹤?

回答

21

通過捕獲SIGINT處理程序,您正在阻止要退出該進程的默認行爲。當第二次使用Ctrl+C時,進程將因爲server.close引發未捕獲的異常而死亡。

只需在您的SIGINT處理程序的末尾添加一個process.exit()即可正常退出此過程。

+0

使用'process.exit()'是像你這樣一兩件事,不應該正常(恕我直言)考慮後發送^ C。我認爲更完整的答案在下面(儘管有點晚)。 – Whyhankee

4

我使用這個變體:

server.close(() => { 
    process.exit(0) 
}) 
5

復活一個過時的歌曲,因爲這個問題不完全(或正確)回答人可能仍然覺得這個答案。

你的問題的重要組成部分是:

還有一個警告。如果我啓動這個Express.js服務並且不發送任何請求,那麼SIGINT正常終止。 顯然有什麼基礎,我在這裏失蹤?`

你缺少的是默認快速保持連接打開(HTTP保持活動)重用。所以,當有(最近)請求時,事件循環中仍然存在一些內容,這就是您的應用程序未關閉的原因。

使用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);

+1

由於關機前潛在的延遲很長,這可能仍然不理想,並且使保持連接的連接可能不太有用。要獲得更完整的解決方案,可以使用graceful-exit模塊:https://www.npmjs.com/package/express-graceful-exit。該模塊將關閉保持連接並等待其他活動在退出之前停止。 – nneonneo