KB
Monitoring & Troubleshooting

Understanding lsof: Linux Open Files and Network Connections

5 min read950 words21 code blocks

At a glance#

  • Purpose: Reference for using lsof to inspect open files, network connections and listening ports.
  • Applies to: Any Linux or Unix-like system.
  • Risk: None — read-only diagnostics.
  • Time: Reference article, no fixed duration.

Overview#

lsof stands for list open files. On Unix-like systems almost everything is represented as a file — regular files, directories, sockets, pipes, devices — so a tool that lists open files ends up being one of the most useful diagnostic commands available.

It answers questions that come up constantly during incidents:

  • What is holding port 443 open?
  • Why can I not unmount this filesystem?
  • The disk is full but du disagrees with df — what is holding the space?
  • Which files is this runaway process touching?
Note: lsof needs root to see files opened by other users' processes. Without sudo it silently shows only your own, which can be very misleading during troubleshooting. Use sudo by default.

Network connections#

List all network connections#

bash
sudo lsof -P -i -n
FlagMeaning
-PShow port numbers rather than service names (443 not https)
-iNetwork connections only
-nDo not resolve IPs to hostnames — much faster, and works when DNS is broken

Using -P and -n together is the habit worth forming. Both avoid lookups that can hang for seconds when a system is already unhealthy.

Find what is using a specific port#

The most common use of the command. When a service will not start because the port is taken:

bash
sudo lsof -i tcp:443
bash
sudo lsof -i :8080

Show only listening ports#

bash
sudo lsof -i -P -n | grep LISTEN

Formatted into aligned columns, IPv4 only:

bash
sudo lsof -Pni4 | grep LISTEN | column -t

Connections for one process#

bash
sudo lsof -i -a -p 1234

The -a flag means AND rather than the default OR. Without it, lsof shows network connections or anything belonging to PID 1234, which is rarely what you want.

Files and processes#

All files opened by a command#

bash
sudo lsof -c nginx

Matches by command name, so this covers every nginx worker process at once.

All files opened by a process ID#

bash
sudo lsof -p 1234

Everything a user has open#

bash
sudo lsof -u username

Restricted to a particular directory tree:

bash
sudo lsof -u username -a +D /etc

+D recurses into the directory. It is thorough but slow on large trees — +d checks only the directory itself.

What is using a mount point#

The answer to "target is busy" when unmounting:

bash
sudo lsof +D /mnt/data

Or by device:

bash
sudo lsof /dev/sdb1

A process's current working directory#

bash
sudo lsof -p 1234 | grep cwd

Useful when a process is writing to a relative path and you need to know where that actually is.

Disk space investigation#

Deleted files still holding space#

This is the classic case where df reports a full disk but du cannot account for it. A process still holds an open handle to a file that has been deleted, so the space is not released until that process closes it or exits.

bash
sudo lsof | grep deleted

Or scoped to one filesystem:

bash
sudo lsof +L1

+L1 lists files with a link count below 1 — deleted but still open.

Once identified, restart the owning process to release the space. Truncating the file in place also works without a restart:

bash
sudo truncate -s 0 /proc/<PID>/fd/<FD>

Largest open files#

bash
sudo lsof / | awk '{ if($7 > 1048576) print $7/1048576 "MB", $9, $1 }' | sort -n -u | tail | column -t

Common options reference#

OptionDescription
-iNetwork connections; can be narrowed with -i tcp:443
-PNumeric port numbers instead of service names
-nDo not resolve hostnames
-pFilter by process ID
-uFilter by username
-cFilter by command name
-aCombine filters with AND instead of OR
+DRecurse into a directory
+L1Show deleted files still held open
-tOutput PIDs only — useful for piping into kill

Reading the output#

text
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
nginx    1234  root    6u  IPv4  28371      0t0    TCP *:443 (LISTEN)
ColumnMeaning
COMMANDProcess name
PIDProcess ID
USEROwning user
FDFile descriptor. cwd = working directory, txt = program text, mem = memory-mapped, a number = an open handle
TYPEREG regular file, DIR directory, IPv4/IPv6 socket, FIFO pipe
NAMEPath, or address and port for sockets

In the FD column, the suffix indicates access mode: r read, w write, u read and write.

Practical recipes#

Kill everything using a mount point so it can be unmounted:

bash
sudo lsof -t +D /mnt/data | xargs -r sudo kill
Warning: This terminates processes without warning. Review the list with sudo lsof +D /mnt/data first.

Confirm which process to blame for a port conflict:

bash
sudo lsof -i :80 -P -n | grep LISTEN

Watch a process open files in real time:

bash
watch -n1 "sudo lsof -p 1234 | wc -l"

A steadily climbing count usually means a file descriptor leak.

Alternatives#

ToolBetter for
ss -tulpnFaster for sockets alone; the modern replacement for netstat
fuser -v /pathQuickly identifying processes using one file or mount
netstat -tulpnDeprecated; still common in older documentation

lsof remains the most complete of these because it covers files and sockets together.