9

Node / Express: EADDRINUSE, адрес уже занят - как остановить процесс, использующий порт?

5

У меня есть простой сервер на Node.js, использующий библиотеку connect:

var server = require('connect').createServer();
// действия...
server.listen(3000);

В моем коде есть обработчики маршрутов, но это основная идея. Ошибка, которую я постоянно получаю, выглядит так:

EADDRINUSE, Address already in use

Я получаю эту ошибку, когда запускаю приложение снова после того, как оно раньше упало или возникла ошибка. Поскольку я не открываю новый экземпляр терминала, я завершаю процесс с помощью ctrl + z.

Я вполне уверен, что всё, что мне нужно сделать, это закрыть сервер или соединение. Я пытался вызвать server.close() внутри process.on('exit', ...);, но безуспешно.

Что я делаю не так и как правильно освободить адрес при перезапуске сервера?

5 ответ(ов)

9

Сначала вам нужно выяснить, какой процесс использует порт 3000. Для этого выполните следующую команду:

sudo lsof -i :3000

Эта команда выведет список всех PID, которые прослушивают этот порт. После того как вы получите PID, вы можете завершить процесс с помощью следующей команды:

kill -9 <PID>

Где <PID> нужно заменить на идентификатор процесса, который вы получили в результате предыдущей команды, или на список идентификаторов процессов.

6

Вы также можете воспользоваться командной строкой:

ps aux | grep node

чтобы получить идентификаторы процессов.

Затем выполните:

kill -9 PID

Ключ -9 для команды kill отправляет сигнал SIGKILL (вместо SIGTERM). В некоторых случаях узловая программа игнорировала SIGTERM для меня.

3

Я столкнулся с этой проблемой на своем ноутбуке под управлением Windows 8. Решение оказалось простым.

Запустите cmd.exe от имени 'Администратора':

C:\Windows\System32>taskkill /F /IM node.exe
УСПЕХ: Процесс "node.exe" с PID 11008 был завершен.

Это помогло мне!

1

Событие process.on('exit', ..) не вызывается, если процесс завершается из-за аварии или получает сигнал на завершение. Оно срабатывает только в том случае, если цикл событий завершен. Так как server.close() в некоторой степени заканчивает цикл событий (при этом он все еще должен дождаться завершения выполняющихся стэков), имеет мало смысла помещать это в обработчик события exit.

В случае аварии используйте process.on('uncaughtException', ..), а для обработки сигнала завершения — process.on('SIGTERM', ..).

Стоит отметить, что SIGTERM (сигнал на завершение по умолчанию) позволяет приложению выполнить очистку, в то время как SIGKILL (сигнал на немедленное завершение) не дает приложению возможности выполнить какие-либо действия.

1

Чтобы узнать 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) не срабатывает.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь