Reputation: 4139
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
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