#Симптомы и условия возникновения
Одноразовый скрипт Node.js выполнил основную работу, но процесс продолжает существовать: его удерживают таймер, прослушивающий сервер, соединение с базой, сокет или незавершённый поток. Искать нужно активный ресурс, а не завершать процесс силой. Для начала проверьте используемую версию среды и точный текст ошибки на копии проекта, не меняя рабочий сервер.
#Причины и как их отличить
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Незакрытый таймерВ этой ситуации наблюдается конкретный диагностический признак. Сопоставьте его с журналом ошибки и результатом соответствующей проверки, прежде чем выбирать исправление. | В коде есть setInterval, выполняющийся после основной задачи | Отменить таймер или использовать unref в подходящем сценарии. |
| Подключение остаётся открытымВ этой ситуации наблюдается конкретный диагностический признак. Сопоставьте его с журналом ошибки и результатом соответствующей проверки, прежде чем выбирать исправление. | Процесс использует пул БД/HTTP-agent, сокет или сервер | Корректно закрыть подключение методом библиотеки. |
| Открытый серверВ этой ситуации наблюдается конкретный диагностический признак. Сопоставьте его с журналом ошибки и результатом соответствующей проверки, прежде чем выбирать исправление. | Вызван listen, не был вызван close | Вызвать server.close после завершения обслуживания. |
#Пошаговая диагностика и решение
- 1. Убедитесь, что задача действительно закончиласьЗапустите сценарий на копии данных, дождитесь завершающего сообщения. Если оно не появляется, это зависание операции, а не открытый ресурс; смотрите незавершённый await или сетевой запрос.
- 2. Посмотрите типы активных ресурсовВ современных Node.js перед предполагаемым завершением временно вставьте
process.getActiveResourcesInfo(). Вывод сTimeoutнамекает на таймер, сTCPServerWrap— на сервер; он не даёт точное имя объекта, поэтому сопоставьте с кодом.
- 3. Найдите таймер и его жизненный циклПоиск в редакторе проекта:
setInterval,setTimeout,watch,createServer,createConnection. Для интервальных задач сохраняйте идентификатор и вызывайте clearInterval, когда проверка закончена. Не добавляйтеprocess.exit(0)вместо закрытия файлов/сокетов.
- 4. Закройте сервер без обрыва активных запросовДля собственного HTTP-сервера после окончания сценария вызовите
server.close()и дождитесь обратного вызова. Он прекращает приём новых подключений и завершает обслуживание; работа с активными запросами требует учёта версии Node и тайм-аутов.
- 5. Завершите работу пула БДУзнайте используемую библиотеку (например, pg или mysql2) и вызовите её документированный метод завершения (
pool.end()для этих пакетов) в finally. Если подключение было создано где-то ещё, убедитесь, что закрывает его владелец; не уничтожайте разделяемый пул во время работы API.
- 6. Проверьте оставшийся список ресурсовПовторно выведите
process.getActiveResourcesInfo()и найдите оставшиеся ресурсы. Не путайте стандартные TTY и инфраструктурные дескрипторы отладки с ошибкой скрипта.
- 7. Проверьте естественное завершениеЗапустите скрипт без отладчика и убедитесь, что командная строка вернулась без принудительного kill. Если не вернулась, верните изменение и по одному отключайте собственные компоненты на тестовой копии.
- Пример кода по темеТекстПокажите в отдельной тестовой ветке; server должен ссылаться на ваш экземпляр HTTP-сервера.
console.log('Активные ресурсы:', process.getActiveResourcesInfo()); // Для собственного сервера после окончания обслуживания: server.close((error) => { if (error) console.error('Не удалось закрыть сервер:', error); });
#Как проверить результат и что делать, если не помогло
После завершения всех задач процесс сам освобождает ресурсы, возвращает управление терминалу, записи в БД/файлах сохранены.
Если неисправность повторилась, выпишите первый код ошибки и действие, на котором она возвращается. Сравните версию Node.js/npm, рабочий каталог, настройки процесса и журнал тестового запуска. Откатите только внесённые изменения из предварительно сохранённой копии, затем разберите причину на отдельной среде.