我想告诉Node.js总是在它退出之前做一些事情,无论出于什么原因- Ctrl+C,一个异常,或任何其他原因。

我试了一下:

process.on('exit', function (){
    console.log('Goodbye!');
});

我启动了这个程序,扼杀了它,然后什么都没发生。我再次启动,按下Ctrl+C,仍然什么都没有发生……


当前回答

io.js有一个exit和一个beforeExit事件,它们做你想做的事情。

其他回答

io.js有一个exit和一个beforeExit事件,它们做你想做的事情。

在进程由另一个节点进程生成的情况下,例如:

var child = spawn('gulp', ['watch'], {
    stdio: 'inherit',
});

然后你试图通过以下方式杀死它:

child.kill();

这是如何处理[子]事件的:

process.on('SIGTERM', function() {
    console.log('Goodbye!');
});
function fnAsyncTest(callback) {
    require('fs').writeFile('async.txt', 'bye!', callback);
}

function fnSyncTest() {
    for (var i = 0; i < 10; i++) {}
}

function killProcess() {

    if (process.exitTimeoutId) {
        return;
    }

    process.exitTimeoutId = setTimeout(() => process.exit, 5000);
    console.log('process will exit in 5 seconds');

    fnAsyncTest(function() {
        console.log('async op. done', arguments);
    });

    if (!fnSyncTest()) {
        console.log('sync op. done');
    }
}

// https://nodejs.org/api/process.html#process_signal_events
process.on('SIGTERM', killProcess);
process.on('SIGINT', killProcess);

process.on('uncaughtException', function(e) {

    console.log('[uncaughtException] app will be terminated: ', e.stack);

    killProcess();
    /**
     * @https://nodejs.org/api/process.html#process_event_uncaughtexception
     *  
     * 'uncaughtException' should be used to perform synchronous cleanup before shutting down the process. 
     * It is not safe to resume normal operation after 'uncaughtException'. 
     * If you do use it, restart your application after every unhandled exception!
     * 
     * You have been warned.
     */
});

console.log('App is running...');
console.log('Try to press CTRL+C or SIGNAL the process with PID: ', process.pid);

process.stdin.resume();
// just for testing

"exit"是一个在节点内部完成它的事件循环时触发的事件,当你在外部终止进程时不会触发。

你要做的是在SIGINT上执行一些东西。

http://nodejs.org/api/process.html#process_signal_events上的文档给出了一个例子:

监听SIGINT的例子:

// Start reading from stdin so we don't exit.
process.stdin.resume();

process.on('SIGINT', function () {
  console.log('Got SIGINT.  Press Control-D to exit.');
});

注意:这似乎会中断sigint,当你完成代码时,你需要调用process.exit()。

这将捕获我能找到的可以处理的每个退出事件。目前看来很可靠,也很干净。

[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach((eventType) => {
  process.on(eventType, cleanUpServer.bind(null, eventType));
})