Исправление ошибки: 'listen EADDRINUSE: address already in use' в Node.js
  Печально известная ошибка EADDRINUSE возникает, когда вы меньше всего этого ожидаете. Вы готовы запустить свой Node.js сервер, но вместо работающего приложения получаете: Error: listen EADDRINUSE: address already in use :::3000. Эта ошибка Node.js EADDRINUSE означает, что другой процесс уже использует порт, к которому вы пытаетесь привязаться. Вот как быстро идентифицировать и исправить этот конфликт портов в Node.js.
Ключевые моменты
- Ошибка EADDRINUSE возникает, когда порт уже занят другим процессом
 - Используйте 
lsofна macOS/Linux илиnetstatна Windows для идентификации блокирующего процесса - Завершите процесс, используя его PID, или реализуйте обработчики корректного завершения
 - Предотвращайте будущие конфликты с помощью динамического выбора портов и правильной обработки сигналов
 
Что вызывает ошибку EADDRINUSE?
Ошибка listen EADDRINUSE возникает, когда ваше Node.js приложение пытается привязаться к порту, который уже занят. Типичные причины включают:
- Предыдущий экземпляр вашего сервера всё ещё работает
 - Другое приложение использует тот же порт
 - Зомби-процессы от упавших Node.js приложений
 - Инструменты горячей перезагрузки, такие как nodemon, не выполняют очистку
 - Встроенные терминалы IDE поддерживают процессы активными
 
Как найти процесс, использующий порт
Прежде чем вы сможете освободить занятый порт, нужно определить, что его использует. Команды различаются в зависимости от операционной системы.
macOS и Linux
Используйте lsof для поиска процесса:
lsof -i :3000
Это возвращает детали процесса, включая PID (идентификатор процесса):
COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node     12345   you   11u  IPv6 0xac745b2749fd2be3      0t0  TCP *:3000 (LISTEN)
Windows
Используйте netstat для идентификации процесса:
netstat -ano | findstr :3000
Вывод показывает PID в последнем столбце:
TCP    0.0.0.0:3000    0.0.0.0:0    LISTENING    12345
Как завершить процесс и освободить порт
Получив PID, вы можете завершить процесс, чтобы освободить порт.
Решения для macOS и Linux
Быстрая однострочная команда:
lsof -ti:3000 | xargs kill -9
Ручной подход:
kill -15 12345  # Корректное завершение (предпочтительно)
kill -9 12345   # Принудительное завершение, если -15 не работает
Альтернатива с использованием fuser:
sudo fuser -k 3000/tcp
Решения для Windows
Командная строка:
taskkill /PID 12345 /F
PowerShell:
Stop-Process -Id 12345 -Force
Метод через GUI: Откройте Диспетчер задач (Ctrl+Shift+Esc), найдите процесс Node.js и завершите его.
Discover how at OpenReplay.com.
Предотвращение будущих конфликтов портов
Реализация корректного завершения
Добавьте правильные обработчики очистки в ваш Node.js сервер, чтобы предотвратить ошибки портов:
const server = app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
// Handle termination signals
process.on('SIGTERM', () => {
  server.close(() => {
    console.log('Server closed gracefully');
    process.exit(0);
  });
});
process.on('SIGINT', () => {
  server.close(() => {
    console.log('Server closed gracefully');
    process.exit(0);
  });
});
Использование динамического выбора портов
Избегайте жёсткого кодирования портов. Используйте переменные окружения или автоматически находите доступный порт:
const PORT = process.env.PORT || 3000;
// Or check port availability before binding
const net = require('net');
function getAvailablePort(startPort) {
  return new Promise((resolve) => {
    const server = net.createServer();
    server.listen(startPort, () => {
      const port = server.address().port;
      server.close(() => resolve(port));
    });
    server.on('error', () => {
      getAvailablePort(startPort + 1).then(resolve);
    });
  });
}
Программная обработка ошибки
Перехватывайте ошибку и реагируйте соответствующим образом:
server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.error(`Port ${PORT} is already in use`);
    // Try another port or exit gracefully
    process.exit(1);
  }
});
Распространённые сценарии и быстрые исправления
Nodemon не освобождает порты
Если используете nodemon, убедитесь, что останавливаете его с помощью Ctrl+C, а не Ctrl+Z. Последняя комбинация приостанавливает процесс без освобождения порта.
Конфликты Docker-контейнеров
Проверьте запущенные контейнеры:
docker ps
docker stop <container_id>
Проблемы с терминалом VS Code
Закройте все встроенные терминалы перед перезапуском сервера. Иногда VS Code поддерживает процессы активными в фоновом режиме.
Несколько экземпляров сервера в коде
Убедитесь, что не вызываете app.listen() несколько раз в вашей кодовой базе. Эта распространённая ошибка немедленно вызывает ошибку address already in use.
Заключение
Ошибка Node.js EADDRINUSE раздражает, но легко исправляется. Найдите процесс, использующий ваш порт, с помощью lsof или netstat, завершите его и реализуйте правильные обработчики завершения, чтобы предотвратить будущие случаи. Помните: корректное завершение с обработчиками сигналов и динамический выбор портов избавят вас от необходимости постоянно иметь дело с этой ошибкой порта сервера Node.js.
Часто задаваемые вопросы
Да, вы можете реализовать автоматическое переключение портов, перехватывая ошибку EADDRINUSE и пробуя следующий доступный порт. Используйте рекурсивную функцию или цикл для последовательной проверки портов до нахождения свободного, или используйте библиотеки вроде portfinder, которые обрабатывают это автоматически.
Закрытие окна терминала не всегда завершает запущенные процессы. Фоновые процессы, особенно запущенные с nohup или как службы, продолжают работать. Всегда используйте правильные команды завершения, такие как Ctrl+C, или явно завершайте процесс, используя его PID, чтобы убедиться, что порт освобождён.
Использование kill -9 принудительно завершает процесс немедленно без возможности очистки, что может привести к потере данных или их повреждению. Всегда сначала пробуйте kill -15 для корректного завершения. Оставляйте kill -9 для неотвечающих процессов. Реализуйте правильные обработчики сигналов в вашем коде для обеспечения чистого завершения.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.