Node.js가 종료되기 직전에 어떤 이유로 든 Ctrl+ C, 예외 또는 다른 이유로 항상 무언가를하도록 지시하고 싶습니다 .
나는 이것을 시도했다 :
process.on('exit', function (){
console.log('Goodbye!');
});
나는 그 과정을 시작하고 그것을 죽였고 아무 일도 일어나지 않았다. 나는 그것을 다시 시작하고 Ctrl+를 눌렀 C지만 여전히 아무 일도 일어나지 않았다 ...
Node.js가 종료되기 직전에 어떤 이유로 든 Ctrl+ C, 예외 또는 다른 이유로 항상 무언가를하도록 지시하고 싶습니다 .
나는 이것을 시도했다 :
process.on('exit', function (){
console.log('Goodbye!');
});
나는 그 과정을 시작하고 그것을 죽였고 아무 일도 일어나지 않았다. 나는 그것을 다시 시작하고 Ctrl+를 눌렀 C지만 여전히 아무 일도 일어나지 않았다 ...
답변:
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}));
must only수행 합니다.synchronousexit
beforeExit대신 이벤트 를 사용해야한다고 생각합니다 .
stderr여러 정리 처리기 에서 단일 메시지를 조정하지 않습니다 . 필자는 아래의 cleanup.js 솔루션을 기반으로 github.com/jtlapp/node-cleanup 모듈을 작성 했지만 피드백을 기반으로 크게 수정했습니다. 도움이 되길 바랍니다.
아래 스크립트는 모든 종료 조건에 대해 단일 핸들러를 갖도록 허용합니다. 앱별 콜백 함수를 사용하여 사용자 지정 정리 코드를 수행합니다.
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);
});
};
이 코드는 포착되지 않은 예외, Ctrl+ C및 일반 종료 이벤트를 인터셉트 합니다. 그런 다음 종료하기 전에 단일 선택적 사용자 정리 콜백 함수를 호출하여 단일 오브젝트로 모든 종료 조건을 처리합니다.
모듈은 단순히 다른 이벤트 이미 터를 정의하는 대신 프로세스 오브젝트를 확장합니다. 앱별 콜백이 없으면 정리는 기본적으로 op 기능이 없습니다. 이것은 Ctrl+로 종료 할 때 자식 프로세스가 실행 된 상태에서 사용하기에 충분했습니다 C.
SIGHUP과 같은 다른 종료 이벤트를 원하는대로 쉽게 추가 할 수 있습니다. 참고 : NodeJS 매뉴얼에 따라 SIGKILL은 리스너를 가질 수 없습니다. 아래 테스트 코드는 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
process.exit(). 정리 핸들러는 이제 종료 코드 또는 신호의 기능으로 작동 할 수있는 유연성을 가지며 비동기 정리를 지원하거나 주기적 정리를 방지하기 위해 필요에 따라 정리 핸들러를 설치 제거 할 수 있습니다. 이제 위 코드와 거의 유사하지 않습니다.
이것은 처리 할 수있는 모든 종료 이벤트를 포착합니다. 지금까지는 매우 신뢰할 수 있고 깨끗해 보입니다.
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach((eventType) => {
process.on(eventType, cleanUpServer.bind(null, eventType));
})
"종료"는 노드가 이벤트 루프를 내부적으로 완료 할 때 트리거되는 이벤트이며, 외부에서 프로세스를 종료 할 때 트리거되지 않습니다.
당신이 찾고있는 것은 SIGINT에서 무언가를 실행하는 것입니다.
http://nodejs.org/api/process.html#process_signal_events 의 문서 는 예제를 제공합니다.
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.');
});
참고 : 이것은 sigint를 방해하는 것으로 보이므로 코드를 완료하면 process.exit ()를 호출해야합니다.
kill -2가 전달됩니다 SIGINT. 우리는 txt 파일에 노드 로깅을 가지고 있으므로 Ctrl + C를 사용할 수 없으므로이 방법을 사용해야합니다.
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
https://github.com/jprichardson/node-deathdeath 패키지 를 언급하고 싶었 습니다.
예:
var ON_DEATH = require('death')({uncaughtException: true}); //this is intentionally ugly
ON_DEATH(function(signal, err) {
//clean up code here
})
io.js 에는 원하는 이벤트 exit와 beforeExit이벤트가 있습니다.
다른 답변을 가지고 놀고 나면이 작업에 대한 나의 해결책이 있습니다. 이 방법을 구현하면 정리를 한 곳에서 중앙 집중화하여 정리를 두 번 처리 할 수 없습니다.
const others = [`SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`]
others.forEach((eventType) => {
process.on(eventType, exitRouter.bind(null, { exit: true }));
})
function exitRouter(options, exitCode) {
if (exitCode || exitCode === 0) console.log(`ExitCode ${exitCode}`);
if (options.exit) process.exit();
}
function exitHandler(exitCode) {
console.log(`ExitCode ${exitCode}`);
console.log('Exiting finally...')
}
process.on('exit', exitHandler)
데모 목적으로, 이것은 내 요지에 대한 링크 입니다. 파일에서 setTimeout을 추가하여 실행중인 프로세스를 가짜로 만듭니다.
실행 node node-exit-demo.js하고 아무 것도 수행하지 않으면 2 초 후에 로그가 표시됩니다.
The service is finish after a while.
ExitCode 0
Exiting finally...
서비스가 끝나기 전에로 종료 ctrl+C되면 다음과 같이 표시됩니다.
^CExitCode SIGINT
ExitCode 0
Exiting finally...
발생한 일은 Node 프로세스가 코드 SIGINT로 초기에 종료 된 다음 process.exit ()로 라우팅되고 마지막으로 종료 코드 0으로 종료됩니다.