নোড.জেএস প্রস্থান করার ঠিক আগে ক্লিনআপ ক্রিয়া করা


326

আমি নোড.জেএসকে বলতে চাই যে কোনও কারণেই এটি বেরোনোর ​​আগে সর্বদা কিছু করতে - Ctrl+ C, একটি ব্যতিক্রম বা অন্য কোনও কারণে।

আমি এটি চেষ্টা করেছি:

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

আমি প্রক্রিয়াটি শুরু করেছিলাম, হত্যা করেছি এবং কিছুই ঘটেনি। আমি আবার শুরু চাপা Ctrl+ + C, এবং এখনও কিছুই ঘটেনি ...


উত্তর:


511

হালনাগাদ:

আপনি কল করার জন্য 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}));

4
একই জায়গায় Ctrl + C এবং স্বাভাবিক প্রস্থান উভয়কেই পরিচালনা করার কোনও উপায় আছে বা আমাকে দুটি পৃথক হ্যান্ডলার লিখতে হবে? অন্যান্য প্রস্থান থেকে বেরিয়ে আসা, যেমন আনহানডেল ব্যতিক্রম সম্পর্কে কী হবে - সে ক্ষেত্রে একটি নির্দিষ্ট হ্যান্ডলার রয়েছে, তবে আমি কি একই হ্যান্ডলারের তৃতীয় অনুলিপি সহ এটি পরিচালনা করব?
এরেল সেগাল-হালেভি

1
@ রবফক্স পুনঃসূচনা () পঠন প্রক্রিয়া আরম্ভ করে। স্টিডিন ডিফল্টরূপে বিরতি দেওয়া হয়। আপনি আরও পড়তে পারেন: github.com/joyent/node/blob/…
এমিল কনড্রিয়া

65
মনে রাখবেন আপনি must onlyসঞ্চালন synchronousঅপারেশন exitহ্যান্ডলার
লুইস

2
@ কেসেমড্যাভিড আমার মনে হয় এর beforeExitপরিবর্তে আপনার ইভেন্টটি ব্যবহার করা উচিত ।
লুইস

22
এই সমাধানে অসংখ্য সমস্যা রয়েছে। (1) এটি পিতামাতার প্রক্রিয়াগুলিতে সংকেতগুলির প্রতিবেদন করে না। (২) এটি প্রস্থান প্রক্রিয়াতে প্রস্থান কোডটি পৌঁছে দেয় না। (3) এটি ইমাস-এর মতো বাচ্চাদের জন্য অনুমতি দেয় না যা Ctrl-C সাইন ইন করে। (4) এটি অ্যাসিঙ্ক্রোনাস পরিষ্কারের অনুমতি দেয় না। (5) এটি stderrএকাধিক ক্লিনআপ হ্যান্ডলারের জুড়ে একটি বার্তা সমন্বয় করে না । আমি একটি মডিউল লিখেছি যা এই সমস্তগুলি করে , github.com/jtlapp/node-cleanup , মূলত নীচে ক্লিনআপ.জেএস সমাধানের উপর ভিত্তি করে, তবে প্রতিক্রিয়ার ভিত্তিতে ব্যাপকভাবে সংশোধিত। আমি আশা করি এটি সহায়ক হিসাবে প্রমাণিত হয়েছে।
জো ল্যাপ

180

নীচের স্ক্রিপ্টটি সমস্ত প্রস্থান পরিস্থিতিগুলির জন্য একক হ্যান্ডলার রাখার অনুমতি দেয়। এটি কাস্টম ক্লিনআপ কোড সম্পাদন করতে একটি অ্যাপ নির্দিষ্ট কলব্যাক ফাংশন ব্যবহার করে।

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এবং সাধারণ প্রস্থান ইভেন্টগুলিকে বাধা দেয়। এটি প্রস্থান করার আগে একটি একক alচ্ছিক ব্যবহারকারী ক্লিনআপ কলব্যাক ফাংশন কল করে, একটি একক অবজেক্টের সাথে সমস্ত প্রস্থান শর্তাদি পরিচালনা করে।

মডিউলটি কেবল অন্য ইভেন্ট এমমিটারটি সংজ্ঞায়নের পরিবর্তে প্রক্রিয়া অবজেক্টটিকে প্রসারিত করে। কোনও অ্যাপ্লিকেশন নির্দিষ্ট কলব্যাক ব্যতীত ক্লিনআপ কোনও অপ ফাংশনে ডিফল্ট হয়। এটি আমার ব্যবহারের জন্য পর্যাপ্ত ছিল যেখানে Ctrl+ প্রস্থান করার সময় শিশু প্রক্রিয়াগুলি চলমান ছিল C

আপনি সহজেই অন্যান্য প্রস্থান ইভেন্টগুলি যেমন পছন্দ হিসাবে SIGHUP যুক্ত করতে পারেন। দ্রষ্টব্য: নোডজেএস ম্যানুয়াল অনুসারে, সিক্কিলের শ্রোতা থাকতে পারে না। নীচের পরীক্ষার কোডটি 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 

@ পিয়র-লাকজেন্ড্রিও এই নির্দিষ্ট কোডটি কোথায় যায়?
hownowbrownCO

11
আমি এই কোডটি অনিবার্যভাবে খুঁজে পেয়েছি এবং এটির জন্য একটি নোড প্যাকেজ তৈরি করেছি, পরিবর্তনগুলি সহ, আপনাকে এবং এই উত্তরের জমা দিয়ে। আশা করি এটি ঠিক আছে, @ ক্যানিয়নকাসা। ধন্যবাদ! npmjs.com/package/node-cleanup
জো ল্যাপ

3
আমি পরিষ্কার পরিষ্কার। তবে আমি প্রক্রিয়াটি পছন্দ করি না ex এক্সিট (0); cons.org/cracauer/sigint.html আমার অনুভূতি হ'ল আপনার কার্নেলটি ধ্বংসটিকে পরিচালনা করতে দেওয়া উচিত। আপনি যেভাবে সাইন ইন করেন সেভাবে আপনি প্রস্থান করছেন না। সাইন ইন 2 দিয়ে প্রস্থান করে না আপনি ত্রুটি কোড সহ সাইনটি ভুল করছেন। তারা এক নয়। প্রকৃতপক্ষে Ctrl + C 130 এর সাথে বিদ্যমান 130 2 নয়। Tldp.org/LDP/abs/html/exitcodes.html
বানজোক্যাট

5
আমি @ এনজেজেজেএস / প্যাকেজ / নোড- ক্ল্যানআপ পুনরায় লিখেছি যাতে @ বাঞ্জোকটের লিঙ্ক অনুসারে, SIGINT হ্যান্ডলিং অন্যান্য প্রক্রিয়াগুলির সাথে ভাল কাজ করে। এটি এখন কল করার পরিবর্তে প্যারেন্ট প্রসেসের সাথে সঠিকভাবে সংকেত যুক্ত করে process.exit()। ক্লিনআপ হ্যান্ডলারের এখন প্রস্থান কোড বা সিগন্যালের ফাংশন হিসাবে আচরণ করার নমনীয়তা রয়েছে এবং অ্যাসিঙ্ক্রোনাস ক্লিনআপ সমর্থন করতে বা চক্রীয় ক্লিনআপ প্রতিরোধ করার জন্য প্রয়োজনীয় হিসাবে ক্লিনআপ হ্যান্ডলারগুলি আনইনস্টল করা যায়। উপরের কোডের সাথে এখন সামান্য মিল রয়েছে।
জো ল্যাপ

3
উল্লেখ করতে ভুলে গেছি যে আমি একটি (আশাবাদী) বিস্তৃত পরীক্ষার স্যুটও তৈরি করেছি।
জো ল্যাপ

29

এটি হ'ল যে প্রতিটি প্রস্থান ইভেন্ট আমি খুঁজে পেতে পারি তা ধরা দেয়। এখন পর্যন্ত বেশ নির্ভরযোগ্য এবং পরিষ্কার বলে মনে হচ্ছে।

[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach((eventType) => {
  process.on(eventType, cleanUpServer.bind(null, eventType));
})

এটা সত্যিই দারুন!
Andranik Hovesyan

দুর্দান্ত কাজ, আমি এখনই এটি উত্পাদন ব্যবহার করছি! একটি গুচ্ছ ধন্যবাদ!
রেন্ডি

20

"প্রস্থান" হ'ল এমন একটি ইভেন্ট যা নোড এটির অভ্যন্তরীণভাবে লুপটি শেষ করার পরে ট্রিগার হয়, আপনি বাহ্যিকভাবে প্রক্রিয়াটি শেষ করার পরে এটি ট্রিগার হয় না।

আপনি যা সন্ধান করছেন তা সাইন ইন কিছু কার্যকর করা হচ্ছে something

Http://nodejs.org/api/process.html#process_signal_events এ থাকা দস্তাবেজগুলি একটি উদাহরণ দেয়:

স্বাক্ষরের জন্য শোনার উদাহরণ:

// 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.');
});

দ্রষ্টব্য: এটি সিগিন্টটিকে বাধাগ্রস্থ করছে বলে মনে হচ্ছে এবং আপনি যখন আপনার কোডটি শেষ করবেন তখন আপনাকে প্রসেস.এক্সিট () কল করতে হবে।


1
একই জায়গায় Ctrl + C এবং স্বাভাবিক প্রস্থান উভয়কেই পরিচালনা করার কোনও উপায় আছে? নাকি আমাকে দুটি অভিন্ন হ্যান্ডলার লিখতে হবে?
এরেল সেগাল-হালেভি

ঠিক যেমন একটি নোট, যদি আপনাকে একটি কিল কমান্ডের মাধ্যমে নোডটি শেষ করতে হয় kill -2তবে SIGINTকোডটি পাস করবে । আমাদের এটি এইভাবে করতে হবে কারণ আমাদের কাছে একটি টিএসটি ফাইলে নোড লগিং রয়েছে তাই Ctrl + C সম্ভব নয়।
অস্ট

9
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

4
এই উত্তরটি সমস্ত গৌরবের দাবিদার, তবে কোনও ব্যাখ্যা না থাকায় দুর্ভাগ্যক্রমে কোনও আপ-ভোট নেই। এই উত্তরটির বিষয়ে কী তাৎপর্যপূর্ণ তা হ'ল ডকটি বলেছেন , "শ্রোতার ফাংশনগুলি কেবল সিঙ্ক্রোনাস অপারেশনগুলি করতে হবে। নোট.জেএস প্রক্রিয়াটি 'প্রস্থান' ইভেন্ট শ্রোতাদের কল করার পরে অবিলম্বে প্রস্থান করবে ইভেন্ট ইভেন্ট লুপটিতে থাকা কোনও অতিরিক্ত কাজ এখনও ত্যাগ করা হবে। " , এবং এই উত্তরটি সেই সীমাবদ্ধতা কাটিয়ে উঠেছে!
xpt

7

এখানে কেবল deathপ্যাকেজটি উল্লেখ করতে চেয়েছিলেন : https://github.com/jprichardson/node-death

উদাহরণ:

var ON_DEATH = require('death')({uncaughtException: true}); //this is intentionally ugly

ON_DEATH(function(signal, err) {
  //clean up code here
})

মনে হচ্ছে আপনাকে কলব্যাকের মধ্যেই প্রসেস.এক্সিট () সহ স্পষ্টভাবে প্রোগ্রামটি থেকে বেরিয়ে আসতে হবে। এটি আমাকে ছিটকে গেল।
নিক ম্যানিং



0

অন্যান্য উত্তরের সাথে চারপাশে খেলার পরে, এই কাজের জন্য আমার সমাধান এখানে। এইভাবে প্রয়োগ করা আমাকে ক্লিনআপটিকে এক জায়গায় কেন্দ্রীভূত করতে সহায়তা করে, পরিষ্কারটিকে ডাবল হ্যান্ডলিং প্রতিরোধ করে।

  1. আমি অন্যান্য প্রস্থানকৃত কোডগুলি 'প্রস্থান' কোডে রুট করতে চাই।
const others = [`SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`]
others.forEach((eventType) => {
    process.on(eventType, exitRouter.bind(null, { exit: true }));
})
  1. প্রস্থানটি রাউটার যা করে তা হ'ল কলিং প্রসেস.এক্সিট ()
function exitRouter(options, exitCode) {
   if (exitCode || exitCode === 0) console.log(`ExitCode ${exitCode}`);
   if (options.exit) process.exit();
}
  1. 'প্রস্থান' এ, একটি নতুন ফাংশন সহ ক্লিন আপ পরিচালনা করুন
function exitHandler(exitCode) {
  console.log(`ExitCode ${exitCode}`);
  console.log('Exiting finally...')
}

process.on('exit', exitHandler)

ডেমো উদ্দেশ্যে, এটি আমার সংক্ষেপে লিঙ্ক । ফাইলটিতে, আমি প্রক্রিয়া চলমান জাল করতে একটি সেটটাইমআউট যুক্ত করি।

আপনি যদি চালান 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...

যা ঘটেছিল তা হল নোড প্রক্রিয়াটি কোড সাইনটিন্টের সাথে শুরুতে প্রস্থান করা হয়, তারপরে এটি প্রসেস.এক্সিট () এর দিকে যাত্রা করে এবং অবশেষে প্রস্থান কোড 0 দিয়ে বেরিয়ে আসে।


-1

ক্ষেত্রে যেখানে প্রক্রিয়াটি অন্য নোড প্রক্রিয়া দ্বারা তৈরি হয়েছিল, যেমন:

var child = spawn('gulp', ['watch'], {
    stdio: 'inherit',
});

এবং আপনি এটি পরে মারার চেষ্টা করুন:

child.kill();

আপনি [সন্তানের উপর] ইভেন্টটি এভাবে পরিচালনা করেন:

process.on('SIGTERM', function() {
    console.log('Goodbye!');
});
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.