Introduction / Why This Is Needed
lsof (List Open Files) is a powerful command-line utility in Linux that allows you to see which processes in the system have open files, directories, network sockets, devices, etc. In Unix-like systems, almost everything is a file, so this command is a primary diagnostic tool for system administrators, developers, and DevOps engineers.
You will learn to solve common problems:
- "Port 8080 is already in use, but which process is using it?"
- "I can't delete the file /tmp/app.log; it says it's in use. Who is holding it?"
- "What network connections is my application actively using?"
- "Why is a process consuming so many file descriptors?"
This guide contains specific, tested commands with explanations that you can use immediately.
Requirements / Preparation
- Access to a Linux terminal (Ubuntu, CentOS, Debian, RHEL, Fedora, etc.).
- Superuser (sudo) privileges. Many commands, especially those related to network ports and processes of other users, require administrator rights to display information correctly.
- An installed
lsofpackage. It is included by default in most distributions, but it might be missing in minimal installations.- Debian/Ubuntu:
sudo apt update && sudo apt install lsof - RHEL/CentOS/Fedora:
sudo yum install lsoforsudo dnf install lsof
- Debian/Ubuntu:
- Basic understanding of the command line and the PID (process identifier) concept.
Step-by-Step Guide
Step 1: Basic Syntax and Viewing All Open Files
Running lsof without arguments will list all open files for the current user.
lsof
Example output (simplified):
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1234 user cwd DIR 8,1 4096 2 /
bash 1234 user txt REG 8,1 1028096 12345 /bin/bash
bash 1234 user mem REG 8,1 1985224 67890 /lib/x86_64-linux-gnu/libc-2.31.so
...
Key columns:
COMMAND— the name of the process's executable file.PID— the process identifier.USER— the owner of the process.FD— the file descriptor (cwd — current directory, txt — executable code, mem — memory-mapped region).TYPE— the file type (REG — regular file, DIR — directory, CHR — character device, IPv4/IPv6 — network socket).NAME— the path to the file or socket information.
For a complete system-wide view (all users), use sudo:
sudo lsof
Step 2: Finding Processes That Opened a Specific File or Directory
This is the most common task: "Who is using this file?"
For a single file:
lsof /path/to/file.log
Example: lsof /var/log/syslog
Recursive search in a directory (all files inside):
lsof +D /home/user/documents/
⚠️ Important: The +D option can work very slowly on large directories, as it checks every subdirectory. For a quick check of a specific file, use the first method.
Step 3: Finding a Process by Its PID (What a Process Has Opened)
If you know a process's PID (e.g., 5678), see what resources it uses:
lsof -p 5678
You can specify multiple PIDs separated by commas: lsof -p 5678,9012.
This is useful for analyzing a running daemon, container, or suspicious process.
Step 4: Finding the Process Listening on a Network Port
The classic task: "Port 3000 is in use, which process is listening on it?"
sudo lsof -i :3000
Example output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 4321 user 20u IPv6 123456 0t0 TCP *:3000 (LISTEN)
Here you can see that port 3000 is being listened to by the node (Node.js) process with PID 4321.
Search by service name/port (if the port is known, e.g., 80 for HTTP):
sudo lsof -i :http
# or
sudo lsof -i :80
Step 5: Advanced Filtering of Network Connections
The -i option combinations allow for fine-tuning filters.
TCP connections only:
sudo lsof -i tcp
UDP sockets only:
sudo lsof -i udp
Connections in LISTEN state (listening ports):
sudo lsof -i -s tcp:listen
The -s option allows filtering by connection state (established, listen, close_wait, etc.).
Connections from or to a specific IP address:
# All connections from remote address 192.168.1.100
sudo lsof -i @192.168.1.100
# All connections on local interface 192.168.1.5:80
sudo lsof -i @192.168.1.5:80
Step 6: Finding Files Opened by a Specific User
To see all files opened by the apache or www-data user:
sudo lsof -u apache
You can specify multiple users: lsof -u user1,user2.
Step 7: Combining Filters (Logical AND)
Filters in lsof are combined using AND (logical multiplication) by default. This is very powerful.
Example: Find all TCP connections (-i tcp) that are listening (-s tcp:listen) and belong to a process named nginx (-c nginx).
sudo lsof -i tcp -s tcp:listen -c nginx
Where:
-c <command>— filters by the first characters of the command name (you can use^nginxfor an exact match from the start of the string).
Another example: What files does the postgres user open in the /var/lib/postgresql directory?
sudo lsof -u postgres +D /var/lib/postgresql
Step 8: Useful Options for Convenient Output
-n— do not convert IP addresses to hostnames (speeds up output).-P— do not convert port numbers to service names (shows port 80 instead of http).-F— output in a script-friendly format (each line is a field, prefixed with an identifier character).-t— output only PIDs (useful for piping to other commands likekill).
Example of a fast and clean check of listening ports:
sudo lsof -i -s tcp:listen -n -P
Step 9: Practical Example — Stopping a Process Blocking a Port
Suppose you start a web server on port 8080 and get an Address already in use error.
- Find the culprit:
sudo lsof -i :8080
In the output, look for thePID(e.g., 12345) andCOMMAND(e.g.,java). - Stop the process (if it's not a critical service):
sudo kill 12345
If the process does not respond toSIGTERM(a normalkill), use force termination:sudo kill -9 12345 - Restart your server. The port should now be free.
Step 10: Finding File Descriptor Leaks
If a process (especially a long-running one) opens many files and doesn't close them, it can lead to exhausting the system's limit (Too many open files).
- See how many descriptors a process has open:
lsof -p <PID> | wc -l
(TheCOMMANDline is also counted, but this is sufficient for an order-of-magnitude estimate). - See the top processes by number of open files:
sudo lsof | awk '{print $2}' | sort | uniq -c | sort -nr | head -20
This command:awk '{print $2}'— extracts the second column (PID).sort | uniq -c— counts occurrences of each PID.sort -nr— sorts by descending count.head -20— shows the top 20.
Verifying the Result
After running any lsof command, check that the output contains the expected data:
- For a file search: The
NAMEcolumn should show your path. - For a port search: The
NAMEcolumn should show*:portorIP:port, andTYPEshould beIPv4orIPv6. - For a PID search: The specified PID should be present in the list.
If the output is empty, it means the corresponding resources are not open (the file is not in use, the port is not being listened on) or you ran the command without sudo and cannot see other users' processes.
Common Issues
Issue 1: lsof: command not found
Cause: The package is not installed. Solution: Install it using your distribution's package manager (see Requirements).
Issue 2: Empty output when searching for a port (sudo lsof -i :80 shows nothing)
Cause 1: No process is actually listening on that port. The port is free.
Cause 2: You are searching for an IPv6 port, but the process is listening on IPv4 (or vice versa). Try sudo lsof -i -P -n | grep :80 for a general search.
Cause 3: The port is in a TIME_WAIT state (a closed connection that hasn't fully released yet). lsof does not show such sockets by default. Use netstat -an | grep :80 or ss -ltnp for a more complete picture.
Issue 3: permission denied or insufficient privileges
Cause: You are trying to view open files for a process owned by another user (especially root) without sudo.
Solution: Always use sudo for a system-wide view: sudo lsof.
Issue 4: The lsof command runs very slowly
Cause: Using the +D option on a large directory or filtering by a complex pattern.
Solution:
- Avoid
+Don root directories (/,/home). Search for specific files. - Use more precise filters (
-p,-u,-c) to reduce the volume of data processed. - Add
-nand-Pto disable name resolution (speeds up execution).
Issue 5: Cannot delete a file, even though lsof doesn't show it being used
Cause 1: The file is deleted but still open by a process. In lsof, such a file will appear with (deleted) at the end of the NAME line. The process continues writing to this already deleted file descriptor, occupying disk space.
Solution: Stop the process (kill) that holds the descriptor. Disk space will be freed automatically after the process terminates.
Cause 2: The file is used by the kernel (e.g., as a swap file or the root of a mounted filesystem). lsof might not show such system-level usage. Use fuser -v /path/to/file or lsof /path/to/file | grep -v '(deleted)' for cleaner output.