Devin.KR
로그인

리눅스 ss 명령어 사용법 - 포트 확인과 netstat 대체 실전 예제

개발자 조회 2

이 명령어를 언제 쓰는가

애플리케이션이 Address already in use 로 뜨지 않을 때, 서비스가 8080 에 떠 있다는데 밖에서 안 붙을 때, DB 커넥션이 새고 있는 것 같을 때 ss를 친다. 소켓 상태를 커널에서 직접 읽어 어떤 포트를 누가 잡고 있고, 지금 몇 개의 연결이 어떤 상태인지 보여준다.

예전에는 netstat을 썼지만 RHEL 8 이후로는 net-tools 패키지가 기본 설치되지 않아 netstat 이 아예 없는 서버가 흔하다. 지금 리눅스에서 이 역할은 iproute2 의 ss 가 맡는다. 소켓 수가 수만 개인 서버에서는 netstat 보다 눈에 띄게 빠르다.

기본 형식

ss [옵션] [필터식]
  • 옵션 — 프로토콜(-t, -u), 상태(-l, -a), 표시 방식(-n, -p)을 고른다. 보통 묶어서 -tlnp 처럼 쓴다.
  • 필터식state established, dport = :3306 처럼 조건을 붙여 결과를 줄인다. 괄호나 공백이 들어가면 따옴표로 감싼다.

자주 쓰는 옵션

옵션의미예시
-tTCP 소켓만ss -t
-uUDP 소켓만ss -u -a
-lLISTEN 상태만ss -tl
-aLISTEN 과 연결된 소켓 모두ss -ta
-n포트·주소를 숫자로. DNS 조회를 하지 않아 빠르다ss -tn
-p소켓을 쥔 프로세스 표시(root 필요)sudo ss -tlnp
-s소켓 개수 요약ss -s
-iTCP 내부 정보(rtt, cwnd, 재전송)ss -tin
-4 / -6IPv4 / IPv6 만ss -4tlnp
-o타이머 정보(keepalive, timewait 잔여시간)ss -tno

실전 예제

1. 열려 있는 포트와 그 주인을 한 번에 본다. 서버에 처음 들어갔을 때 가장 먼저 치는 명령이다.

sudo ss -tlnp
State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
LISTEN 0      511          0.0.0.0:80         0.0.0.0:*     users:(("nginx",pid=1180,fd=6))
LISTEN 0      128        127.0.0.1:3306       0.0.0.0:*     users:(("mariadbd",pid=942,fd=22))
LISTEN 0      100          0.0.0.0:22         0.0.0.0:*     users:(("sshd",pid=810,fd=3))

Local Address 를 반드시 본다. 위 MariaDB 는 127.0.0.1:3306 이므로 다른 서버에서는 절대 붙을 수 없다. 방화벽을 아무리 열어도 안 된다. 원격 접속이 필요하면 bind-address 설정을 고쳐야 한다.

2. 포트를 이미 누가 쓰고 있는지 확인한다. 기동 실패 로그에 Address already in use 가 찍혔을 때다.

sudo ss -tlnp 'sport = :8080'

3. DB 커넥션 수를 세어 누수를 확인한다. 커넥션 풀이 반환되지 않으면 이 숫자가 계속 오른다.

ss -Htn state established '( dport = :3306 )' | wc -l

-H(헤더 생략)를 빼면 헤더 줄까지 세어 결과가 실제보다 1 크게 나온다.

어느 애플리케이션 서버가 많이 물고 있는지 보려면 상대 IP 로 집계한다.

ss -Htn state established '( sport = :3306 )' | awk '{split($4,a,":"); print a[1]}' | sort | uniq -c | sort -rn

상대 주소가 $5 가 아니라 $4 인 이유가 있다. state established 처럼 상태를 하나로 못 박으면 ss 가 State 열을 통째로 빼고 출력하기 때문이다. 반면 -l 은 내부적으로 LISTEN 과 CLOSE 두 상태를 잡아서 State 열이 남는다. 열 번호를 쓰기 전에 필터를 건 그대로 한 번 실행해 눈으로 세어본다.

4. 소켓이 어떤 상태에 몰려 있는지 요약한다. TIME-WAIT 이 수만 개면 포트 고갈을 의심한다.

ss -s
Total: 412
TCP:   1183 (estab 96, closed 1042, orphaned 0, timewait 1041)

Transport Total     IP        IPv6
RAW	  0         0         0
UDP	  8         6         2
TCP	  141       133       8

5. 특정 서버와의 연결만 추린다. 어느 백엔드와 통신이 끊겼는지 확인할 때 쓴다.

sudo ss -tnp dst 10.0.1.30

함정과 주의점

-p는 root 가 아니면 남의 프로세스를 보여주지 않는다. 일반 사용자로 ss -tlnp 를 치면 Process 칸이 비어 있어 주인 없는 포트처럼 보인다. 포트를 잡은 범인을 찾을 때는 반드시 sudo를 붙인다.

0.0.0.0:포트127.0.0.1:포트는 하늘과 땅 차이다. 전자는 모든 인터페이스에서 받고, 후자는 서버 자기 자신에서만 받는다. 서버 안에서 curl 이 되는데 밖에서 안 된다는 상황의 절반은 방화벽이 아니라 이 바인딩 주소 문제다. [::]:80 으로만 떠 있으면 IPv6 만 받고 있는 것이므로 이것도 확인한다.

필터식은 따옴표로 감싼다. ss -tn state established ( dport = :80 ) 처럼 치면 셸이 괄호를 서브셸로 해석해 문법 오류가 난다. 괄호와 공백이 있는 조건은 통째로 작은따옴표 안에 넣는다.

ss 는 리눅스 전용이다. macOS 와 BSD 에는 없다. 맥에서는 netstat -an 이나 lsof -nP -iTCP -sTCP:LISTEN 을 쓴다. 리눅스 서버용으로 짠 점검 스크립트를 맥에서 돌리면 여기서 걸린다.

함께 보면 좋은 명령어

  • lsof — 소켓뿐 아니라 그 프로세스가 연 파일까지 같이 본다. 포트 주인을 파고들 때 쓴다.
  • curl — 포트가 열려 있는 것과 애플리케이션이 정상 응답하는 것은 다른 문제다. ss 다음에 확인한다.
  • ip — 인터페이스와 라우팅을 본다. 바인딩 주소 문제를 추적할 때 함께 쓴다.