Doing a cleanup action just before Node.js exits

后端 未结 11 1339
时光说笑
时光说笑 2020-11-22 13:54

I want to tell Node.js to always do something just before it exits, for whatever reason — Ctrl+C, an exception, or any other reason.

I tried th

相关标签:
11条回答
  • 2020-11-22 14:03

    "exit" is an event that gets triggered when node finish it's event loop internally, it's not triggered when you terminate the process externally.

    What you're looking for is executing something on a SIGINT.

    The docs at http://nodejs.org/api/process.html#process_signal_events give an example:

    Example of listening for 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.');
    });
    

    Note: this seems to interrupt the sigint and you would need to call process.exit() when you finish with your code.

    0 讨论(0)
  • 2020-11-22 14:03

    io.js has an exit and a beforeExit event, which do what you want.

    0 讨论(0)
  • 2020-11-22 14:05
    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
    
    0 讨论(0)
  • 2020-11-22 14:09

    After playing around with other answer, here is my solution for this task. Implementing this way helps me centralize cleanup in one place, preventing double handling the cleanup.

    1. I would like to route all other exiting codes to 'exit' code.
    const others = [`SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`]
    others.forEach((eventType) => {
        process.on(eventType, exitRouter.bind(null, { exit: true }));
    })
    
    1. What the exitRouter does is calling process.exit()
    function exitRouter(options, exitCode) {
       if (exitCode || exitCode === 0) console.log(`ExitCode ${exitCode}`);
       if (options.exit) process.exit();
    }
    
    1. On 'exit', handle the clean up with a new function
    function exitHandler(exitCode) {
      console.log(`ExitCode ${exitCode}`);
      console.log('Exiting finally...')
    }
    
    process.on('exit', exitHandler)
    

    For the demo purpose, this is link to my gist. In the file, i add a setTimeout to fake the process running.

    If you run node node-exit-demo.js and do nothing, then after 2 seconds, you see the log:

    The service is finish after a while.
    ExitCode 0
    Exiting finally...
    

    Else if before the service finish, you terminate by ctrl+C, you'll see:

    ^CExitCode SIGINT
    ExitCode 0
    Exiting finally...
    

    What happened is the Node process exited initially with code SIGINT, then it routes to process.exit() and finally exited with exit code 0.

    0 讨论(0)
  • 2020-11-22 14:14

    Just wanted to mention death package here: https://github.com/jprichardson/node-death

    Example:

    var ON_DEATH = require('death')({uncaughtException: true}); //this is intentionally ugly
    
    ON_DEATH(function(signal, err) {
      //clean up code here
    })
    
    0 讨论(0)
  • 2020-11-22 14:15

    This catches every exit event I can find that can be handled. Seems quite reliable and clean so far.

    [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach((eventType) => {
      process.on(eventType, cleanUpServer.bind(null, eventType));
    })
    
    0 讨论(0)
提交回复
热议问题