How to Check Listening Ports in Linux: ss, netstat, lsof

When troubleshooting network connectivity or application-specific issues, one of the first things to check is what ports are actually in use on your system and which application is listening on a specific port.
This article explains how to use the ss command
, netstat, and the lsof command
to find out which services are listening on which ports. The example output comes from an Ubuntu 26.04 server running SSH, Apache, and MySQL, but the commands work the same way on any modern distribution.
What is a Listening Port
A network port is identified by its number, the associated IP address, and the type of the communication protocol, such as TCP or UDP.
The IP address matters as much as the port number. A service bound to localhost
at 127.0.0.1 accepts connections only from the same machine, while one bound to 0.0.0.0 listens on every IPv4 interface. Firewall and routing rules still determine whether remote clients can reach it.
A listening port is a network port on which an application or process listens, acting as a communication endpoint.
A local listening socket does not guarantee that the port is reachable from another host. A firewall can allow or block traffic to it, and a network scan may report the port as open, closed, or filtered. In general terms, an open port accepts incoming packets from the system running the scan.
Normally, two services cannot independently bind to the same port, protocol, and IP address.
For example, if you are running an Apache web server that listens on ports 80 and 443 and you try to install Nginx
, the latter will fail to start because the HTTP and HTTPS ports are already in use.
Check Listening Ports with ss
ss is the modern replacement for netstat. It is faster, provides more detailed TCP state information, and is installed by default on all modern Linux distributions.
To get a list of all listening ports with ss, type:
sudo ss -tunlpThe options used in this command have the following meaning:
-t- Show TCP ports.-u- Show UDP ports.-n- Show numerical addresses instead of resolving hosts.-l- Show only listening ports.-p- Show the process using the socket. Run the command as root or with sudo to see sockets owned by other users.
The output will look something like this:
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=499,fd=18))
udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=499,fd=16))
udp UNCONN 0 0 10.0.2.15%enp0s1:68 0.0.0.0:* users:(("systemd-network",pid=988,fd=33))
udp UNCONN 0 0 127.0.0.1:323 0.0.0.0:* users:(("chronyd",pid=1208,fd=4))
udp UNCONN 0 0 [::1]:323 [::]:* users:(("chronyd",pid=1208,fd=5))
tcp LISTEN 0 151 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=3671,fd=22))
tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=499,fd=17))
tcp LISTEN 0 70 127.0.0.1:33060 0.0.0.0:* users:(("mysqld",pid=3671,fd=19))
tcp LISTEN 0 4096 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=499,fd=19))
tcp LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1309,fd=3),("systemd",pid=1,fd=358))
tcp LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=1309,fd=4),("systemd",pid=1,fd=359))
tcp LISTEN 0 511 *:80 *:* users:(("apache2",pid=4387,fd=4),("apache2",pid=4386,fd=4),("apache2",pid=4370,fd=4))The important columns are:
Netid- The socket type,tcporudp.State- The socket state.LISTENmeans a TCP port is waiting for incoming connections. UDP is connectionless and never enters theLISTENstate, so a UDP service waiting for datagrams showsUNCONN.Local Address:Port- The IP address and port number the process listens on.Process- The name, PID, and file descriptor of each process using the socket.
The local address shows which addresses and interfaces the service is bound to. In the output above, MySQL listens on 127.0.0.1:3306, so only programs on the same machine can connect to it. SSH listens on 0.0.0.0:22 (all IPv4 interfaces) and [::]:22 (all IPv6 interfaces). On this server, Apache shows *:80 for a dual-stack socket that accepts both IPv4 and IPv6 connections. A suffix such as %lo means the socket is bound to one network interface only.
You may also notice that port 22 lists two processes, sshd and systemd with PID 1. Recent Ubuntu releases start SSH through systemd socket activation: systemd opens the listening socket and passes it to sshd, so both processes hold the same socket. This is expected and does not mean that two services are fighting over the port.
To filter the results, you can pipe the output through grep
. For example, to find what process listens on TCP port 22:
sudo ss -tnlp | grep :22The matching sockets are:
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1309,fd=3),("systemd",pid=1,fd=358))
LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=1309,fd=4),("systemd",pid=1,fd=359))The ss command also has built-in filtering, which is faster than piping through grep:
sudo ss -tlnp sport = :22The exact port filter returns the same two SSH sockets:
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1309,fd=3),("systemd",pid=1,fd=358))
LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=1309,fd=4),("systemd",pid=1,fd=359))Unlike grep :22, the sport = :22 expression matches the local port exactly, so it does not also return ports such as 2222.
You can also filter by state, source address, or destination address. For example, to show all connections in the ESTABLISHED state:
ss -tn state establishedOn this server, one SSH connection is established:
Recv-Q Send-Q Local Address:Port Peer Address:Port
0 0 10.0.2.15:22 10.0.2.2:54758The State column is gone because every row is in the same state. Here, the only established connection is the SSH session from 10.0.2.2.
Check Listening Ports with netstat
netstat
is a legacy command-line tool that provides information about network connections. On modern Linux distributions, netstat is not installed by default. It is part of the net-tools package, which you can install with:
# Ubuntu, Debian, and derivatives
sudo apt install net-tools
# Fedora, RHEL, and derivatives
sudo dnf install net-toolsTo list all TCP or UDP ports that are listening, including the services using the ports and the socket status:
sudo netstat -tunlpThe options are the same as with ss:
-t- Show TCP ports.-u- Show UDP ports.-n- Show numerical addresses instead of resolving hosts.-l- Show only listening ports.-p- Show the PID and name of the listener’s process. Run the command as root or with sudo to see sockets owned by other users.
The output will look something like this:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 3671/mysqld
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 499/systemd-resolve
tcp 0 0 127.0.0.1:33060 0.0.0.0:* LISTEN 3671/mysqld
tcp 0 0 127.0.0.54:53 0.0.0.0:* LISTEN 499/systemd-resolve
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1/systemd
tcp6 0 0 :::22 :::* LISTEN 1/systemd
tcp6 0 0 :::80 :::* LISTEN 4370/apache2
udp 0 0 127.0.0.54:53 0.0.0.0:* 499/systemd-resolve
udp 0 0 127.0.0.53:53 0.0.0.0:* 499/systemd-resolve
udp 0 0 10.0.2.15:68 0.0.0.0:* 988/systemd-network
udp 0 0 127.0.0.1:323 0.0.0.0:* 1208/chronyd
udp6 0 0 ::1:323 :::* 1208/chronydThe important columns are:
Proto- The protocol used by the socket.Local Address- The IP address and port number the process listens on.PID/Program name- The PID and the name of the process.
Compare this with the ss output. netstat prints only one process per socket, so port 22 shows 1/systemd instead of sshd, and Apache shows a single apache2 process instead of all three. The State column is empty for UDP sockets, and Apache appears only as tcp6 on :::80, even though that socket also accepts IPv4 connections.
To find what process listens on a specific port, for example TCP port 22:
sudo netstat -tnlp | grep :22The matching entries are:
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1/systemd
tcp6 0 0 :::22 :::* LISTEN 1/systemdIf the output is empty, nothing is listening on that port. To test a port from another host, use netcat
.
netstat is obsolete and replaced with ss and ip
, but it is still one of the most used commands for checking network connections.
Check Listening Ports with lsof
lsof is a powerful command-line utility that provides information about files opened by processes.
In Linux, everything is a file. You can think of a socket as a file that writes to the network.
If lsof is not available on your system, install it with:
# Ubuntu, Debian, and derivatives
sudo apt install lsof
# Fedora, RHEL, and derivatives
sudo dnf install lsofTo get a list of all listening TCP ports with lsof, type:
sudo lsof -nP -iTCP -sTCP:LISTENThe options used are as follows:
-n- Do not resolve hostnames, show numerical addresses.-P- Do not convert port numbers to port names.-iTCP -sTCP:LISTEN- Show only network files with TCP state LISTEN.
The output lists each process that holds a listening TCP socket:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 358u IPv4 18858 0t0 TCP *:22 (LISTEN)
systemd 1 root 359u IPv6 18860 0t0 TCP *:22 (LISTEN)
systemd-r 499 systemd-resolve 17u IPv4 10129 0t0 TCP 127.0.0.53:53 (LISTEN)
systemd-r 499 systemd-resolve 19u IPv4 10131 0t0 TCP 127.0.0.54:53 (LISTEN)
sshd 1309 root 3u IPv4 18858 0t0 TCP *:22 (LISTEN)
sshd 1309 root 4u IPv6 18860 0t0 TCP *:22 (LISTEN)
mysqld 3671 mysql 19u IPv4 27468 0t0 TCP 127.0.0.1:33060 (LISTEN)
mysqld 3671 mysql 22u IPv4 31568 0t0 TCP 127.0.0.1:3306 (LISTEN)
apache2 4370 root 4u IPv6 32272 0t0 TCP *:80 (LISTEN)
apache2 4386 www-data 4u IPv6 32272 0t0 TCP *:80 (LISTEN)
apache2 4387 www-data 4u IPv6 32272 0t0 TCP *:80 (LISTEN)Most of the output column names are self-explanatory:
COMMAND,PID,USER- The name, the PID, and the user running the program associated with the port.lsofshortens long command names, sosystemd-resolveappears assystemd-r.NAME- The address and port the socket is bound to, followed by the TCP state. An asterisk (*) means the socket listens on all interfaces.
Like ss, lsof shows both systemd and sshd on port 22, and each Apache process on its own line. The USER column shows that the Apache parent process runs as root, while its workers run as www-data.
The quickest way to check a single port with lsof is the -i :PORT form. The following command shows every process that has port 80 open:
sudo lsof -i :80On the example server, the result is:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
apache2 4370 root 4u IPv6 32272 0t0 TCP *:http (LISTEN)
apache2 4386 www-data 4u IPv6 32272 0t0 TCP *:http (LISTEN)
apache2 4387 www-data 4u IPv6 32272 0t0 TCP *:http (LISTEN)Without -P, lsof translates the port number into its service name from /etc/services, which is why the NAME column shows http instead of 80. The -i :80 form matches TCP and UDP sockets in any state, so on a busy web server it also lists established connections to and from port 80.
To find only the process listening on a particular port, for example port 3306, add the protocol and the state filter:
sudo lsof -nP -iTCP:3306 -sTCP:LISTENThe output shows that the MySQL server uses port 3306 and accepts connections only on 127.0.0.1:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 3671 mysql 22u IPv4 31568 0t0 TCP 127.0.0.1:3306 (LISTEN)UDP sockets have no LISTEN state, so drop the -s filter when you look for UDP services:
sudo lsof -nP -iUDPFor more information, visit the lsof man page and read about all other powerful options of this tool.
Common Mistakes
- Forgetting
sudo. Without root privileges, the-pflag will not show the process name or PID for ports owned by other users. The port will appear in the output, but the process column will be empty. Depending on howlsofwas built and the system security settings, its non-root output may also be limited to your own processes. - Confusing listening and established connections. The
-lflag shows only listening ports. Without it,ssandnetstatshow all connections, including established ones. If you only care about what services are running, always use-l. - Looking for UDP services in the
LISTENstate. UDP sockets showUNCONNinssand an empty state innetstat. Filtering the output withgrep LISTENhides every UDP socket, such as the chronyd monitoring port used bychronycon 323. - Searching for a port without the colon. When using
grepto filter by port, always include the colon (e.g.,grep :22). Searching for just22will also match PIDs, addresses, and other numbers that contain22.
Quick Reference
For printable quick references, see the ss cheatsheet , netstat cheatsheet , and lsof cheatsheet .
| Task | Command |
|---|---|
| List all listening ports | sudo ss -tunlp |
| List listening UDP ports | sudo ss -unlp |
| List all listening ports (netstat) | sudo netstat -tunlp |
| Find process on a specific port | sudo ss -tlnp sport = :80 |
| Find process on a specific port (grep) | sudo ss -tnlp | grep :80 |
| Find processes using port 80 (lsof) | sudo lsof -i :80 |
| List listening TCP ports (lsof) | sudo lsof -nP -iTCP -sTCP:LISTEN |
| Find process on port 3306 (lsof) | sudo lsof -nP -iTCP:3306 -sTCP:LISTEN |
| Show established connections | ss -tn state established |
| Show all connections with process info | sudo ss -tunp |
FAQ
What is the difference between ss and netstat?
Both show network connection information. ss is the modern replacement. It is faster, provides more TCP state details, and is installed by default on modern Linux distributions. netstat requires the net-tools package and is considered obsolete.
Why is the process column empty in the output?
You can generally see process information for sockets owned by your account. Run the command as root or with sudo to see details for sockets owned by other users. Some systems may impose additional restrictions on lsof output.
How do I check if a specific port is open from a remote machine?
The commands in this article check listening ports on the local system. To test whether a port is reachable from a remote machine, use netcat
(nc -zv host port) or nmap.
Can two services listen on the same port?
Not normally. Two services cannot independently bind to the same port, protocol, and IP address simultaneously. The SO_REUSEPORT socket option lets processes that all opt in share a port for load balancing, while socket activation can pass one listener from systemd to a service such as sshd. Otherwise, a service trying to claim an address that is already in use will fail. To trace that error back to the process holding the port, see the guide on how to find which process is using a port
.
Conclusion
The ss command is the standard choice for checking listening ports, while lsof provides a process-focused view and netstat remains available on older systems. For details beyond these common tasks, open the local manuals with man ss, man netstat, or man lsof.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

Dejan Panovski
Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page