📂 lsof Command - List Open Files

Purpose: The lsof (List Open Files) command displays information about files opened by processes. In Linux, "everything is a file" - including network connections, devices, and pipes - making lsof an essential troubleshooting and system monitoring tool.
Basic Syntax: lsof [options] [names]
Installation: If lsof is not installed:
Debian/Ubuntu: sudo apt install lsof
RHEL/CentOS: sudo yum install lsof

📋 10 Detailed Examples

Example 1: List All Open Files

Display all files opened by all processes on the system:

sudo lsof

Sample Output (truncated):

COMMAND    PID   TID    USER   FD      TYPE    DEVICE  SIZE/OFF    NODE NAME
systemd      1            root  cwd      DIR      253,0      4096       2 /
systemd      1            root  rtd      DIR      253,0      4096       2 /
systemd      1            root  txt      REG      253,0   1632776  134678 /lib/systemd/systemd
sshd      1234           root    3u     IPv4     12345      0t0     TCP *:22 (LISTEN)
nginx     5678          nginx    6u     IPv4     56789      0t0     TCP *:80 (LISTEN)

Output Column Meanings:

Note: Running without sudo shows only files from your processes. Use sudo to see system-wide information.
Example 2: Find Which Process is Using a File

Identify the process accessing a specific file:

lsof /var/log/syslog

Sample Output:

COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
rsyslogd  1234  syslog  6w   REG   253,0  1234567  789012 /var/log/syslog

Use Cases:

Real-World Example:

# Can't unmount filesystem?
sudo lsof /mnt/data

# Find out what's keeping it busy
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    5678 john  cwd    DIR   8,1     4096    2 /mnt/data
Example 3: List Files Opened by Specific User

Show all files opened by a particular user:

lsof -u username

Multiple users:

lsof -u user1,user2

Exclude specific user:

lsof -u ^root

What it shows: Every file, directory, network connection, and device opened by the specified user's processes. Useful for:

Example 4: Find Network Connections and Listening Ports

Display all network connections:

sudo lsof -i

Specific port:

sudo lsof -i :80

Specific protocol and port:

sudo lsof -i TCP:22
sudo lsof -i UDP:53

Show listening ports only:

sudo lsof -i -sTCP:LISTEN

Sample Output:

COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    1234   root    3u  IPv4  12345      0t0  TCP *:22 (LISTEN)
nginx   5678 nobody    6u  IPv4  56789      0t0  TCP *:80 (LISTEN)
mysqld  9012  mysql   20u  IPv4  90123      0t0  TCP localhost:3306 (LISTEN)

Common Uses:

Example 5: Find Files Opened by Specific Process

List all files opened by a process ID:

lsof -p 1234

Multiple processes:

lsof -p 1234,5678,9012

By process name (all instances):

lsof -c nginx

Practical Examples:

# Find all files used by Apache
sudo lsof -c httpd

# Check what database server has open
sudo lsof -c mysql

# See all files for a specific PID
sudo lsof -p $(pgrep -f "my_application")

Helps diagnose:

Example 6: Find Deleted But Still Open Files (Disk Space Recovery)

Identify deleted files still held open by processes:

sudo lsof | grep deleted

Or more specifically:

sudo lsof +L1

Sample Output:

COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NLINK    NODE NAME
java    5678 app   12u   REG   253,0 5368709120     0  123456 /tmp/app.log (deleted)

What this means: The file has been deleted from the filesystem, but the process still has it open. The disk space won't be freed until the process closes the file or terminates.

To recover disk space:

# Option 1: Restart the process gracefully
sudo systemctl restart application

# Option 2: Kill the specific process
sudo kill 5678

# Option 3: Truncate the file while still open (for logs)
sudo truncate -s 0 /proc/5678/fd/12

Common Scenario: Your /var is full, you deleted huge logs, but df still shows no space freed. This command finds the culprit!

Example 7: Continuous Monitoring Mode

Monitor file operations in real-time:

sudo lsof -r 2

What it does: Refreshes the list every 2 seconds, showing dynamic file access. The -r option enables repeat mode.

Monitor specific directory continuously:

sudo lsof -r 1 +D /var/www/html

Monitor network connections to specific host:

sudo lsof -r 2 -i @192.168.1.100

Practical monitoring script:

#!/bin/bash
# Monitor who's accessing sensitive directory

echo "Monitoring /etc/shadow access..."
sudo lsof -r 1 /etc/shadow | while read line; do
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $line"
    # Could send alert here
done

Press Ctrl+C to stop monitoring.

Example 8: Complex Filtering with AND/OR Logic

Combine multiple criteria (default is OR logic):

# Files opened by nginx OR on port 80
sudo lsof -c nginx -i :80

Use AND logic (both conditions must match):

# Files opened by nginx AND on port 80
sudo lsof -c nginx -a -i :80

Complex real-world examples:

# All network connections by user www-data
sudo lsof -a -u www-data -i

# TCP connections to port 443 in ESTABLISHED state
sudo lsof -i TCP:443 -a -sTCP:ESTABLISHED

# Files in /var/log opened by non-root users
sudo lsof +D /var/log -a -u ^root

# Network connections excluding localhost
sudo lsof -i -a -u ^root | grep -v localhost

Troubleshooting Example:

# Find why specific user can't bind to port
sudo lsof -i :8080 -a -u appuser
Example 9: Security Audit Script - Suspicious Activity Detection

Comprehensive security monitoring script:

#!/bin/bash
# security-audit.sh - Detect suspicious file and network activity

REPORT_FILE="/tmp/security_audit_$(date +%Y%m%d_%H%M%S).txt"

echo "=== Security Audit Report ===" > $REPORT_FILE
echo "Date: $(date)" >> $REPORT_FILE
echo "" >> $REPORT_FILE

# 1. Check for suspicious network connections
echo "=== Suspicious Outbound Connections ===" >> $REPORT_FILE
sudo lsof -i -sTCP:ESTABLISHED | grep -v -E "(localhost|127.0.0.1)" | \
    grep -v -E "(github.com|google.com)" >> $REPORT_FILE || echo "None found" >> $REPORT_FILE
echo "" >> $REPORT_FILE

# 2. Check deleted but open files (possible rootkit)
echo "=== Deleted Files Still Open ===" >> $REPORT_FILE
sudo lsof +L1 >> $REPORT_FILE || echo "None found" >> $REPORT_FILE
echo "" >> $REPORT_FILE

# 3. Check for processes with no name (suspicious)
echo "=== Unnamed Processes ===" >> $REPORT_FILE  
sudo lsof | grep -E "^\s*$" >> $REPORT_FILE || echo "None found" >> $REPORT_FILE
echo "" >> $REPORT_FILE

# 4. Check unusual ports (not 22,80,443)
echo "=== Non-Standard Listening Ports ===" >> $REPORT_FILE
sudo lsof -i -sTCP:LISTEN | grep -v -E ":(22|80|443|3306|5432)" >> $REPORT_FILE || \
    echo "None found" >> $REPORT_FILE
echo "" >> $REPORT_FILE

# 5. Files opened from /tmp (execution from tmp)
echo "=== Execution from /tmp ===" >> $REPORT_FILE
sudo lsof | grep "/tmp" | grep -E "(EXEC|txt)" >> $REPORT_FILE || echo "None found" >> $REPORT_FILE
echo "" >> $REPORT_FILE

# 6. Check for excessive file descriptors (leak detection)
echo "=== Processes with >1000 Open Files ===" >> $REPORT_FILE
for pid in $(ps -eo pid); do
    count=$(sudo lsof -p $pid 2>/dev/null | wc -l)
    if [ "$count" -gt 1000 ]; then
        echo "PID $pid has $count open files" >> $REPORT_FILE
        ps -p $pid -o pid,user,comm >> $REPORT_FILE
    fi
done

echo "Audit complete! Report: $REPORT_FILE"
cat $REPORT_FILE

Run this daily via cron to catch suspicious activity early.

Example 10: Comprehensive Network Connection Monitor

Advanced network monitoring and analysis tool:

#!/bin/bash
# netmon.sh - Comprehensive network connection monitor

print_header() {
    echo "======================================"
    echo "$1"
    echo "======================================"
}

# Summary of all network connections
print_header "LISTENING SERVICES"
sudo lsof -i -sTCP:LISTEN -P | awk 'NR>1 {print $1, $3, $9}' | column -t

echo ""
print_header "ESTABLISHED CONNECTIONS"
sudo lsof -i -sTCP:ESTABLISHED -P | awk 'NR>1 {print $1, $3, $9}' | column -t

echo ""
print_header "UDP SERVICES"  
sudo lsof -i UDP -P | awk 'NR>1 {print $1, $3, $9}' | column -t

echo ""
print_header "CONNECTION COUNT BY PROCESS"
sudo lsof -i -sTCP:ESTABLISHED | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn

echo ""
print_header "CONNECTION COUNT BY USER"
sudo lsof -i -sTCP:ESTABLISHED | awk 'NR>1 {print $3}' | sort | uniq -c | sort -rn

echo ""
print_header "EXTERNAL CONNECTIONS (Non-Localhost)"
sudo lsof -i -sTCP:ESTABLISHED | grep -v -E "(localhost|127.0.0.1)" | \
    awk 'NR>1 {print $1, $3, $9}' | column -t

echo ""
print_header "SUSPICIOUS HIGH PORTS (>10000)"
sudo lsof -i -sTCP:LISTEN | awk '$9 ~ /:/ {split($9,a,":"); if(a[2]>10000) print $0}'

# Optional: continuous monitoring
if [ "$1" == "-w" ]; then
    echo ""
    echo "Entering watch mode (refreshing every 3 seconds)..."
    watch -n 3 "$0"
fi

Usage:

# Single snapshot
bash netmon.sh

# Continuous monitoring
bash netmon.sh -w

📊 Complete Options Reference

Option Description Example
-u user List files for specific user lsof -u john
-c name List files for processes beginning with name lsof -c nginx
-p PID List files for specific process ID lsof -p 1234
-i List network connections lsof -i
-i :port List connections on specific port lsof -i :80
-i protocol List connections for protocol (TCP/UDP) lsof -i TCP
-i @host List connections to/from host lsof -i @192.168.1.1
+D dir List all open files under directory lsof +D /var/log
-a AND logic for multiple conditions lsof -u john -a -i
-r seconds Repeat mode (monitor continuously) lsof -r 2
+L1 Find deleted files still open lsof +L1
-P Don't resolve port names lsof -P -i
-n Don't resolve hostnames lsof -n -i
-t Terse output (PIDs only) lsof -t /file

🎯 Common Use Cases

Find and Kill Process Using a Port

sudo kill $(sudo lsof -t -i :8080)

Check If Port is Available

if sudo lsof -i :8080 > /dev/null; then
    echo "Port 8080 is in use"
else
    echo "Port 8080 is available"
fi

Find Why Directory Can't Be Unmounted

sudo lsof +D /mnt/external

Monitor Apache Connections

watch -n 1 'sudo lsof -i :80 -i :443 | grep ESTABLISHED | wc -l'

Find All MySQL Connections

sudo lsof -i :3306 -sTCP:ESTABLISHED

🔍 Troubleshooting Common Issues

Permission Denied Errors

Most lsof commands require root privileges:

sudo lsof ...

Output Too Large

Filter and use grep:

sudo lsof | grep pattern
sudo lsof -i | less

Slow Performance

Disable hostname and port resolution:

sudo lsof -n -P

📚 Quick Reference Card

Task Command
All open files sudo lsof
What's using this file? lsof /path/to/file
What's listening on port 80? sudo lsof -i :80
All user's files lsof -u username
All process's files lsof -p PID
All network connections sudo lsof -i
Deleted but open files sudo lsof +L1
Monitor continuously sudo lsof -r 2
Pro Tip: Combine lsof with other commands:
sudo lsof -t -i :8080 | xargs kill - Kill process on port 8080
sudo lsof | wc -l - Count total open files
sudo lsof -p $(pgrep nginx) - Files for all nginx processes