Как остановить процесс, блокирующий порт в Linux

У вас сервер отказывается запускаться, потому что на порту 8080 уже что-то работает, и вам нужно найти, что именно его занимает, и завершить этот процесс без перезагрузки всей машины. Такое постоянно происходит в реальной работе системного администратора. Вы перезапускаете службу, получаете сообщение «Адрес уже используется», и теперь вы просматриваете списки процессов, пытаясь выяснить, что же занимает ваш порт.

Решение проблемы довольно простое, если вы знаете нужные команды, и есть три надежных способа это сделать в зависимости от того, какие инструменты доступны в вашей системе.

Сначала найдите, что запущено на порту

Прежде чем что-либо завершать, вам нужно узнать, какой процесс владеет портом. Угадывать и завершать случайные процессы — это верный способ сломать что-нибудь в производственной среде. Поэтому сначала запустите одну из этих команд.

lsof — самый распространенный инструмент для этой цели, и он доступен по умолчанию почти в каждой системе Linux.

sudo lsof -i :8080

Здесь sudo запускает команду с правами root, чтобы lsof можно было увидеть процессы, принадлежащие другим пользователям, а не только вашим собственным. Без этого вы увидите только процессы, запущенные вашим текущим пользователем, а это, как правило, не то, что вам нужно.

COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node     3821    ravi   22u  IPv6  54312      0t0  TCP *:8080 (LISTEN)

Этот вывод говорит вам обо всем. node — это имя процесса, 3821PID, который вы будете использовать для его завершения, а LISTEN подтверждает, что он активно держит порт открытым. Если вместо этого вы видите ESTABLISHED, то у процесса есть активное соединение через этот порт.

Если lsof не установлен, используйте команду ss, которая входит в пакет iproute2 и доступна практически в любой современной системе Linux.

sudo ss -tulnp | grep :8080

Вот что делает каждый флаг:

  • -t – показать сокеты TCP
  • -u – показать сокеты UDP
  • -l – показать только сокеты в режиме прослушивания
  • -n – показать номера портов вместо имен служб
  • -p – показать процесс, использующий сокет
tcp   LISTEN 0  128   0.0.0.0:8080   0.0.0.0:*   users:(("node",pid=3821,fd=22))

pid=3821 в конце — это то, что вам нужно. Тот же процесс, тот же PID, просто другой инструмент для его поиска.

Убейте его с помощью команды kill

Как только у вас есть PID, команда kill — это прямой подход. По умолчанию она посылает SIGTERM (сигнал 15), который просит процесс корректно завершить работу и очистить все открытые файловые дескрипторы или соединения перед выходом.

kill 3821

Отсутствие вывода означает, что все сработало. Запустите lsof -i :8080 еще раз, чтобы убедиться.

lsof -i :8080

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

kill -9 3821

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

Убить напрямую с помощью fuser

Команда fuser полностью обходит двухэтапный подход. Вы указываете номер порта, и она убивает все, что его использует, без необходимости поиска PID.

sudo fuser -k 8080/tcp
  • -k – отправляет SIGTERM каждому процессу, использующему этот порт.
  • 8080/tcp – порт и протокол, на которые вы нацеливаетесь.
8080/tcp:  3821
fuser</code> выводит PID убитого процесса и завершает работу. Вот и всё. Если вы хотите SIGKILL вместо SIGTERM, добавьте <code>-9
sudo fuser -k -9 8080/tcp

Примечание: fuser может быть не установлен по умолчанию на минимальных серверных установках, поэтому установите его, как показано.

sudo apt install psmisc         [On Debian, Ubuntu and Mint]
sudo dnf install psmisc         [On RHEL/CentOS/Fedora and Rocky/AlmaLinux]

Убейте процесс одной строкой, используя lsof и kill вместе

Если вы хотите пропустить ручной поиск PID и убить процесс одной командой, объедините lsof и kill с помощью подстановки команд.

sudo kill -9 $(sudo lsof -t -i :8080)

Вот что делает каждая часть:

  • lsof -t -i :8080 флаг -t выводит только PID, ничего больше, так что вы получаете чистый номер для передачи в kill
  • $(...) – подстановка команд, запускает внутреннюю команду и передает её вывод в качестве аргумента.
  • kill -9 — отправляет SIGKILL любому PID, возвращаемому lsof.

Если после запуска этого порта он возвращается пустым, процесс исчез и порт свободен. Если вы получаете kill: usage или синтаксическую ошибку, порт уже был свободен и lsof ничего не вернул, поэтому kill не с чем было работать.

Совет: Если один и тот же порт используют несколько процессов (редко, но бывает с SO_REUSEPORT), эта однострочная команда убивает их все сразу, поскольку lsof -t может возвращать несколько PID в отдельных строках.

Заключение

Теперь у вас есть 3 рабочих подхода: lsof или ss для определения PID, kill для его завершения с помощью PID, fuser для завершения непосредственно по порту и однострочная команда lsof + kill для тех случаев, когда вы хотите сделать это одной командой.

Единственное, что стоит попробовать прямо сейчас: запустите любой сервис на порту 8080 (python3 -m http.server 8080 подойдет, если у вас установлен Python), затем запустите sudo lsof -i :8080, запишите PID и завершите процесс. Повторите это несколько раз, и навык закрепится быстрее, чем любая закладка.

Зарубин Иван Эксперт по Linux и Windows

Парашютист со стажем. Много читаю и слушаю подкасты. Люблю посиделки у костра, песни под гитару и приближающиеся дедлайны. Люблю путешествовать.

Похожие статьи

Комментарии (2)

Автар по умолчанию