web-dev-qa-db-fra.com

faire une action de nettoyage juste avant la sortie de node.js

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é ...

280
Erel Segal-Halevi

MISE À JOUR:

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}));
445
Emil Condrea

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 
168
CanyonCasa

"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.

19
user1278519

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));
})
15
light24bulbs
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
8
Abdullah Aydın

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
})
5
antongorodezkiy

io.js a une exit et un beforeExit événement qui fait ce que vous voulez.

0
Golo Roden