Выполнение действий очистки непосредственно перед node.js завершает
Я хочу сказать node.js всегда делать что-то непосредственно перед тем, как оно выйдет, по любой причине - Ctrl + C, исключение или по любой другой причине.
Я пробовал это:
process.on('exit', function (){
console.log('Goodbye!');
});
Начал процесс, убил его, и ничего не произошло; снова начал, нажал Ctrl + C, и до сих пор ничего не произошло...
Ответы
Ответ 1
UPDATE:
Вы можете зарегистрировать обработчик для process.on('exit')
и в любом другом случае (SIGINT
или необработанное исключение) для вызова process.exit()
process.stdin.resume();//so the program will not close instantly
function exitHandler(options, err) {
if (options.cleanup) console.log('clean');
if (err) console.log(err.stack);
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}));
Ответ 2
Ниже приведено script, позволяющее иметь один обработчик для всех условий выхода. Для выполнения пользовательского кода очистки используется специальная функция обратного вызова приложения.
cleanup.js
// 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 и обычные события выхода. Затем он вызывает одну дополнительную функцию обратного вызова очистки пользователя перед выходом, обрабатывая все условия выхода с помощью одного объекта.
Модуль просто расширяет объект процесса, а не определяет другой эмитент событий. Без специального обратного вызова приложения очистка по умолчанию не имеет функции op. Этого было достаточно для моего использования, когда дочерние процессы оставались включенными при выходе из 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
Ответ 3
"exit" - событие, которое запускается, когда node завершает цикл событий внутри, он не запускается, когда вы завершаете процесс извне.
То, что вы ищете, выполняет что-то на 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.');
});
Примечание: это, по-видимому, прерывает сигмин, и вам нужно будет вызвать process.exit(), когда вы закончите свой код.
Ответ 4
Просто хотел упомянуть пакет 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
})
Ответ 5
io.js имеет exit
и a beforeExit
, которые делают то, что вы хотите.
Ответ 6
var fs = require('fs');
function async(callback) {
fs.writeFile('async.txt', 'bye!', callback);
}
function sync()
{
for (var i = 0; i < 10; i++) {}
return true;
}
function killProcess()
{
if (process.exitTimeoutId){
return;
}
process.exitTimeoutId = setTimeout(process.exit, 5000);
console.log('process will exit in 5 seconds');
async(function() {
console.log('async op. done', arguments);
});
if (sync()) {
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
Ответ 7
В случае, когда процесс был порожден другим процессом node, например:
var child = spawn('gulp', ['watch'], {
stdio: 'inherit',
});
И вы попытаетесь убить его позже, используя:
child.kill();
Вот как вы обрабатываете событие [у ребенка]:
process.on('SIGTERM', function() {
console.log('Goodbye!');
});