Node и NPM Запуск скрипта и Ctrl-C запускают SIGINT дважды
Я столкнулся с проблемой в одном из моих приложений Nodejs, работающих с npm start
(который просто делает node app.js
).
Мое приложение содержит обработчик сигинта следующим образом:
process.on('SIGINT', () => {
db.disconnect().then({
process.exit(0);
}).catch(e => process.exit(1));
});
С соответствующими журналами. После некоторого тестирования других файлов, я заметил, что Ctrl-C, когда на npm
Процесс вызывает SIGINT дважды, если первый из них занимает слишком много времени для выхода. (попробуйте добавить таймаут в пример приложения).
На данный момент я добавил счетчик, чтобы проверить, выполняется ли вызов более одного раза, но я не уверен, что это "путь" в отношении этой проблемы. Я предполагаю, что SIGINT для процесса npm, как ожидается, завершится через определенный промежуток времени, поэтому npm передает его еще раз (всегда только дважды).
Кто-нибудь сталкивался с этой проблемой и нашел жизнеспособное решение?
Спасибо!
3 ответа
Возможно, вы захотите запустить свою команду напрямую через узел, а не через npm start
. NPM может быть причиной странного перехвата сигналов, см. https://lisk.io/blog/tutorial/why-we-stopped-using-npm-start-child-processes.
Ваш обработчик SIGINT может вызываться несколько раз, вы должны написать свой код для защиты от этого.
Также, если вы используете родительские / дочерние процессы, см. https://github.com/jtlapp/node-cleanup.
Когда вы нажимаете Ctrl-C, вы отправляете сигнал SIGINT каждому процессу в текущей группе процессов. Группа процессов - это набор процессов, которые должны завершиться вместе как группа, а не существовать независимо. Однако некоторые программы, такие как Emacs, перехватывают и изменяют назначение SIGINT, так что это не завершает процесс. В таких случаях SIGINT не должен завершать какие-либо процессы группы.
Кроме того, в большинстве случаев вызов process.exit не требуется, см. https://nodejs.org/api/process.html
Вместо этого установите process.exitCode
, удалите обработчики сигналов, а затем повторно поднимите сигнал с помощью process.kill(process.pid, signal)
Я знаю, что этот пост существует уже некоторое время, но, к сожалению, у меня такая же проблема. При беге простоnode <app.js>
выдает только один сигнал. Этот сигнал приходит дважды, если работаетnpm start
. Вместо счетчика я предлагаю проверить, продолжает ли сервер слушать, если да, продолжайте свою логику и внутреннее завершение (например, подключения к базе данных и т. Д.):
process.on('SIGINT', function(){
if (server.listening) {
server.close(function (err) {
if (err) {
console.error(err);
process.exit(1)
}
process.exit(0);
})
}
})
Более чистым решением было бы обернуть обработчик отключения в обещание, и из-за внутренней реализации обещания разрешение будет вызываться только один раз.
new Promise((resolve) => process.on('SIGINT', resolve))
.then(() => db.disconnect())
.then(() => process.exit(0))
.catch(() => process.exit(1));
Примечание. Я бы посоветовал избегать явного вызова process.exit() и позволить узлу выйти самостоятельно. Если по каким-то причинам процесс не завершился, это означает, что есть что-то, что его блокирует (например, прослушивание портов, открытые/ожидающие TCP-соединения, очищенные
setInterval
или же
setTimeout
использованная литература)