fazendo uma ação de limpeza antes do node.js sair

Eu quero dizer ao node.js para sempre fazer algo antes de sair, por qualquer motivo – Ctrl + C, exceção ou qualquer outro motivo.

Eu tentei isso:

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

Começou o processo, matou e nada aconteceu; começou de novo, pressionou Ctrl + C, e ainda assim nada aconteceu …

ATUALIZAR:

Você pode registrar um manipulador para process.on('exit') e em qualquer outro caso (exceção SIGINT ou não tratada) para chamar process.exit()

 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})); 

O script abaixo permite ter um único manipulador para todas as condições de saída. Ele usa uma function de retorno de chamada específica do aplicativo para executar o código de limpeza personalizado.

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); }); }; 

Este código intercepta exceções não identificadas, Ctrl-C e events de saída normais. Em seguida, ele chama uma function de retorno de chamada opcional de limpeza de usuário opcional antes de sair, manipulando todas as condições de saída com um único object.

O módulo simplesmente estende o object de processo em vez de definir outro emissor de evento. Sem um retorno de chamada específico do aplicativo, a limpeza é padronizada para uma function no op. Isso foi suficiente para meu uso, onde os processos filhos foram deixados em execução ao sair pelo Ctrl-C.

Você pode adicionar facilmente outros events de saída, como SIGHUP, conforme desejado. Nota: de acordo com o manual do NodeJS, o SIGKILL não pode ter um ouvinte. O código de teste abaixo demonstra várias maneiras de usar 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 

“exit” é um evento que é acionado quando o nó termina seu loop de events internamente, não é acionado quando você finaliza o processo externamente.

O que você está procurando é executar algo em um SIGINT.

Os documentos em http://nodejs.org/api/process.html#process_signal_events fornecem um exemplo:

Exemplo de escuta do 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.'); }); 

Nota: isto parece interromper o sigint e você precisaria chamar process.exit () quando terminar seu código.

 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 

Só queria mencionar o pacote da death aqui: https://github.com/jprichardson/node-death

Exemplo:

 var ON_DEATH = require('death')({uncaughtException: true}); //this is intentionally ugly ON_DEATH(function(signal, err) { //clean up code here }) 

Isso captura todos os events de saída que posso encontrar e que podem ser manipulados. Parece bastante confiável e limpo até agora.

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

O io.js tem um evento exit e beforeExit , que faz o que você deseja.

No caso em que o processo foi gerado por outro processo de nó, como:

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

E você tenta matá-lo mais tarde, via:

 child.kill(); 

É assim que você lida com o evento [na criança]:

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