On Linux, almost everything is a file: regular files, directories, sockets, pipes, devices. lsof (list open files) shows which processes have which of them open. That answers questions like “what’s listening on port 8080?”, “why can’t I unmount this disk?” and “why didn’t deleting that log free any space?”.
Install it if needed (sudo apt install lsof), and run it with sudo to see every process.
Who uses this port?
sudo lsof -i :80
sudo lsof -i :3306
sudo lsof -i TCP:8000-8100 # a port range
sudo lsof -iUDP:51820
Output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 812 root 6u IPv4 23741 0t0 TCP *:http (LISTEN)
nginx 813 www-data 6u IPv4 23741 0t0 TCP *:http (LISTEN)
Add -P (numeric ports) and -n (no DNS lookups) — faster and clearer:
sudo lsof -nP -i :443
All network connections
sudo lsof -nP -i # everything
sudo lsof -nP -iTCP -sTCP:LISTEN # listening TCP sockets only
sudo lsof -nP -iTCP -sTCP:ESTABLISHED # active connections
sudo lsof -nP -i @203.0.113.5 # connections to/from an IP
For a quick list of listening ports, ss is faster; lsof is great when you want everything about one process.
What does a process have open?
sudo lsof -p 1234
sudo lsof -p 1234 -i # only its network sockets
sudo lsof -c nginx # by command name
sudo lsof -u www-data # by user
Count open files per process — useful when you hit “Too many open files”:
sudo lsof -n | awk '{print $2, $1}' | sort | uniq -c | sort -rn | head
Compare with the limit: cat /proc/<PID>/limits | grep "open files". See ulimit and open files.
Who has this file or directory open?
sudo lsof /var/log/nginx/access.log
sudo lsof +D /var/www/uploads # anything open under a directory (recursive, slow on big trees)
sudo lsof /mnt/backup # why "target is busy" on umount
umount: /mnt/backup: target is busy is answered immediately — often a shell whose current directory is inside the mount. fuser -vm /mnt/backup gives a compact view too.
Deleted files still using space
The classic disk mystery: you deleted a big log, but df still shows the disk full. The process writing to it still holds it open, so the space isn’t released:
sudo lsof +L1
sudo lsof -nP +L1 | grep deleted
+L1 lists files with a link count below 1 — deleted but open. Fix by restarting the process, or truncate through /proc:
sudo truncate -s 0 /proc/<PID>/fd/<FD>
(FD is the number in the FD column, without the letter.) More in disk full troubleshooting.
Recover a deleted file
As long as a process still has it open, you can copy the contents back:
sudo lsof -nP +L1 | grep important.db
sudo cp /proc/<PID>/fd/<FD> /root/important.db.recovered
Do it before the process exits.
Reading the FD column
| FD | Meaning |
|---|---|
cwd |
Current working directory |
rtd |
Root directory |
txt |
Program code |
mem |
Memory-mapped file (libraries) |
0u, 1w, 2w |
File descriptor number + mode: r read, w write, u read/write |
Combining options
lsof combines options with OR by default. Use -a for AND:
sudo lsof -a -u www-data -i # network files of www-data only
sudo lsof -a -p 1234 -d cwd # just the working directory of PID 1234
Repeat mode
sudo lsof -nP -i :443 -r 2 # refresh every 2 seconds
Quick reference
| Question | Command |
|---|---|
| Who uses port 80? | lsof -nP -i :80 |
| Listening ports | lsof -nP -iTCP -sTCP:LISTEN |
| Files of a process | lsof -p PID |
| Files of a user | lsof -u USER |
| Who has this file open? | lsof /path/file |
| Why is the mount busy? | lsof /mount/point |
| Deleted-but-open files | lsof +L1 |
| AND conditions | -a |
Related: check open ports, ps and kill a process.