我希望告诉Node.js在退出之前始终执行某些操作-无论是 Ctrl + C ,异常还是其他任何原因。
我尝试过这样做:
process.on('exit', function (){
console.log('Goodbye!');
});
我开始了这个过程,然后停止了它,但是没有任何反应。我又开始了它,按下了Ctrl+C,但仍然没有任何反应...
我希望告诉Node.js在退出之前始终执行某些操作-无论是 Ctrl + C ,异常还是其他任何原因。
我尝试过这样做:
process.on('exit', function (){
console.log('Goodbye!');
});
我开始了这个过程,然后停止了它,但是没有任何反应。我又开始了它,按下了Ctrl+C,但仍然没有任何反应...
process.stdin.resume(); // so the program will not close instantly
function exitHandler(options, exitCode) {
if (options.cleanup) console.log('clean');
if (exitCode || exitCode === 0) console.log(exitCode);
if (options.exit) process.exit();
}
// do something when app is closing
process.on('exit', exitHandler.bind(null,{cleanup:true}));
// catches ctrl+c event
process.on('SIGINT', exitHandler.bind(null, {exit:true}));
// catches "kill pid" (for example: nodemon restart)
process.on('SIGUSR1', exitHandler.bind(null, {exit:true}));
process.on('SIGUSR2', exitHandler.bind(null, {exit:true}));
// catches uncaught exceptions
process.on('uncaughtException', exitHandler.bind(null, {exit:true}));
必须只执行
同步操作。 - Lewisstderr
消息。我编写了一个模块,https://github.com/jtlapp/node-cleanup,可以解决所有这些问题,最初基于下面的cleanup.js解决方案,但根据反馈进行了大量修订。希望它能对您有所帮助。 - Joe Lappon("exit", ...)
处理程序中,不能调用process.exit
。该处理程序应在process.exit
调用后调用。https://nodejs.org/api/process.html#process_event_exit 否则后果将非常严重,例如,所有错误都将被消音。 - Ivan Kleshnin// Object to capture process exits and call app specific cleanup function
function noOp() {};
exports.Cleanup = function Cleanup(callback) {
// attach user callback to the process event emitter
// if no callback, it will still exit gracefully on Ctrl-C
callback = callback || noOp;
process.on('cleanup',callback);
// do app specific cleaning before exiting
process.on('exit', function () {
process.emit('cleanup');
});
// catch ctrl+c event and exit normally
process.on('SIGINT', function () {
console.log('Ctrl-C...');
process.exit(2);
});
//catch uncaught exceptions, trace, then exit normally
process.on('uncaughtException', function(e) {
console.log('Uncaught Exception...');
console.log(e.stack);
process.exit(99);
});
};
这段代码截取未捕获的异常、Ctrl+C和正常退出事件。然后在退出前调用一个可选的用户清理回调函数,在一个对象中处理所有退出条件。
该模块只是扩展了进程对象,而不是定义另一个事件发射器。如果没有特定于应用程序的回调,则清除默认为无操作函数。在我使用Ctrl+C退出时,父进程仍在运行时,这已经足够了。
您可以根据需要轻松添加其他退出事件,如SIGHUP。注意:根据NodeJS手册,SIGKILL无法有监听器。下面的测试代码演示了使用cleanup.js的各种方式。
// test cleanup.js on version 0.10.21
// loads module and registers app specific cleanup callback...
var cleanup = require('./cleanup').Cleanup(myCleanup);
//var cleanup = require('./cleanup').Cleanup(); // will call noOp
// defines app specific callback...
function myCleanup() {
console.log('App specific cleanup code...');
};
// All of the following code is only needed for test demo
// Prevents the program from closing instantly
process.stdin.resume();
// Emits an uncaught exception when called because module does not exist
function error() {
console.log('error');
var x = require('');
};
// Try each of the following one at a time:
// Uncomment the next line to test exiting on an uncaught exception
//setTimeout(error,2000);
// Uncomment the next line to test exiting normally
//setTimeout(function(){process.exit(3)}, 2000);
// Type Ctrl-C to test forced exit
process.exit()
。清理处理程序现在具有依据退出码或信号行为的灵活性,并且可以根据需要卸载清理处理程序,以支持异步清理或防止循环清理。现在它与上面的代码几乎没有相似之处。 - Joe Lappprocess.emit('cleanup');
。Node.js文档中指出:"监听器函数只能执行同步操作。在调用'exit'事件监听器后,Node.js进程将立即退出,导致事件循环中仍排队的任何其他工作都将被放弃"。 - aromero我找到了可以处理的每个退出事件。目前看来相当可靠和干净。
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach((eventType) => {
process.on(eventType, cleanUpServer.bind(null, eventType));
})
man kill
。 - oligofrenprocess.exit()
。原因是,您的函数将覆盖默认行为,例如杀死端口(请参阅Node文档:https://nodejs.org/api/process.html#process_signal_events)。 - Liran H"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.');
});
kill -2
将传递SIGINT
代码。我们必须以这种方式执行此操作,因为我们将节点记录到txt文件中,因此无法使用Ctrl + C。 - Austfunction 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
async-exit-hook 看起来是处理这个问题最新的解决方案。它是 exit-hook 的一个分支/重写版本,在退出之前支持异步代码。
我想提一下这里的death
包:https://github.com/jprichardson/node-death
示例:
var ON_DEATH = require('death')({uncaughtException: true}); //this is intentionally ugly
ON_DEATH(function(signal, err) {
//clean up code here
})
我需要在退出时执行异步清理操作,但是这个问题中的所有答案都对我没用。
所以我自己尝试了一下,最终找到了这个:
process.once('uncaughtException', async () => {
await cleanup()
process.exit(0)
})
process.once('SIGINT', () => { throw new Error() })
在尝试其他答案后,这是我对此任务的解决方案。以这种方式实现可以帮助我将清理集中在一个地方,防止重复处理清理。
const others = [`SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`]
others.forEach((eventType) => {
process.on(eventType, exitRouter.bind(null, { exit: true }));
})
function exitRouter(options, exitCode) {
if (exitCode || exitCode === 0) console.log(`ExitCode ${exitCode}`);
if (options.exit) process.exit();
}
function exitHandler(exitCode) {
console.log(`ExitCode ${exitCode}`);
console.log('Exiting finally...')
}
process.on('exit', exitHandler)
node node-exit-demo.js
并且什么都不做,那么2秒后,你会看到日志:The service is finish after a while.
ExitCode 0
Exiting finally...
ctrl+C
,你会看到:^CExitCode SIGINT
ExitCode 0
Exiting finally...
"start": "npm run add-hosts-to-hosts-file && npm run start ; npm run clear-hosts-from-hosts file",
这涵盖了 Ctrl + C 的情况,也可能包括其他情况。