Как я буду держать процесс node.js открытым в течение секунды, когда я его закрываю [дублировать]

работает нормально и производит ожидаемый результат вместо любой ошибки времени выполнения.

Это основная ошибка допущения.

Приложение: обратите внимание, что при наличии дефекта CWG ( # 315

Addendum: g0]), который закрывается как «согласованный» , а не , делающий вышеуказанный UB, он полагается на положительное закрытие другого дефекта CWG (

# 232 ), который по-прежнему активен, и, следовательно, ни один из них не добавлен к стандарту.

Позвольте мне привести часть комментария из Джеймса Макнеллиса к an ответьте на аналогичный вопрос переполнения стека:

Я не думаю, что дефект CWG 315 «закрыт», поскольку его присутствие на странице «закрытые проблемы» подразумевает. В обосновании говорится, что это должно быть разрешено, потому что «* p не является ошибкой, когда p равно null, если значение lvalue не преобразуется в значение r». Тем не менее, это зависит от концепции «пустой lvalue», которая является частью предлагаемой резолюции для дефекта CWG 232, но которая не была принята.

238
задан Erel Segal-Halevi 25 December 2012 в 17:07
поделиться

8 ответов

UPDATE:

Вы можете зарегистрировать обработчик для 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}));
370
ответ дан dopeddude 18 August 2018 в 23:28
поделиться
  • 1
    Есть ли способ обрабатывать как Ctrl + C, так и обычный выход в одном месте, или мне нужно написать два отдельных обработчика? Как насчет других типов выхода, таких как необработанное исключение - для этого случая есть специальный обработчик, но должен ли я обработать это с помощью третьей копии того же обработчика? – Erel Segal-Halevi 26 December 2012 в 11:04
  • 2
    Можете ли вы объяснить process.stdin.resume (), как это работает? – Rob Fox 4 February 2014 в 21:46
  • 3
    @RobFox resume () инициализирует процесс чтения. По умолчанию Stdin приостановлен. Вы можете узнать больше: github.com/joyent/node/blob/… – Emil Condrea 5 February 2014 в 14:08
  • 4
    Обратите внимание, что вы must only выполняете операции synchronous в обработчике exit – Lewis 10 February 2015 в 15:23
  • 5
  • 6
    Это решение имеет множество проблем. (1) Он не сообщает сигналы родительским процессам. (2) Он не передает код выхода родительскому процессу. (3) Это не позволяет детям, подобным Emacs, игнорировать Ctrl-C SIGINT. (4) Он не позволяет асинхронную очистку. (5) Он не координирует одно сообщение stderr для нескольких обработчиков очистки. Я написал модуль, который делает все это, github.com/jtlapp/node-cleanup , первоначально основанный на решении cleanup.js ниже, но сильно переработанный на основе обратной связи. Надеюсь, это окажется полезным. – Joe Lapp 27 December 2016 в 06:45
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
5
ответ дан Abdullah Aydın 18 August 2018 в 23:28
поделиться
  • 1
    Этот ответ заслуживает всей славы, но, поскольку нет никаких объяснений, к сожалению, нет никакого голосования. Что такое значительный об этом ответе, , говорит doc , "Функции прослушивателя должны выполнять только синхронные операции. Процесс Node.js выйдет сразу после вызова прослушивателей событий «exit», из-за чего любая дополнительная работа, все еще поставленная в очередь в цикле событий, будет отменена. & quot; , и этот ответ преодолевает это ограничение! – xpt 25 February 2018 в 15:36

Просто хотел упомянуть пакет 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
})
4
ответ дан antongorodezkiy 18 August 2018 в 23:28
поделиться

io.js имеет событие exit и beforeExit , которые делают то, что вы хотите.

0
ответ дан Golo Roden 18 August 2018 в 23:28
поделиться

В случае, когда процесс был порожден другим процессом узла, например:

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

И вы пытаетесь его убить позже, через:

child.kill();

Это как вы обрабатываете событие [у ребенка]:

process.on('SIGTERM', function() {
    console.log('Goodbye!');
});
-1
ответ дан Jaime Gómez 18 August 2018 в 23:28
поделиться

Это улавливает каждое событие выхода, которое я могу найти, которое можно обработать. До сих пор кажется довольно надежным и чистым.

[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `SIGTERM`].forEach((eventType) => {
  process.on(eventType, cleanUpServer.bind(null, eventType));
})
4
ответ дан light24bulbs 18 August 2018 в 23:28
поделиться

Нижеприведенный сценарий позволяет иметь один обработчик для всех условий выхода. Он использует специальную функцию обратного вызова для выполнения пользовательского кода очистки.

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 
135
ответ дан Pier-Luc Gendreau 18 August 2018 в 23:28
поделиться
  • 1
    Этот ответ заслуживает большего доверия, чем он получает. – Pier-Luc Gendreau 19 November 2014 в 00:33
  • 2
    Я нашел этот код незаменимым и создал для него пакет узлов, с изменениями, зачислив вас и этот ответ SO. Надеюсь, все в порядке, @CanyonCasa. Спасибо! npmjs.com/package/node-cleanup – Joe Lapp 13 September 2016 в 16:07
  • 3
    Мне нравится очистка. Но мне не нравится process.exit (0); cons.org/cracauer/sigint.html Я чувствую, что вы должны позволить ядру обрабатывать уничтожение. Вы не выходите так же, как SIGINT. SIGINT не выходит с 2. Вы принимаете SIGINT с кодом ошибки. Они не то же самое. На самом деле Ctrl + C существует с 130. Не 2. tldp.org/LDP/abs/html/exitcodes.html – Banjocat 18 November 2016 в 03:44
  • 4
    Я переписал npmjs.com/package/node-cleanup , так что обработка SIGINT хорошо работает с другими процессами, по ссылке @ Banjocat. Он также теперь корректно передает сигналы родительскому процессу вместо вызова process.exit(). У обработчиков очистки теперь есть возможность вести себя как функция кода выхода или сигнала, а обработчики очистки могут быть удалены, если необходимо, для поддержки асинхронной очистки или предотвращения циклической очистки. Теперь он мало похож на приведенный выше код. – Joe Lapp 27 December 2016 в 06:28
  • 5
    Забыл упомянуть, что я также сделал (надеюсь) всеобъемлющий набор тестов. – Joe Lapp 27 December 2016 в 06:36

«exit» - событие, которое запускается, когда узел завершает цикл события внутри, он не запускается, когда вы завершаете процесс извне.

То, что вы ищете, выполняет что-то на 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.');
});

Примечание: это, кажется, прерывает сигмин, и вам нужно будет вызвать process.exit (), когда вы закончите с кодом.

14
ответ дан user1278519 18 August 2018 в 23:28
поделиться
  • 1
    Есть ли способ обрабатывать как Ctrl + C, так и обычный выход в одном месте? Или мне нужно написать два одинаковых обработчика? – Erel Segal-Halevi 25 December 2012 в 22:49
  • 2
    Как примечание, если вам нужно закончить узел командой kill, выполняющей kill -2, будет передан код SIGINT. Мы должны сделать это так, потому что у нас есть ведение журнала узла в txt-файле, поэтому Ctrl + C невозможно. – Aust 15 February 2013 в 01:22
Другие вопросы по тегам:

Похожие вопросы: