ss — штатный инструмент iproute2 для просмотра сокетов, а netstat из пакета net-tools устарел: в свежих Debian, Ubuntu и Fedora его может не быть. ss читает данные напрямую из ядра и показывает то, чего нет в старом выводе: состояния, очереди, таймеры и параметры TCP. Разберём, как найти занятый порт и отличить нормальный TIME_WAIT от утечки CLOSE_WAIT.
Что такое сокет и что показывает ss
Сокет — это пара «адрес:порт» плюс состояние протокола. В выводе ss одна строка соответствует одному сокету. Для слушающего сокета Recv-Q — сколько соединений ждёт в очереди accept, а Send-Q — предел этой очереди. Для установленного соединения Recv-Q — байты, которые приложение ещё не прочитало, Send-Q — байты, не подтверждённые сетью.
ss -tulpn
ss -tan
ss -s
Ключи простые: -t — TCP, -u — UDP, -l — только слушающие, -p — процесс, -n — без DNS. Комбинация -tulpn стала шпаргалкой. Без -a не видно закрывающихся сокетов.
Состояния TCP без паники
LISTEN — сервис ждёт подключения, ESTAB — рабочее соединение, TIME_WAIT держится около минуты после разрыва и защищает от дубликатов. Много TIME_WAIT на веб-сервере — следствие коротких соединений, а не авария.
SYN-SENT— мы отправили SYN и ждём ответ; много строк означает потери или недоступный адрес.SYN-RECV— пришёл SYN, ответ ушёл; застой говорит о проблемах с очередью.FIN-WAIT-1/2— корректное закрытие;FIN-WAIT-2висит, если вторая сторона молчит.CLOSE-WAIT— удалённая сторона закрылась, а приложение не вызвалоclose().LAST-ACKиCLOSING— редкие состояния, застрявшие надолго, требуют разбора.
ss -tan state established
ss -Htan state time-wait | wc -l
ss -tan state close-wait
Фильтр state принимает имена состояний. Если CLOSE_WAIT накапливается сотнями, ищите процесс через -p: приложение не закрывает дескрипторы, и увеличение лимита лишь отложит проблему.
Фильтры по адресам и портам
Выводить сотни строк и искать глазами — плохая практика. ss фильтрует по адресам и портам; кавычки обязательны, иначе shell попытается разобрать скобки и двоеточия.
ss -tn 'sport = :22'
ss -tn 'dport = :443'
ss -tn dst 192.168.1.10
ss -tn '( dport = :80 or dport = :443 )'
ss -ltn 'sport = :8080'
dst и src работают по IP, dport и sport — по портам. Вместе с state можно одним запросом получить все соединения к базе данных.
ss -tnp state established '( dport = :5432 or sport = :5432 )'
Кто занял порт: процесс, inode и файл
Ключ -p показывает процесс, если хватает прав на чтение /proc. Для чужих процессов нужен root; если вместо имени прочерк, проверьте права и kernel.yama.ptrace_scope.
sudo ss -tulpn 'sport = :80'
sudo lsof -iTCP:80 -sTCP:LISTEN
sudo fuser -v -n tcp 80
sudo ss -tlnpe 'sport = :80'
В выводе ss -e есть inode сокета. По нему находят дескриптор в /proc/<pid>/fd, если процесс уже не виден в ss -p.
sudo ss -tlnpe 'sport = :80'
sudo ls -l /proc/1234/fd | grep socket
sudo grep -i ':0050' /proc/net/tcp
В /proc/net/tcp порт записан в шестнадцатеричном виде: 0050 — это 80, 1F90 — 8080.
Очереди, таймеры и параметры TCP
Ключ -i показывает внутреннюю информацию TCP: RTT, cwnd, retrans, доставленные сегменты. Ключ -o добавляет таймеры.
ss -tinp
ss -toin state established
ss -tin '( dport = :443 )' | head -20
Растущий retrans указывает на потери, маленькое cwnd при большом RTT объясняет низкую скорость. Если Recv-Q слушающего сокета близок к Send-Q, приложение не успевает вызывать accept(): соединения сбрасываются, хотя сервис формально работает.
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
nstat -az TcpExtListenOverflows TcpExtListenDrops
Счётчики ListenOverflows и ListenDrops подтверждают переполнение. Увеличивайте somaxconn вместе с backlog в приложении: один sysctl без правки конфигурации сервиса ничего не даст.
UDP и UNIX-сокеты
У UDP состояния нет, поэтому ss -uan показывает сокеты и очереди, но не соединения. Ключ -x открывает UNIX-сокеты, через которые общаются systemd, базы данных и Docker.
ss -uan
ss -xap
ss -xl | grep -i docker
ss -xp | grep -i postgres
При ошибке «Address already in use» для UNIX-сокета удаляйте файл только после остановки процесса-владельца.
netstat: что осталось и чем заменить
netstat ещё встречается в старых инструкциях, но его возможности ограничены, а вывод менее информативен. Основные соответствия пригодятся при чтении чужой документации.
netstat -tulpn→ss -tulpnnetstat -an→ss -annetstat -i→ip -s linknetstat -rn→ip routenetstat -s→nstat -az
netstat -tulpn
netstat -rn
ip -s link
ss -s
Если netstat нужен старому скрипту, поставьте net-tools, но новые проверки пишите на ss и ip.
Практические сценарии
Порт занят после перезапуска. Найдите процесс через ss -tulpn, остановите его штатно, проверьте, что сокет исчез, и только потом запускайте новый экземпляр.
Сайт открывается нестабильно. ss -s и nstat покажут переполнение accept-очереди, потери и ретрансмиссии. Дальше смотрите ss -tin по конкретному соединению.
Много TIME_WAIT. Для коротких клиентских соединений это норма. Если упираетесь в лимит локальных портов, расширьте диапазон, но не отключайте защиту без понимания последствий.
Приложение висит. Скопление CLOSE_WAIT почти всегда означает, что код не закрывает дескриптор после ошибки. Проверьте ulimit -n и lsof -p PID | wc -l.
Чек-лист диагностики
- Начните с
ss -tulpn: кто слушает и на каких адресах. - Проверьте, не привязан ли сервис к
127.0.0.1вместо внешнего адреса. - Смотрите состояния, а не только список портов.
- Сопоставьте
Recv-QиSend-Qу слушающего сокета. - Проверьте потери через
nstat, прежде чем менять sysctl.
Итог
ss — базовый инструмент сетевой диагностики. Четыре команды покрывают большинство задач: ss -tulpn для слушателей, ss -tan state established для активных соединений, ss -tinp для качества TCP и ss -s для общей картины. netstat оставьте для старых инструкций. Главное — смотреть на состояния и очереди, а не только на номера портов: именно там причина сбоя.