When debugging a server problem, you may need to know which ports a specific process opened - or which process is listening on a specific port. There are many ways to do this, using different tools. It may be useful to know more than one, because you may not have every tool available (specially in containerized environments).
Checking if a port is open
The first step is checking if a port is open. The easiest way to do this is using netcat
. In this example, there’s an HTTP server running on port 8000:
$ nc -zv localhost 8000
Connection to localhost 8000 port [tcp/*] succeeded!
$ nc -zv localhost 8001
nc: connect to localhost port 8001 (tcp) failed: Connection refused
You can also add a -u
flag to check UDP ports.
Another tool you can use to check for open ports is telnet
:
$ telnet localhost 8000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
^]
telnet> quit
Connection closed.
$ telnet localhost 8001
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
Telnet can’t be used to test UDP ports.
Testing HTTP ports
In the specific case of an HTTP server, you can use curl
to make requests - -v
flags makes the output verbose:
$ curl -v localhost:8000/check
* Trying 127.0.0.1:8000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /check HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.65.3
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 2
< ETag: W/"2-4KoCHiHd29bYzs7HHpz1ZA"
< Date: Fri, 13 Sep 2019 21:11:22 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
OK
When the port isn’t open, you get a Connection refused
message:
$ curl -v localhost:8001/check
* Trying 127.0.0.1:8001...
* TCP_NODELAY set
* connect to 127.0.0.1 port 8001 failed: Connection refused
* Failed to connect to localhost port 8001: Connection refused
* Closing connection 0
curl: (7) Failed to connect to localhost port 8001: Connection refused
You can also make this same request with telnet
, if curl
is unavailable:
$ telnet localhost 8000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /check
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 2
ETag: W/"2-4KoCHiHd29bYzs7HHpz1ZA"
Date: Fri, 13 Sep 2019 21:16:53 GMT
Connection: close
OKConnection closed by foreign host.
Checking open ports by process
Sometimes you need to check which ports a specific process is listening to. First you need to find out the process id (pid) using ps
:
$ ps aux | grep python
ggarnier 8762 0.6 0.0 94900 14928 pts/2 S+ 17:31 0:00 python server.py
ggarnier 8789 0.0 0.0 21536 1092 pts/11 S+ 17:31 0:00 grep python
The process id is the second column - in this example it’s 8762
. Now you can use lsof
:
$ lsof -Pan -p 8762 -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 8762 ggarnier 3u IPv4 13254927 0t0 TCP *:8000 (LISTEN)
In the example above, process 8762
is listening on port TCP 8000
.
An alternative command is ss
:
$ ss -tulpn | grep "pid=8762"
tcp LISTEN 0 5 0.0.0.0:8000 0.0.0.0:* users:(("python"id=8762,fd=3))
You may need to run lsof
and ss
with sudo
if the process is owned by another user.
Checking which process is listening on a port
Finally, if a port is open and you don’t know with process did it, use lsof
:
$ lsof -i :8000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 8762 ggarnier 3u IPv4 13254927 0t0 TCP *:8000 (LISTEN)
netstat
can also be used. It doesn’t support filtering by port or process, but you can use grep
to filter its output:
$ netstat -ntlp | grep 8000
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 8762/python
In both commands, use sudo
if you aren’t the process owner.