ss -tulpn is the direct replacement for netstat -tulpn, and it is already installed. netstat shipped in net-tools, a package that modern minimal systems and container images leave out on purpose — installing it is treating the symptom. Routing moved too: netstat -r is now ip route.
1. Why the command disappeared
$ clai show listening ports→ netstat -tulpnbash: line 1: netstat: command not found
net-tools has been unmaintained for years, so slim images drop it. Inside a container apt-get install net-tools often answers E: Unable to locate package net-tools — there is nothing to install, and nothing to miss: ss comes from iproute2, which is already there.
2. The direct replacement for netstat -tulpn
$ clai show what is listening on port 8099→ ss -tulpn 'sport = :8099'Netid State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess tcp LISTEN 0 5 127.0.0.1:8099 0.0.0.0:* users:(("python3",pid=1034062,fd=3))
The flags are the same ones you already know: -t tcp, -u udp, -l listening, -p process, -n no name resolution. What is new is 'sport = :8099' — a filter evaluated by ss itself instead of a grep over the output.
3. See who is actually connected
$ clai show connections on port 8099→ ss -tan 'dport = :8099 or sport = :8099'State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 5 127.0.0.1:8099 0.0.0.0:* TIME-WAIT 0 0 127.0.0.1:8099 127.0.0.1:51350
netstat had no filter language at all, so everything ended in a pipe to grep. Here state established, state time-wait, dport and sport combine with and and or.
4. A summary instead of netstat -s
$ clai show a summary of socket usage→ ss -sTotal: 2161TCP: 190 (estab 58, closed 108, orphaned 0, timewait 29)
The first line counts every socket on the machine, the second breaks TCP down by state. A large timewait number is normal; a large orphaned number is a reason to go look at the application.
5. netstat -r is replaced by ip, not by ss
$ clai show the routing table→ ip routedefault via 172.17.0.1 dev eth0 172.17.0.0/16 dev eth0 scope link src 172.17.0.2
Routes, interfaces and addresses all moved into ip: netstat -r is ip route, netstat -i is ip -s link, and ifconfig is ip addr. Only sockets stayed with ss.
6. The whole translation table
$ clai list the ss equivalent of every netstat flag I use→ ss -tulpn # netstat -tulpn→ ss -an # netstat -an→ ss -s # netstat -s→ ip route # netstat -r→ ip -s link # netstat -i→ ip maddr # netstat -g
Six lines cover everything most people ever typed into netstat. nstat gives the long protocol counters if ss -s is too coarse.
Gotchas
- Without root the Process column is empty for other people's processes. Your own sockets always show
users:(("name",pid=…)); everything else needssudo. An empty Process on a busy port almost always means "not your process", not "no process". - There is no continuous mode. netstat had
-cto repeat every second;ss --helplists nothing of the kind. Do the repeating outside:watch -n1 'ss -tan'. - Parentheses in a filter must be quoted.
ss -tan 'sport = :8099'works even unquoted, because the shell just passes three words through. Butss -tan ( sport = :8099 )never reaches ss at all — the shell dies withsyntax error near unexpected token '('. Quote the whole expression and stop thinking about it.
Related questions
What if I really need netstat? sudo apt install net-tools brings it back on a full system, but on slim images the package doesn't exist at all. Learning six lines of the table above is the shorter path.
How do I see bandwidth per process? ss shows connections, not speed. For throughput you need nethogs or the counters in /proc/<pid>/net/dev.
What's the shortest way to find who holds a port? ss -tulpn | grep :8099 — fine when you don't feel like recalling the filter syntax.
See also
- Check if a port is open
- Linux equivalents of the Windows commands you know
- Measure API latency with curl
CliAI writes the ss filter for you when your fingers still type netstat, and shows the command before it runs. Install it in one line.