# Linux – How to determine the actual command that is piping into you

bashlinuxpipe

Let's say I have a bash script called log.sh. In this script, I want to read in input from a pipe, but I also want to know the command used to pipe input into me. Example:

tail -f /var/log/httpd/error | log.sh


In the shell script, I want to know the command tail -f /var/log/httpd/error.

Akira suggested using lsof.

Here's how you could script it:

whatpipe2.sh

#!/bin/bash

pid=$$pgid=(ps -o pgid= -p pid) lsofout=(lsof -g pgid) pipenode=(echo "lsofout" | awk '5 == "0r" { print 9 }') otherpids=(echo "lsofout" | awk '5 == "1w" { print 2 }') for pid in otherpids; do if cmd=(ps -o cmd= -p pid 2>/dev/null); then echo "cmd" break fi done  Running it:  tail -f /var/log/messages | ./whatpipe2.sh tail -f /var/log/messages ^C  Another way is using process groups. whatpipe1.sh #!/bin/bash pid=$$
# ps output is nasty, can (and usually does) start with spaces
# to handle this, I don't quote the "if test $_pgrp =$pgrp" line below
pgrp=$(ps -o pgrp= -p$pid)
psout=$(ps -o pgrp= -o pid= -o cmd=) echo "$psout" | while read _pgrp _pid _cmd; do
if test $_pgrp =$pgrp; then
if test $_pid !=$pid; then
case $_cmd in ps*) # don't print the "ps" we ran to get this info # XXX but this actually means we exclude any "ps" command :-( ;; *) echo "$_cmd"
;;
esac
fi
fi
done


Running it:

$tail -f /var/log/messages | ./whatpipe1.sh tail -f /var/log/messages ^C  Note they both only work if the command on the left side of the pipe runs for long enough for ps to see it. You said you were using it with tail -f, so I doubt this is an issue. $ sleep 0 | ./whatpipe1.sh

\$ sleep 1 | ./whatpipe1.sh
sleep 1