在node.js退出之前进行清理操作

本文翻译自:doing a cleanup action just before node.js exits

I want to tell node.js to always do something just before it exits, for whatever reason - Ctrl+C, exception, or any other reason. 我想告诉node.js无论出于什么原因-Ctrl + C,异常或任何其他原因,总是要在退出之前做一些事情。

I tried this: 我尝试了这个:

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

Started the process, killed it, and nothing happened; 开始了这个过程,杀死了它,什么也没有发生。 started again, pressed Ctrl+C, and still nothing happened... 重新启动,按Ctrl + C,仍然没有任何反应...


#1楼

参考:https://stackoom.com/question/wsIl/在node-js退出之前进行清理操作


#2楼

UPDATE: 更新:

You can register a handler for process.on('exit') and in any other case( SIGINT or unhandled exception) to call process.exit() 您可以为process.on('exit')注册一个处理程序,在任何其他情况下( SIGINT或未处理的异常)都可以调用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}));

#3楼

"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. 您正在寻找的是在SIGINT上执行某些操作。

The docs at http://nodejs.org/api/process.html#process_signal_events give an example: http://nodejs.org/api/process.html#process_signal_events上的文档给出了一个示例:

Example of listening for SIGINT: 收听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. 注意:这似乎会中断sigint,并且在完成代码后需要调用process.exit()。


#4楼

The script below allows having a single handler for all exit conditions. 下面的脚本允许所有退出条件都使用一个处理程序。 It uses an app specific callback function to perform custom cleanup code. 它使用应用程序特定的回调函数来执行自定义清理代码。

cleanup.js 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);
  });
};

This code intercepts uncaught exceptions, Ctrl-C and normal exit events. 此代码拦截未捕获的异常,Ctrl-C和常规退出事件。 It then calls a single optional user cleanup callback function before exiting, handling all exit conditions with a single object. 然后,它在退出之前调用一个可选的用户清除回调函数,用一个对象处理所有退出条件。

The module simply extends the process object instead of defining another event emitter. 该模块只是扩展了过程对象,而不是定义另一个事件发射器。 Without an app specific callback the cleanup defaults to a no op function. 如果没有应用特定的回调,则清理默认为无操作功能。 This was sufficient for my use where child processes were left running when exiting by Ctrl-C. 这对于我使用Ctrl-C退出时仍在运行子进程的情况已经足够了。

You can easily add other exit events such as SIGHUP as desired. 您可以根据需要轻松添加其他退出事件,例如SIGHUP。 Note: per NodeJS manual, SIGKILL cannot have a listener. 注意:根据NodeJS手册,SIGKILL不能具有侦听器。 The test code below demonstrates various ways of using cleanup.js 下面的测试代码演示了使用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 

#5楼

io.js具有exitbeforeExit事件,它们可以执行您想要的操作。


#6楼

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值