How to Identify and Debug Linux Pipe Connections in /proc//fd


2 views

When examining file descriptors in Linux's /proc/[pid]/fd directory, you'll frequently encounter entries like:

l-wx------ 1 root root 64 Jul 30 15:14 10 -> pipe:[90222668]
lr-x------ 1 root root 64 Jul 30 15:14 11 -> pipe:[90222669]

These represent interprocess communication pipes, where the number in brackets (e.g., 90222668) is the kernel's inode identifier for the pipe.

To identify processes sharing a pipe, use this bash command sequence:

# Find all processes with the specific pipe open
grep -l 'pipe:[90222668]' /proc/*/fd/* 2>/dev/null |
while read -r link; do
    pid=${link#/proc/}
    pid=${pid%/fd*}
    echo "Process $pid has fd $(basename $link) connected to pipe 90222668"
    ps -p "$pid" -o comm=,pid=,cmd=
done

This script will output all processes holding file descriptors connected to the specified pipe, along with their command lines.

The lsof command can provide similar information more conveniently:

lsof | grep '90222668'

Sample output would show:

python3   1234 user    3w  FIFO   0,13    0t0 90222668 pipe
bash      5678 user    4r  FIFO   0,13    0t0 90222668 pipe

While you can't directly read from pipes in /proc (as they're kernel objects), you can:

  1. Trace the processes using strace:
    strace -p 1234 -e trace=read,write -s 80
  2. Use gdb to attach to the process and inspect file descriptors

Let's walk through a real-world debugging scenario:

# First, find all pipe connections for a specific process
ls -l /proc/12345/fd | grep pipe

# Output shows:
# 5 -> pipe:[87654321]

# Now find the other end
lsof | grep 87654321

# Output reveals:
# app1     12345 user    5w  FIFO   0,13    0t0 87654321 pipe
# app2     67890 user    7r  FIFO   0,13    0t0 87654321 pipe

This shows process 12345 (app1) has FD 5 writing to the pipe, while process 67890 (app2) has FD 7 reading from it.

For persistent monitoring of pipe activity:

# Set up inotify watch on the pipe
inotifywait -m /proc/12345/fd -e open |
while read -r dir action file; do
    if [[ "$file" == pipe* ]]; then
        echo "New pipe connection: $(readlink "/proc/12345/fd/$file")"
    fi
done

Remember that pipes are unidirectional - one process writes while another reads, which explains the different permissions shown in the original ls -l output (w vs r).


When examining file descriptors in /proc/<pid>/fd, you'll frequently encounter entries like:

l-wx------ 1 root root 64 Jul 30 15:14 10 -> pipe:[90222668]
lr-x------ 1 root root 64 Jul 30 15:14 11 -> pipe:[90222669]

These represent anonymous pipes created between processes. The number in square brackets is the kernel's internal inode number for the pipe.

To identify both ends of a pipe connection:

# Find all processes with open pipes
find /proc -type l -name '[0-9]*' -exec ls -l {} + | grep 'pipe:\[' | sort

This command scans all processes' file descriptors for pipe references. Matching inode numbers indicate connected pipes.

The lsof utility provides detailed pipe information:

# Install if needed
sudo apt install lsof

# Show all open pipes
lsof | grep FIFO

# Filter for specific pipe inode
lsof | grep '90222668'

For deeper analysis, use SystemTap to trace pipe operations:

# SystemTap script to track pipe creation
probe syscall.pipe {
    printf("Pipe created by PID %d (%s)\n", pid(), execname())
}

probe syscall.pipe2 {
    printf("Pipe2 created by PID %d (%s)\n", pid(), execname())
}

For kernel developers, pipe details are available in the pipefs filesystem:

# Requires debugfs mounted
cat /sys/kernel/debug/pipe_info

# Alternative via /proc (if configured)
cat /proc/<pid>/fdinfo/10