The “Device or Resource Busy” Frustration
We’ve all been there. You try to unmount a drive, delete a massive log, or restart Nginx, only to get hit with a “Device or resource busy” or “Address already in use” error. Linux is famous for treating everything as a file—from your hard drive to your network sockets. But when something is locked, the OS doesn’t always tell you which process is the culprit. That is where lsof (List Open Files) comes in.
On a production Ubuntu 22.04 server running 12 microservices, I used lsof to solve a recurring deployment hang. It cut our troubleshooting time from 20 minutes of guessing down to 30 seconds of precision. Instead of blindly killing processes, we could see exactly which Python script was hanging onto a socket. It is the ultimate “who is doing what” tool for any sysadmin.
Quick Start: The 5-Minute lsof Essentials
If you need to fix a problem right now, these are the commands you will use 90% of the time. Remember to use sudo, or you won’t see processes owned by other users.
1. Find what process is using a specific port
This is a lifesaver when a web server fails to start. If port 80 is taken, run this to find the squatter:
sudo lsof -i :80
2. List files opened by a specific user
To see every file the ‘www-data’ user is currently touching:
sudo lsof -u www-data
3. See what a specific process is doing
If you have a Process ID (PID) like 1234 and want to see its activity:
sudo lsof -p 1234
4. Check a specific directory
Trying to unmount /mnt/data? This command shows you who is blocking the exit:
sudo lsof +D /mnt/data
Decoding the lsof Output
Running lsof without arguments spits out a wall of text. To find the needle in the haystack, you need to know what these columns mean:
- COMMAND: The name of the app or script.
- PID: The unique ID of the process.
- USER: Who owns the process.
- FD: The File Descriptor. Look for
cwd(current directory) ortxt(the actual code being run). - TYPE:
REGis a normal file,DIRis a folder, andIPv4/IPv6are network connections. - NAME: The path to the file or the IP address involved.
When I first checked this on a busy database server, I saw thousands of mem entries. Don’t panic. These are just shared libraries mapped into memory. It is normal for a single app to show dozens of these.
Advanced Troubleshooting: Network and Disk Space
Once you learn the basics, you can use lsof for more complex tasks like forensic analysis or cleaning up “ghost” files.
Filtering Network Connections
You can filter by protocol to find specific types of traffic. This is helpful for spotting unauthorized connections or debugging stuck sync jobs.
# List only TCP connections
sudo lsof -i tcp
# Find connections to a specific remote server
sudo lsof -i @192.168.1.50
Recovering “Ghost” Disk Space
Have you ever deleted a 50GB log file with rm, but df -h still shows the disk is full? This happens because a process still has that file open. The file is “deleted” but the space isn’t freed until the process lets go.
Find these hidden space-hogs with:
sudo lsof +L1
The +L1 flag finds files with a link count of zero. Once you find the PID, restart that service to finally reclaim your disk space.
Combining Filters with -a
By default, lsof uses “OR” logic. If you want to find files opened by user ‘john’ AND specifically on port 22, you must use the -a (AND) flag:
sudo lsof -a -u john -i :22
Practical Tips for Modern Admins
1. Speed Up Results
By default, lsof tries to turn IP addresses into hostnames. This is slow. On a busy network, the command might hang for seconds. Use -n to skip DNS and -P to skip port names:
sudo lsof -nP -i :443
2. Scripting and Automation
If you need to kill whatever is blocking a port during a CI/CD pipeline, use the -t (terse) flag. It returns only the PID, which is perfect for piping into other commands.
# Force-kill whatever is using port 3000
sudo kill -9 $(lsof -t -i :3000)
Use this sparingly. It is a heavy-handed approach, but sometimes it is the only way to clear a stuck deployment.
3. Real-Time Monitoring
You can watch a file or port in real-time using the -r flag. This is great for watching a log file grow or waiting for a specific connection to land.
# Check every 2 seconds for new connections on port 80
sudo lsof -i :80 -r 2
Summary
Learning lsof changes how you manage Linux. Instead of rebooting and hoping for the best, you can pinpoint the exact process causing a conflict. Whether you are hunting down a 100GB ghost log or finding out why a dev port is hijacked, lsof provides the clarity you need. Keep these commands handy, and you will never be intimidated by a “Resource busy” error again.

