Node / Express: EADDRINUSE, адрес уже занят - как остановить процесс, использующий порт?
У меня есть простой сервер на Node.js, использующий библиотеку connect:
var server = require('connect').createServer();
// действия...
server.listen(3000);
В моем коде есть обработчики маршрутов, но это основная идея. Ошибка, которую я постоянно получаю, выглядит так:
EADDRINUSE, Address already in use
Я получаю эту ошибку, когда запускаю приложение снова после того, как оно раньше упало или возникла ошибка. Поскольку я не открываю новый экземпляр терминала, я завершаю процесс с помощью ctrl + z
.
Я вполне уверен, что всё, что мне нужно сделать, это закрыть сервер или соединение. Я пытался вызвать server.close()
внутри process.on('exit', ...);
, но безуспешно.
Что я делаю не так и как правильно освободить адрес при перезапуске сервера?
5 ответ(ов)
Сначала вам нужно выяснить, какой процесс использует порт 3000
. Для этого выполните следующую команду:
sudo lsof -i :3000
Эта команда выведет список всех PID, которые прослушивают этот порт. После того как вы получите PID, вы можете завершить процесс с помощью следующей команды:
kill -9 <PID>
Где <PID>
нужно заменить на идентификатор процесса, который вы получили в результате предыдущей команды, или на список идентификаторов процессов.
Вы также можете воспользоваться командной строкой:
ps aux | grep node
чтобы получить идентификаторы процессов.
Затем выполните:
kill -9 PID
Ключ -9
для команды kill
отправляет сигнал SIGKILL (вместо SIGTERM). В некоторых случаях узловая программа игнорировала SIGTERM для меня.
Я столкнулся с этой проблемой на своем ноутбуке под управлением Windows 8. Решение оказалось простым.
Запустите cmd.exe от имени 'Администратора':
C:\Windows\System32>taskkill /F /IM node.exe
УСПЕХ: Процесс "node.exe" с PID 11008 был завершен.
Это помогло мне!
Событие process.on('exit', ..)
не вызывается, если процесс завершается из-за аварии или получает сигнал на завершение. Оно срабатывает только в том случае, если цикл событий завершен. Так как server.close()
в некоторой степени заканчивает цикл событий (при этом он все еще должен дождаться завершения выполняющихся стэков), имеет мало смысла помещать это в обработчик события exit
.
В случае аварии используйте process.on('uncaughtException', ..)
, а для обработки сигнала завершения — process.on('SIGTERM', ..)
.
Стоит отметить, что SIGTERM (сигнал на завершение по умолчанию) позволяет приложению выполнить очистку, в то время как SIGKILL (сигнал на немедленное завершение) не дает приложению возможности выполнить какие-либо действия.
Чтобы узнать PID (идентификатор процесса), который использует порт 3000, выполните следующую команду:
lsof -i tcp:3000
На выходе вы получите что-то похожее на это:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 5805 xyz 12u IPv6 63135 0t0 TCP *:3000 (LISTEN)
Как видно из вывода, PID процесса – это 5805. Чтобы завершить этот процесс, выполните команду:
kill -9 5805
Обратите внимание, что использование -9
(SIGKILL) завершает процесс принудительно, поэтому рекомендуется применять эту команду только в тех случаях, когда стандартное завершение (например, kill 5805
) не срабатывает.
Как предотвратить установку "devDependencies" модулей NPM для Node.js (package.json)?
Ошибка "npm WARN package.json: Нет поля repository"
Как исправить ошибку "ReferenceError: primordials is not defined" в Node.js
Как протестировать один файл с помощью Jest?
nvm постоянно "забывает" Node.js в новой сессии терминала