Fabian Fagerholm
Fabian Fagerholm

Reputation: 4139

How can a process find the pids of processes it communicates with over a pipe?

Let's say I have the following pipeline:

$ generator_process | filter_process | storage_process

Is it possible for filter_process to find out the pid of generator_process and storage_process? If so, how? If not, why?

More generally, how can a process find the pids of processes it communicates with over a pipe?

I'm looking for a portable (POSIX) way to do this, but if it requires some platform-specific trickery, a Linux solution is what I'm looking for. I guess an answer in C would give most detail but if it involves the shell, I'm looking for a bash solution.

Please assume that I can change filter_process but generator_process and storage_process are programs that I have no possibility or desire to alter (they could be standard Unix tools that I don't want to fiddle with). Also, wrapping them in scripts that write their pids to disk is not the solution I'm after.

Upvotes: 0

Views: 666

Answers (1)

nneonneo
nneonneo

Reputation: 179592

Note that one end of a pipe might be open in more than one process simultaneously (through fork() or sendmsg file-descriptor transmission), so you might not get just one answer.

In Linux, you can examine /proc/<pid>/fd to see what fds it has open (you need to be root, or the same uid as the target process). I just ran grep a | grep b and got the following output:

/proc/10442/fd:
total 0
dr-x------ 2 nneonneo nneonneo  0 Sep 20 02:19 .
dr-xr-xr-x 7 nneonneo nneonneo  0 Sep 20 02:19 ..
lrwx------ 1 nneonneo nneonneo 64 Sep 20 02:19 0 -> /dev/pts/5
l-wx------ 1 nneonneo nneonneo 64 Sep 20 02:19 1 -> pipe:[100815116]
lrwx------ 1 nneonneo nneonneo 64 Sep 20 02:19 2 -> /dev/pts/5

/proc/10443/fd:
total 0
dr-x------ 2 nneonneo nneonneo  0 Sep 20 02:19 .
dr-xr-xr-x 7 nneonneo nneonneo  0 Sep 20 02:19 ..
lr-x------ 1 nneonneo nneonneo 64 Sep 20 02:19 0 -> pipe:[100815116]
lrwx------ 1 nneonneo nneonneo 64 Sep 20 02:19 1 -> /dev/pts/5
lrwx------ 1 nneonneo nneonneo 64 Sep 20 02:19 2 -> /dev/pts/5

So it follows that by using readlink on your own process's fd, followed by readlink on other process fds you own, you can figure out who is on the other side of the pipe.

Madly hackish way to find out (from within a Bash script) which pids and fds are connected to a particular pipe:

get_fd_target() {
    pid=$1
    fd=$2
    readlink /proc/$pid/fd/$fd
}

find_fd_target() {
    target=$1
    for i in /proc/*/fd/*; do
        if [ "`readlink $i`" == "$target" ]; then
            echo $i
        fi
    done
}

Then, if you want to find out what fds on the system are connected to your script's stdin:

find_fd_target `get_fd_target $$ 0`

Upvotes: 2

Related Questions