Real-Time Monitoring of Process File Descriptors in Linux: A tail-like Interactive Approach


2 views

When debugging or monitoring Linux processes, developers often need to inspect which files a process has open. The traditional method using ls -l /proc/PID/fd provides a static snapshot, but lacks the dynamic observation capabilities that modern debugging scenarios demand.

For real-time monitoring, we can combine the ls approach with the watch command:

watch -n 2 "ls -l /proc/1234/fd"

This refreshes every 2 seconds (adjustable with -n), showing changes in the file descriptor table.

For more detailed information, lsof offers superior capabilities:

watch -n 1 "lsof -p 1234"

This displays not just file descriptors but also socket connections, pipes, and other I/O channels.

For persistent monitoring with logging capabilities:


#!/bin/bash
PID=$1
INTERVAL=${2:-1}
LOG_FILE="fd_monitor_${PID}.log"

while true; do
    echo "=== $(date) ===" >> $LOG_FILE
    lsof -p $PID >> $LOG_FILE
    sleep $INTERVAL
done

Usage: ./monitor_fd.sh 1234 0.5 (monitors PID 1234 every 0.5 seconds)

For kernel-level monitoring, consider using inotifywait:


inotifywait -m /proc/1234/fd -e create,delete |
while read -r directory event file; do
    echo "File descriptor $file was $event at $(date)"
done

Combine with grep for focused monitoring:

watch -n 0.5 "lsof -p 1234 | grep -E 'REG|CHR'"

This filters for regular files and character devices only.




When debugging processes or analyzing system behavior, developers often need to monitor which files a process has opened. While ls -l /proc/PID/fd provides this information, it's a static snapshot that requires manual repetition.

The most straightforward approach is using the watch command combined with our original query:

watch -n 1 "ls -l /proc/PID/fd"

This refreshes the output every second (-n 1). Adjust the interval as needed.

For more detailed real-time monitoring, lsof (LiSt Open Files) offers powerful options:

watch -n 1 "lsof -p PID"

This shows not just file descriptors but also sockets, pipes, and other file types.

For persistent monitoring with timestamps:

#!/bin/bash
PID=$1
INTERVAL=${2:-1}  # Default to 1 second

while true; do
    clear
    echo "=== $(date) ==="
    ls -l /proc/$PID/fd
    sleep $INTERVAL
done

Save as fdmonitor.sh, make executable (chmod +x fdmonitor.sh), and run with ./fdmonitor.sh PID [interval].

For event-driven monitoring (rather than polling), consider inotifywait:

inotifywait -m /proc/PID/fd

This triggers only when file descriptors change, but has limitations with /proc virtual filesystem.

For programmatic access:

import os
import time

def monitor_fds(pid, interval=1):
    fd_path = f"/proc/{pid}/fd"
    while True:
        print(f"\n=== {time.ctime()} ===")
        for fd in os.listdir(fd_path):
            try:
                link = os.readlink(f"{fd_path}/{fd}")
                print(f"FD {fd} -> {link}")
            except (FileNotFoundError, PermissionError):
                continue
        time.sleep(interval)

monitor_fds(1234)  # Replace with target PID