Checking whether a Linux service is listening on the expected port confirms that it successfully bound a network socket and is ready to accept connections. This quick check helps separate application startup failures from routing, firewall, and proxy issues during troubleshooting.

The kernel maintains a socket table for TCP and UDP, including the local address, port, and current state. The ss utility queries this table and can show listener details plus the owning process when sufficient privileges are available.

Listening status does not guarantee end-to-end reachability because a service can bind only to 127.0.0.1/::1, listen on IPv6 only, or be blocked by host firewall rules. Socket-activated services can appear as owned by systemd until the first connection, and administrative privileges are typically required to display process names reliably.

Steps to check if a Linux service is listening on a port with ss and nc:

  1. List all listening sockets with process ownership.
    $ sudo ss --listening --tcp --udp --numeric --processes | head -n 12
    Netid State  Recv-Q Send-Q Local Address:Port  Peer Address:PortProcess
    udp   UNCONN 0      0            0.0.0.0:48814      0.0.0.0:*    users:(("avahi-daemon",pid=871,fd=14))
    udp   UNCONN 0      0         127.0.0.54:53         0.0.0.0:*    users:(("systemd-resolve",pid=604,fd=16))
    ##### snipped #####
    tcp   LISTEN 0      5          127.0.0.1:9000       0.0.0.0:*    users:(("python3",pid=150533,fd=3))

    LISTEN indicates a TCP listener, and UNCONN is a common state for UDP sockets.

  2. Filter for the expected port to confirm the service is bound.
    $ sudo ss --listening --tcp --udp --numeric --processes | grep ':9000 '
    tcp   LISTEN 0      5          127.0.0.1:9000       0.0.0.0:*    users:(("python3",pid=150533,fd=3))

    A bind on 0.0.0.0 or [::] listens on all interfaces, while 127.0.0.1 or ::1 limits access to the local host.

  3. Test a local TCP connection to the port.
    $ nc -vz 127.0.0.1 9000
    Connection to 127.0.0.1 9000 port [tcp/*] succeeded!

    A successful TCP connect proves only that the port accepts a handshake, and protocol-level checks may still be required for full service validation.