ss — Inspect sockets — modern netstat replacement, faster on Linux across all 5 shells
Equivalents in every shell
ss -tulnFrom `iproute2`. Flags: `-t` TCP, `-u` UDP, `-l` listening only, `-n` numeric (no DNS), `-p` show process holding the socket (needs root for other users' sockets). Common combos: `ss -tunlp` (everything listening, with PIDs), `ss -tn state established` (established TCP only), `ss dst :443` (filter by destination port). Way faster than `netstat` because it talks to the kernel via netlink instead of parsing `/proc/net/tcp`.
ss -tulnSame `iproute2` binary. NOT on macOS — macOS still uses `netstat`. macOS-equivalent for "what is listening": `netstat -an | grep LISTEN` or `lsof -iTCP -sTCP:LISTEN -P -n`. `lsof` on macOS is the closest to `ss -tunlp` (sockets + process binding).
ss -tulnSame external. Fish has decent completion for `ss` — TAB after `ss state ` lists every TCP state (`established`, `syn-sent`, `syn-recv`, `fin-wait-1`, etc). Useful idiom: `ss -tn state established | wc -l` for "how many active TCP connections do I have right now?"
Get-NetTCPConnectionPowerShell's socket-listing cmdlet — Windows-only. `Get-NetTCPConnection -State Listen` for just listeners; `Get-NetUDPEndpoint` for UDP. Join with `Get-Process` for owning-process info: `Get-NetTCPConnection -State Listen | Select LocalPort, OwningProcess, @{n="Process";e={(Get-Process -Id $_.OwningProcess).ProcessName}}`. No `netstat`-style summary mode out of the box.
netstat -ano`netstat -ano` is the universal Windows answer — `-a` all sockets, `-n` numeric, `-o` show owning PID. `netstat -anob` adds the EXE name (requires admin). For listeners only: `netstat -ano | findstr LISTENING`. Windows ships `netstat` since Windows NT 3.1; the modern PowerShell `Get-NetTCPConnection` is preferred but `netstat -ano` remains the default fallback for scripts that must work everywhere.
Worked examples
List all listening TCP/UDP sockets with owning process
sudo ss -tulnpGet-NetTCPConnection -State Listen | Select-Object LocalAddress, LocalPort, OwningProcessnetstat -anobShow only established TCP connections
ss -tn state establishedGet-NetTCPConnection -State Establishednetstat -an | findstr ESTABLISHEDFind what is using port 8080
sudo ss -tlnp sport = :8080Get-NetTCPConnection -LocalPort 8080 | Select-Object OwningProcess, @{n="Process";e={(Get-Process -Id $_.OwningProcess).ProcessName}}netstat -ano | findstr :8080Gotchas
- `ss` is LINUX-ONLY (`iproute2`). macOS and BSD ship `netstat` and `lsof` only — `ss` returns "command not found". For maximally portable Unix scripts use `lsof -iTCP -sTCP:LISTEN -P -n` which works on every Unix and outputs PID-bound socket info.
- Without root, `ss -p` (or `ss -tunlp`) suppresses process info for sockets owned by OTHER users — and silently omits the column rather than erroring. If `ss -tunlp` looks unexpectedly empty in the process column, prefix with `sudo`.
- `ss state established` filters require the WORD `state` (not just the state name). `ss established` returns no rows; `ss state established` works. Same for `ss sport = :8080` — the `= :` syntax is mandatory for the port filter form.
- PowerShell `Get-NetTCPConnection` does NOT include UDP — UDP is `Get-NetUDPEndpoint`. Cross-protocol queries need both: `(Get-NetTCPConnection) + (Get-NetUDPEndpoint)`. The two return slightly different property names too (`LocalAddress`/`LocalPort` vs `LocalAddress`/`LocalPort` — actually identical in modern PS, but they were divergent in older builds).
- cmd `netstat -ano | findstr :8080` matches ANY occurrence of `:8080` — including a connection FROM remote port 8080. Use `:8080 ` (with trailing space) to anchor to the local-port column, or `findstr "TCP.*:8080 "` for a tighter regex. PowerShell `Get-NetTCPConnection -LocalPort 8080` is unambiguous.
WSL & PowerShell Core notes
Common tasks using ss
- Find all listening ports across every network interface
List every TCP / UDP port currently accepting connections on the local host — for security audits ("what is exposed?"), firewall rule verification, troubleshooting "address already in use" errors, and inventory of running services.
- Find which process is listening on a port
Identify the PID and process name bound to a local TCP/UDP port — for debugging "address already in use" errors, auditing what's exposed, and killing a zombie server holding port 3000.
- Kill the process listening on a port
Find and terminate whatever process is bound to a TCP/UDP port — the answer to "address already in use" when a previous run did not release the socket.
- Scan a port range on a host
Check which TCP/UDP ports are open on a target host — for service discovery, firewall validation, post-deploy "is the new server reachable?" smoke tests, or troubleshooting connectivity ahead of an SSH/HTTP call that's timing out.
- Test if a network port is open
Check whether a remote (or local) TCP port is accepting connections — for service health checks, firewall debugging, or pre-flight validation in scripts.