lsof (List Open Files) is one of the most versatile diagnostic tools on Linux. Since everything in Linux is a file — including network connections, pipes, and devices — lsof can help you find what processes are using specific files, ports, or network connections.
Installation
# Ubuntu/Debian
sudo apt install lsof
# AlmaLinux/Rocky
sudo dnf install lsof
Find What Process Is Using a Port
# Find what is listening on port 80
sudo lsof -i :80
# Example output:
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# nginx 1234 root 6u IPv4 12345 0t0 TCP *:http (LISTEN)
# nginx 1235 www-data 6u IPv4 12345 0t0 TCP *:http (LISTEN)
# Find what is using port 3306 (MySQL)
sudo lsof -i :3306
# Find all listening TCP ports
sudo lsof -i -P -n | grep LISTEN
# Find all established connections
sudo lsof -i -P -n | grep ESTABLISHED
Find What Process Has a File Open
# Who has this log file open?
sudo lsof /var/log/syslog
# Who has files open in this directory?
sudo lsof +D /var/www/html
# Find deleted files that are still held open (consuming disk space)
sudo lsof +L1
# This is a common cause of "disk full" when df and du disagree:
# A large log file was deleted but the process still holds it open
# Solution: restart the process to release the file handle
Find Open Files by Process
# List all files opened by a specific process
sudo lsof -p 1234
# List files opened by a specific command
sudo lsof -c nginx
# List files opened by a specific user
sudo lsof -u www-data
# Count open files per process
sudo lsof | awk "{print $1}" | sort | uniq -c | sort -rn | head -15
Network Diagnostics
# Show all network connections for a process
sudo lsof -i -a -p $(pgrep -f mysql)
# Show connections to a specific remote host
sudo lsof -i @192.168.1.100
# Show all IPv4 connections
sudo lsof -i 4
# Show all IPv6 connections
sudo lsof -i 6
# Show connections in a specific state
sudo lsof -i -s TCP:LISTEN # Only listening
sudo lsof -i -s TCP:ESTABLISHED # Only established
sudo lsof -i -s TCP:CLOSE_WAIT # Connections waiting to close
Troubleshooting Common Issues
Port Already in Use
# When you get "Address already in use" error:
sudo lsof -i :8080
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# node 5678 deploy 12u IPv4 67890 0t0 TCP *:8080 (LISTEN)
# Now you know PID 5678 (node) is using port 8080
# Either stop that process or use a different port
Disk Space Not Freed After Deleting Files
# Find deleted files still held open
sudo lsof +L1 | grep deleted
# Example:
# nginx 1234 root 2w REG 252,1 5368709120 0 /var/log/nginx/access.log (deleted)
# The file is deleted but nginx still writes to it
# The 5GB of space is not freed until nginx releases the file handle
# Fix: Restart the process
sudo systemctl restart nginx
# Or truncate the file descriptor:
sudo truncate -s 0 /proc/1234/fd/2
Too Many Open Files
# Check current limits
ulimit -n # Per-process limit (default: 1024)
cat /proc/sys/fs/file-nr # System-wide: allocated free maximum
# Count open files for a process
sudo ls /proc/$(pgrep -f nginx | head -1)/fd | wc -l
# Increase limits for a service
sudo systemctl edit nginx
# Add:
# [Service]
# LimitNOFILE=65536
# Increase system-wide limit
echo "fs.file-max = 2097152" | sudo tee -a /etc/sysctl.d/99-file-max.conf
sudo sysctl -p /etc/sysctl.d/99-file-max.conf
Useful lsof Combinations
# AND logic (both conditions must match): use -a flag
sudo lsof -u www-data -a -i # Network connections by www-data
# Repeat every 5 seconds (like watch)
sudo lsof -i :80 -r 5
# Output in parseable format
sudo lsof -i :80 -F pcn # Fields: PID, command, network
# Exclude a user (useful to filter noise)
sudo lsof -i -u ^root # All network connections except root
lsof vs ss
For pure network diagnostics, ss is faster and more modern. Use lsof when you need to correlate files with processes, and ss when you only care about network connections.
# Equivalent commands:
sudo lsof -i :80 # lsof: who is using port 80
sudo ss -tlnp sport = :80 # ss: who is listening on port 80 (faster)