Блог

Как на linux найти процесс слушающий порт?

September 29, 2020

Во время разработки периодически возникают ситуации, когда вы запустили, например, NodeJs сервер и в какой-то момент произошла ошибка. Вы прерываете процесс через Ctrl+C, запускаете сервер заново, но в ответ видите ошибку Error: listen EADDRINUSE: address already in use :::3000. Самое неприятное с этой ошибкой то, что вы вроде бы остановили процесс, однако несмотря на это, процесс так и не освободил порт и все еще крутится где-то в памяти. В этом посте речь пойдет о том, как отловить такие процессы и все же убить их.

Чтобы убить процесс в linux, вам необходимо использовать команду kill с сигналом 9 (SIGKILL):

kill -9 <PID>

Чтобы получить process id (PID), нужно выполнить другую команду. При чем в конкретно нашей ситуации, нам нужно найти процесс по номеру порта, который он занял. Разновидностей команд для решения такой задачи есть довольно много и далеко не все из этих программ будут установлены в системе, с которой вам придется работать. Потому далее предлагаю несколько альтернативных команд, чтобы было из чего выбирать. Начну с той, которую обычно использую сам.

Обратите внимание, если процесс был запущен на порту :80 или если он был запущен другим юзером, скорее всего вам понадобится добавить sudo, чтобы выполнить команду с правами администратора, иначе со своего юзера вы либо не сможете увидеть процессы, либо не увидите их PID.

lsof

Чтобы проверить какой процесс слушает на порту 3000, необходимо ввести следующую команду:

lsof -i :3000

Расшифровку ключей можно посмотреть здесь

В ответ получите нечто на подобии этого:

COMMAND    PID        USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
node    241907 sleepwalker   38u  IPv6 3609283      0t0  TCP *:3000 (LISTEN)

Можно так же передать флаг -t, чтобы получить только pid. Это дает возможность убить нужный процесс в одну строку:

kill -9 $(lsof -t -i:3000)

fuser

fuser -v -n tcp 3000

вывод команды будет выглядеть так:

                     USER        PID ACCESS COMMAND
3000/tcp:            sleepwalker  367896 F.... node

Расшифровку ключей можно посмотреть здесь

Более короткий вариант команды:

fuser 3000/tcp

Кроме того, можно сразу попросить fuser убить процесс:

fuser -k 3000/tcp

ss

ss -tlpn

вывод команды будет выглядеть так:

State    Recv-Q   Send-Q      Local Address:Port        Peer Address:Port   Process
LISTEN   0        511             127.0.0.1:3000             0.0.0.0:*       users:(("node",pid=365730,fd=22))
LISTEN   0        511             127.0.0.1:42679            0.0.0.0:*       users:(("code",pid=338363,fd=109))
LISTEN   0        5               127.0.0.1:631              0.0.0.0:*
LISTEN   0        1                 0.0.0.0:7070             0.0.0.0:*

Расшифровку ключей можно посмотреть здесь

Самый простой способ сократить вывод команды — использовать grep: ss -tlpn | grep 3000.

netstat

netstat -tlpn

Вот так будет выглядеть вывод команды:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 :::3000                 :::*                    LISTEN      25/.pm2)
tcp        0      0 :::27017                :::*                    LISTEN      -

Расшифровку ключей можно посмотреть здесь. Флаг -t отфильтровывает только TCP соединения.

Самый простой способ сократить вывод команды — использовать grep: netstat -tlpn | grep 3000.

Выводы

В этом посте было рассмотрено 4 утилиты, которые помогут найти и убить процесс, который занял порт. Надеюсь, эта информация окажется вам полезной и спасет вас от лишних затрат времени на поиски решения в будущем.