The lsof Output That Showed Who Was Holding the Port

The bind failed with the address already in use and nothing in the project was running, and the listing named a leftover process from the previous session…

Share
The lsof Output That Showed Who Was Holding the Port. Abstract tooling illustration in orange and dark grey on debugly.dev

It ended at the answer. It started at the not start. Every hand-off in between did exactly what it was told, and this is the one that lied.

This is the anatomy of the socket ownership question, and of the specific property that makes the tool decisive: the error says the port is taken and not by whom, and the listing answers the whom, which is the only question that matters.

The case was a development machine and a production container; the mechanics generalise to any Unix system where a listening socket belongs to a process.

Why the error did not say

The bind was the kernel's refusal, and the refusal was the port's state, and the state was the in use, and the in use was the fact, and the fact was the not the owner, and the not owner was the error's limit, and the limit was the API's, and the API's was the errno, and the errno was the code, and the code was the not the process, and the not process was the gap, and the gap was the tool's job.

The ps was the project's check, and the check was the absence, and the absence was the misleading, because the holder was the not the project, and the not project was the leftover, and the leftover was the previous session's, and the previous session's was the not terminated, and the not terminated was the orphan, and the orphan was the invisible to the project's view.

The listing is the kernel's table, and the table is the every open file, and the every open file is the sockets included, and the sockets included is the port's owner, and the owner is the PID and the command, and the two are the answer, and the answer is the one command.

The same question decided the sidecar that bound the app's port first, which is why the two fixes look alike.

The queries that did the work

The port's owner. The lsof with the -i and the port is the listener, and the listener is the PID and the name, and the name is the answer, and the answer is the fix's target, and the target is the kill or the config, and the two are the resolution.

The process's every socket. The lsof with the -p and the PID is the process's connections, and the connections are the behaviour, and the behaviour is the diagnosis, and the diagnosis is the fix, and the fix is the reading, and the reading is the discipline.

The deleted file still held open. The lsof shows the deleted marker, and the marker is the space's retention, and the retention is the disk's full despite the deletion, and the full is the incident, and the incident is the fix's target, and the target is the restart, and the restart is the release.

The IPv4 and the IPv6 split. The listener may be the one family only, and the family is the bind's failure on the other, and the other is the confusion, and the confusion is the fix's target, and the target is the address, and the address is the discipline, because the wildcard and the specific address are the different bindings.

The TIME_WAIT state. The state is the closed connection's residue, and the residue is the not the holder, and the not holder is the distinction, and the distinction is the fix, and the fix is the SO_REUSEADDR, and the flag is the discipline, because the TIME_WAIT does not block the listening bind when the flag is set.

The habit

Ask who holds it before changing anything. The listing is the one command, and the command is the seconds, and the seconds is the answer, and the answer is the fix, and the fix is the order, because the reboot is the minutes and the minutes is the waste.

Read the command, not only the PID. The command is the identification, and the identification is the safe kill, and the safe kill is the fix, and the fix is the confidence, and the confidence is the discipline, because the PID alone is the wrong process's risk.

Check the parent when the process is unexpected. The parent is the supervisor, and the supervisor is the restart, and the restart is the kill's futility, and the futility is the fix's target, and the target is the supervisor's stop, and the stop is the discipline.

Remember the container's namespace. The lsof inside the container is the container's view, and the view is the not the host's, and the not host's is the different table, and the table is the host's check, and the check is the discipline, because the port may be held by the proxy outside the container.

What I now do

A bind failure tells you the port is taken and not by whom, so list the open sockets for that port to get the PID and the command before changing anything. Check the parent process, distinguish TIME_WAIT from a live listener, and remember that a container sees only its own network namespace.

The development server refused to start with the address already in use and the project had no running process, and one lsof command named a node process from the previous session that had survived the terminal closing. That is the whole pattern, and it is the part worth remembering.


Published on debugly.dev by Rohit Bhadani | Founder of Krova Cloud