Je veux dire à node.js de toujours faire quelque chose juste avant sa sortie, pour une raison quelconque - Ctrl + C, une exception ou toute autre raison.
J'ai essayé ceci:
process.on('exit', function (){
console.log('Goodbye!');
});
Commencé le processus, tué, et rien ne s'est passé; recommencé, appuyé sur Ctrl + C, et toujours rien ne s'est passé ...
Vous pouvez enregistrer un gestionnaire pour process.on('exit')
et dans tous les autres cas (SIGINT
ou exception non gérée) pour appeler 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}));
Le script ci-dessous permet d'avoir un seul gestionnaire pour toutes les conditions de sortie. Il utilise une fonction de rappel spécifique à l'application pour exécuter un code de nettoyage personnalisé.
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);
});
};
Ce code intercepte les exceptions non interceptées, les événements Ctrl-C et les événements de sortie normaux. Il appelle ensuite une seule fonction de rappel de nettoyage utilisateur facultative avant de quitter, en gérant toutes les conditions de sortie avec un seul objet.
Le module étend simplement l'objet de processus au lieu de définir un autre émetteur d'événements. Sans un rappel spécifique à l'application, le nettoyage utilise par défaut une fonction non opérationnelle. Cela suffisait pour mon utilisation lorsque les processus enfants étaient laissés en marche lors de la sortie par Ctrl-C.
Vous pouvez facilement ajouter d'autres événements de sortie, tels que SIGHUP, à votre guise. Remarque: selon le manuel de NodeJS, SIGKILL ne peut pas avoir d’écoute. Le code de test ci-dessous illustre différentes manières d'utiliser 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" est un événement qui est déclenché lorsque le noeud termine sa boucle d'événements en interne, il n'est pas déclenché lorsque vous terminez le processus en externe.
Ce que vous cherchez, c'est exécuter quelque chose sur un SIGINT.
La documentation sur http://nodejs.org/api/process.html#process_signal_events donne un exemple:
Exemple d'écoute pour 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.');
});
Remarque: cela semble interrompre la sigint et vous auriez besoin d’appeler process.exit () lorsque vous aurez terminé avec votre code.
Cela attrape tous les événements de sortie que je peux trouver qui peuvent être gérés. Semble assez fiable et propre jusqu'à présent.
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach((eventType) => {
process.on(eventType, cleanUpServer.bind(null, eventType));
})
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
Je voulais juste mentionner le paquet death
ici: https://github.com/jprichardson/node-death
Exemple:
var ON_DEATH = require('death')({uncaughtException: true}); //this is intentionally ugly
ON_DEATH(function(signal, err) {
//clean up code here
})
io.js a une exit
et un beforeExit
événement qui fait ce que vous voulez.