Перейти к содержимому

ss: socket statistics вместо устаревшего netstat

Если netstat зависает на сервере с десятками тысяч соединений — пора переходить на ss. Утилита из пакета iproute2 работает напрямую с ядром через netlink, а не парсит /proc/net/*. Результат — мгновенный вывод и меньше накладных расходов.

Зачем переходить с netstat

netstat из net-tools использует устаревшую схему: читает файлы из /proc/net/tcp, /proc/net/unix и преобразует числовые ID в символические имена. На сервере с активными соединениями это занимает секунды и нагружает CPU.

ss обращается к ядру через netlink-сокет. Вызов один, данные уже структурированные. Для 10 000 соединений разница — 0.02 секунды против 3–5 секунд.

Примечание

netstat официально помечен как deprecated в большинстве дистрибутивов. iproute2 — текущий стандарт для управления сетью в Linux.

Установка отдельно обычно не нужна: ss входит в iproute2, который есть в любом Linux по умолчанию.

Базовые флаги: аналог -tulnp

Запоминать заново не придётся — флаги похожи, только порядок гибче:

# Слушать порты, показать процесс
ss -tlnp
ФлагЧто показывает
-tTCP-сокеты
-uUDP-сокеты
-lТолько слушающие
-nЧисловые адреса и порты (без DNS)
-pПроцесс-владелец (PID, имя)
-aВсе сокеты (не только слушающие)
-eРасширенная информация (uid, inode)
-oИнформация по таймерам

Порядок флагов не важен — -tlnp и -ltnp дают один результат. -p показывает чужие процессы только с root.

Вывод отличается от netstat структурно:

State      Recv-Q   Send-Q   Local Address:Port   Peer Address:Port   Process
LISTEN     0        128      0.0.0.0:22           0.0.0.0:*          users:(("sshd",pid=1234,fd=3))
LISTEN     0        511      127.0.0.1:6379       0.0.0.0:*          users:(("redis-server",pid=5678,fd=6))

Ключевые колонки:

КолонкаЧто значит
Recv-QБайт в приёмном буфере, не прочитанных приложением
Send-QБайт в отправляющем буфере, не подтверждённых получателем
Local Address:PortЛокальный конец соединения
Peer Address:PortУдалённый конец
Подсказка

Ненулевые значения Recv-Q или Send-Q на established-соединении — признак проблемы. Приложение не успевает читать или сеть перегружена.

Полный набор базовых фильтров:

ss -t       # только TCP
ss -u       # только UDP
ss -w       # raw sockets
ss -x       # Unix sockets
ss -a       # все (listening и established)
ss -l       # только listening

Фильтрация по состоянию и порту

ss выигрывает у netstat именно здесь. Фильтры нативные, не через grep:

# Только установленные соединения
ss -t state established

# Только активные (не listening)
ss -t state connected

# TIME_WAIT — классический кейз
ss -t state time-wait

# Все, кроме listening
ss -t state connected -s

Комбинации состояний:

# ESTABLISHED с информацией о процессе
ss -t state established -p

# SYN-SENT, SYN-RECV — проблемы с установкой
ss -t state syn-sent

# FIN-WAIT-1, FIN-WAIT-2
ss -t state fin-wait1,fin-wait2

# CLOSE-WAIT — соединение висит, ждёт закрытия
ss -t state close-wait

# Группировка состояний
ss -tan 'state established or state time-wait'

Фильтр по порту — один из самых частых:

# Кто слушает 443
ss -tlnp 'sport = :443'

# Кто подключён к 5432 (PostgreSQL)
ss -tp 'dport = :5432'

# Все подключения к любому порту 80 или 443
ss -t 'sport = :80 or dport = :80 or sport = :443 or dport = :443'
Предупреждение

Фильтры sport и dport работают с числовыми значениями. Для диапазонов используйте >= и <=: 'dport >= 3000 and dport <= 4000'.

Фильтр по адресу:

# Подключения с конкретного IP
ss -tp 'src 192.168.1.100'

# Подключения наружу (не из локальной сети)
ss -tp 'not src 192.168.0.0/16'

Расширенный вывод: -e, -i, -s

Для диагностики очередей и статистики:

# Подробная информация (extended)
ss -teln

# Добавляет:
# - uid (пользователь)
# - inode
# - timers (для keepalive, TIME_WAIT)
# - timeout

Вывод с -e для Established-соединения:

ESTAB 0 0 10.0.0.5:22 10.0.0.100:52431 users:(("sshd",pid=1820,fd=3)) uid=1000 ino=35234 sk=0xffff88003a2c8000 <->

Информация об интерфейсе (-i):

ss -ti 'dst 10.0.0.1'
ESTAB 0 0 10.0.0.5:22 10.0.0.100:52431
         ts sack hbrs pmtu cwnd rtt rttvar unacked
         wscale:7,7 pmtu:1500 rcvmss:1448 advmss:1448 cwnd:10
         send 0.4Mbps rcv_space:43690

Ключевые метрики:

МетрикаОписание
cwndCongestion window — окно перегрузки
rttRound-trip time
pmtuPath MTU
rcv_spaceРазмер receive buffer
sendТекущая скорость отправки

Статистика по состояниям (-s):

ss -s
Total: 124 (kernel 128)
TCP:   45 (estab 38, closed 2, orphaned 0, synrecv 0, timewait 2)

Transport Total     IP          IPv6
*         128       -           -
RAW       0         0           0
UDP       12        8           4
TCP       43        38          5
INET      55        46          9
FRAG      0         0           0
Примечание

Параметр timewait 2 в выводе ss -s — быстрый способ оценить накопление соединений. Если число растёт при каждом запуске — что-то не закрывает соединения штатно.

Типичные кейзы

Кто слушает порт и на каком интерфейсе:

ss -tlnp 'sport = :3306'
State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
LISTEN  0       128     0.0.0.0:3306        0.0.0.0:*         users:(("mysqld",pid=2345,fd=18))
LISTEN  0       128     127.0.0.1:3306      0.0.0.0:*         users:(("mysqld",pid=2345,fd=17))

Дважды слушает — значит, один раз на всех интерфейсах, второй на localhost. Если нужен только внешний — искать в конфиге bind-address.

Сколько сокетов в TIME_WAIT — и к кому они копятся:

ss -s | grep timewait
# или
ss -ant | awk '/TIME-WAIT/ {count++} END {print count}'

# Топ направлений с утечкой TIME-WAIT
ss -tan state time-wait | awk '{print $5}' | sort | uniq -c | sort -rn | head -20
Подсказка

Много TIME_WAIT обычно нормально. Если мешает — на стороне клиента setsockopt с SO_LINGER или SO_REUSEADDR на сервере. Флаг -ttu покажет таймеры.

Не зависло ли соединение:

ss -ti 'dst 10.0.0.50'

Смотрим rtt и unacked. Если unacked растёт, а rtt не меняется — пакеты не доходят, но и не теряются. Скорее всего, удалённая сторона перестала читать из сокета.

Найти процесс, открывший соединение на конкретный хост:

ss -tp 'dst 192.168.1.50'
State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
ESTAB   0       0       10.0.0.5:45678      192.168.1.50:443   users:(("curl",pid=9876,fd=3))

Агрегированная статистика по процессам:

ss -tnp | awk 'NR>1 {print $6}' | sort | uniq -c | sort -rn | head -10

Покажет, сколько соединений у каждого процесса. Удобно искать процессы, которые открывают слишком много сокетов.

Шпаргалка-минимум для повседневных задач:

# netstat -tulnp  →  ss -tlnp
# netstat -ulnp   →  ss -ulnp

# Что слушает
ss -tlnp

# Активные соединения
ss -tnp

# Соединения к порту
ss -t 'dport = :80'

# Число TIME_WAIT
ss -s | grep timewait

# Процесс на порту
ss -tlnp 'sport = :8080'

# Таймеры keepalive / TIME_WAIT
ss -tno