How do you determine the actual command that is piping into you?












9















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.










share|improve this question























  • I am extremely curious as to why you want this.

    – Ignacio Vazquez-Abrams
    Feb 11 '11 at 6:41











  • My guess is your making some type of GUI program which captures & processes pids?

    – palbakulich
    Feb 11 '11 at 6:50











  • I would like to know so I can distinguish where to put the results. Depending on the command and filename, I would want to perform different actions.

    – St. John Johnson
    Feb 11 '11 at 6:57








  • 4





    That sounds like a major violation of the Principle of Least Surprise to me. If the script should do different things under different circumstances, then that should be controlled by a command-line option rather than by where its input is coming from.

    – Dave Sherohman
    Feb 11 '11 at 10:10











  • @Dave, I agree. Let's just say, for the sake of this example, I just want to 'know' what the incoming command is.

    – St. John Johnson
    Feb 11 '11 at 16:57
















9















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.










share|improve this question























  • I am extremely curious as to why you want this.

    – Ignacio Vazquez-Abrams
    Feb 11 '11 at 6:41











  • My guess is your making some type of GUI program which captures & processes pids?

    – palbakulich
    Feb 11 '11 at 6:50











  • I would like to know so I can distinguish where to put the results. Depending on the command and filename, I would want to perform different actions.

    – St. John Johnson
    Feb 11 '11 at 6:57








  • 4





    That sounds like a major violation of the Principle of Least Surprise to me. If the script should do different things under different circumstances, then that should be controlled by a command-line option rather than by where its input is coming from.

    – Dave Sherohman
    Feb 11 '11 at 10:10











  • @Dave, I agree. Let's just say, for the sake of this example, I just want to 'know' what the incoming command is.

    – St. John Johnson
    Feb 11 '11 at 16:57














9












9








9


6






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.










share|improve this question














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.







linux bash pipe






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Feb 11 '11 at 6:40









St. John JohnsonSt. John Johnson

1485




1485













  • I am extremely curious as to why you want this.

    – Ignacio Vazquez-Abrams
    Feb 11 '11 at 6:41











  • My guess is your making some type of GUI program which captures & processes pids?

    – palbakulich
    Feb 11 '11 at 6:50











  • I would like to know so I can distinguish where to put the results. Depending on the command and filename, I would want to perform different actions.

    – St. John Johnson
    Feb 11 '11 at 6:57








  • 4





    That sounds like a major violation of the Principle of Least Surprise to me. If the script should do different things under different circumstances, then that should be controlled by a command-line option rather than by where its input is coming from.

    – Dave Sherohman
    Feb 11 '11 at 10:10











  • @Dave, I agree. Let's just say, for the sake of this example, I just want to 'know' what the incoming command is.

    – St. John Johnson
    Feb 11 '11 at 16:57



















  • I am extremely curious as to why you want this.

    – Ignacio Vazquez-Abrams
    Feb 11 '11 at 6:41











  • My guess is your making some type of GUI program which captures & processes pids?

    – palbakulich
    Feb 11 '11 at 6:50











  • I would like to know so I can distinguish where to put the results. Depending on the command and filename, I would want to perform different actions.

    – St. John Johnson
    Feb 11 '11 at 6:57








  • 4





    That sounds like a major violation of the Principle of Least Surprise to me. If the script should do different things under different circumstances, then that should be controlled by a command-line option rather than by where its input is coming from.

    – Dave Sherohman
    Feb 11 '11 at 10:10











  • @Dave, I agree. Let's just say, for the sake of this example, I just want to 'know' what the incoming command is.

    – St. John Johnson
    Feb 11 '11 at 16:57

















I am extremely curious as to why you want this.

– Ignacio Vazquez-Abrams
Feb 11 '11 at 6:41





I am extremely curious as to why you want this.

– Ignacio Vazquez-Abrams
Feb 11 '11 at 6:41













My guess is your making some type of GUI program which captures & processes pids?

– palbakulich
Feb 11 '11 at 6:50





My guess is your making some type of GUI program which captures & processes pids?

– palbakulich
Feb 11 '11 at 6:50













I would like to know so I can distinguish where to put the results. Depending on the command and filename, I would want to perform different actions.

– St. John Johnson
Feb 11 '11 at 6:57







I would like to know so I can distinguish where to put the results. Depending on the command and filename, I would want to perform different actions.

– St. John Johnson
Feb 11 '11 at 6:57






4




4





That sounds like a major violation of the Principle of Least Surprise to me. If the script should do different things under different circumstances, then that should be controlled by a command-line option rather than by where its input is coming from.

– Dave Sherohman
Feb 11 '11 at 10:10





That sounds like a major violation of the Principle of Least Surprise to me. If the script should do different things under different circumstances, then that should be controlled by a command-line option rather than by where its input is coming from.

– Dave Sherohman
Feb 11 '11 at 10:10













@Dave, I agree. Let's just say, for the sake of this example, I just want to 'know' what the incoming command is.

– St. John Johnson
Feb 11 '11 at 16:57





@Dave, I agree. Let's just say, for the sake of this example, I just want to 'know' what the incoming command is.

– St. John Johnson
Feb 11 '11 at 16:57










3 Answers
3






active

oldest

votes


















7














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





share|improve this answer


























  • instead of this huge post i would have given a 2nd answer with the lsof-based script. nice work for that one.

    – akira
    Feb 11 '11 at 10:02











  • @akira Thanks. It took a few attempts to make it clean and portable. Learned a few things about procfs and lsof along the way. Thanks for the idea.

    – Mikel
    Feb 11 '11 at 10:04











  • I accepted yours as it gives an answer other people can directly use. @Akira, you did most of the work, sorry I couldn't accept yours as well.

    – St. John Johnson
    Feb 11 '11 at 17:02



















10














the pipe will appear as an entry in the list of open filedescriptors of your process:



 % ls -l /proc/PID/fd
lr-x------ 1 xyz xyz 64 Feb 11 08:05 0 -> pipe:[124149866]
lrwx------ 1 xyz xyz 64 Feb 11 08:05 1 -> /dev/pts/2
lrwx------ 1 xyz xyz 64 Feb 11 08:05 2 -> /dev/pts/2
lr-x------ 1 xyz xyz 64 Feb 11 08:05 10 -> /tmp/foo.sh


you could also use something like:



 % lsof -p PID
sh 29890 xyz cwd DIR 0,44 4096 77712070 /tmp
sh 29890 xyz rtd DIR 0,44 4096 74368803 /
sh 29890 xyz txt REG 0,44 83888 77597729 /bin/dash
sh 29890 xyz mem REG 0,44 1405508 79888619 /lib/tls/i686/cmov/libc-2.11.1.so
sh 29890 xyz mem REG 0,44 113964 79874782 /lib/ld-2.11.1.so
sh 29890 xyz 0r FIFO 0,6 124149866 pipe
sh 29890 xyz 1u CHR 136,2 4 /dev/pts/2
sh 29890 xyz 2u CHR 136,2 4 /dev/pts/2
sh 29890 xyz 10r REG 0,44 66 77712115 /tmp/foo.sh


so, than you have the inode of the pipe :) you can now search every other process under /proc/ for that pipe. then you will have the command that is piping to you:



 % lsof | grep 124149866 
cat 29889 xyz 1w FIFO 0,6 124149866 pipe
sh 29890 xyz 0r FIFO 0,6 124149866 pipe


in this example, cat piped to wards sh. in /proc/29889 you can find a file called cmdline which tells you, what exactly was called:



 % cat /proc/29889/cmdline
cat/dev/zero%


the fields of the command line are separated by NUL, thus it looks a bit ugly :)






share|improve this answer


























  • I don't know which answer to accept. @Akira, you gave the actual breakdown as to how to determine it, while @Mikel gave me a script. Way to make things awesome + difficult.

    – St. John Johnson
    Feb 11 '11 at 16:59



















1














Here's a compact solution using modern lsof on modern Linux distributions:



cmd=$(lsof -t -p $$ -a -d 0 +E | while read p; do
[ $p -ne $$ ] && echo "$(tr \000 " " </proc/$p/cmdline)"
done)


This lists the endpoint files (+E) of FD 0 on the current shell process (-p $$ -a -d 0), then limits the output to PIDs only (-t), yielding the PIDs on both sides of the pipe.



Note that:




  1. There may be more than one PID found on the source end, e.g. { echo Hi; sleep 5 ; } | whatpipe.sh will likely yield a bash (the input subshell) and sleep 5.


  2. +E is only available if lsof was compiled with -DHASUXSOCKEPT. That should be true for most modern Linux distros, but check your installation anyway with: lsof -v 2>&1 | grep HASUXSOCKEPT






share|improve this answer























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "3"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f244413%2fhow-do-you-determine-the-actual-command-that-is-piping-into-you%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    7














    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





    share|improve this answer


























    • instead of this huge post i would have given a 2nd answer with the lsof-based script. nice work for that one.

      – akira
      Feb 11 '11 at 10:02











    • @akira Thanks. It took a few attempts to make it clean and portable. Learned a few things about procfs and lsof along the way. Thanks for the idea.

      – Mikel
      Feb 11 '11 at 10:04











    • I accepted yours as it gives an answer other people can directly use. @Akira, you did most of the work, sorry I couldn't accept yours as well.

      – St. John Johnson
      Feb 11 '11 at 17:02
















    7














    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





    share|improve this answer


























    • instead of this huge post i would have given a 2nd answer with the lsof-based script. nice work for that one.

      – akira
      Feb 11 '11 at 10:02











    • @akira Thanks. It took a few attempts to make it clean and portable. Learned a few things about procfs and lsof along the way. Thanks for the idea.

      – Mikel
      Feb 11 '11 at 10:04











    • I accepted yours as it gives an answer other people can directly use. @Akira, you did most of the work, sorry I couldn't accept yours as well.

      – St. John Johnson
      Feb 11 '11 at 17:02














    7












    7








    7







    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





    share|improve this answer















    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






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 11 '11 at 9:59

























    answered Feb 11 '11 at 7:25









    MikelMikel

    7,53013434




    7,53013434













    • instead of this huge post i would have given a 2nd answer with the lsof-based script. nice work for that one.

      – akira
      Feb 11 '11 at 10:02











    • @akira Thanks. It took a few attempts to make it clean and portable. Learned a few things about procfs and lsof along the way. Thanks for the idea.

      – Mikel
      Feb 11 '11 at 10:04











    • I accepted yours as it gives an answer other people can directly use. @Akira, you did most of the work, sorry I couldn't accept yours as well.

      – St. John Johnson
      Feb 11 '11 at 17:02



















    • instead of this huge post i would have given a 2nd answer with the lsof-based script. nice work for that one.

      – akira
      Feb 11 '11 at 10:02











    • @akira Thanks. It took a few attempts to make it clean and portable. Learned a few things about procfs and lsof along the way. Thanks for the idea.

      – Mikel
      Feb 11 '11 at 10:04











    • I accepted yours as it gives an answer other people can directly use. @Akira, you did most of the work, sorry I couldn't accept yours as well.

      – St. John Johnson
      Feb 11 '11 at 17:02

















    instead of this huge post i would have given a 2nd answer with the lsof-based script. nice work for that one.

    – akira
    Feb 11 '11 at 10:02





    instead of this huge post i would have given a 2nd answer with the lsof-based script. nice work for that one.

    – akira
    Feb 11 '11 at 10:02













    @akira Thanks. It took a few attempts to make it clean and portable. Learned a few things about procfs and lsof along the way. Thanks for the idea.

    – Mikel
    Feb 11 '11 at 10:04





    @akira Thanks. It took a few attempts to make it clean and portable. Learned a few things about procfs and lsof along the way. Thanks for the idea.

    – Mikel
    Feb 11 '11 at 10:04













    I accepted yours as it gives an answer other people can directly use. @Akira, you did most of the work, sorry I couldn't accept yours as well.

    – St. John Johnson
    Feb 11 '11 at 17:02





    I accepted yours as it gives an answer other people can directly use. @Akira, you did most of the work, sorry I couldn't accept yours as well.

    – St. John Johnson
    Feb 11 '11 at 17:02













    10














    the pipe will appear as an entry in the list of open filedescriptors of your process:



     % ls -l /proc/PID/fd
    lr-x------ 1 xyz xyz 64 Feb 11 08:05 0 -> pipe:[124149866]
    lrwx------ 1 xyz xyz 64 Feb 11 08:05 1 -> /dev/pts/2
    lrwx------ 1 xyz xyz 64 Feb 11 08:05 2 -> /dev/pts/2
    lr-x------ 1 xyz xyz 64 Feb 11 08:05 10 -> /tmp/foo.sh


    you could also use something like:



     % lsof -p PID
    sh 29890 xyz cwd DIR 0,44 4096 77712070 /tmp
    sh 29890 xyz rtd DIR 0,44 4096 74368803 /
    sh 29890 xyz txt REG 0,44 83888 77597729 /bin/dash
    sh 29890 xyz mem REG 0,44 1405508 79888619 /lib/tls/i686/cmov/libc-2.11.1.so
    sh 29890 xyz mem REG 0,44 113964 79874782 /lib/ld-2.11.1.so
    sh 29890 xyz 0r FIFO 0,6 124149866 pipe
    sh 29890 xyz 1u CHR 136,2 4 /dev/pts/2
    sh 29890 xyz 2u CHR 136,2 4 /dev/pts/2
    sh 29890 xyz 10r REG 0,44 66 77712115 /tmp/foo.sh


    so, than you have the inode of the pipe :) you can now search every other process under /proc/ for that pipe. then you will have the command that is piping to you:



     % lsof | grep 124149866 
    cat 29889 xyz 1w FIFO 0,6 124149866 pipe
    sh 29890 xyz 0r FIFO 0,6 124149866 pipe


    in this example, cat piped to wards sh. in /proc/29889 you can find a file called cmdline which tells you, what exactly was called:



     % cat /proc/29889/cmdline
    cat/dev/zero%


    the fields of the command line are separated by NUL, thus it looks a bit ugly :)






    share|improve this answer


























    • I don't know which answer to accept. @Akira, you gave the actual breakdown as to how to determine it, while @Mikel gave me a script. Way to make things awesome + difficult.

      – St. John Johnson
      Feb 11 '11 at 16:59
















    10














    the pipe will appear as an entry in the list of open filedescriptors of your process:



     % ls -l /proc/PID/fd
    lr-x------ 1 xyz xyz 64 Feb 11 08:05 0 -> pipe:[124149866]
    lrwx------ 1 xyz xyz 64 Feb 11 08:05 1 -> /dev/pts/2
    lrwx------ 1 xyz xyz 64 Feb 11 08:05 2 -> /dev/pts/2
    lr-x------ 1 xyz xyz 64 Feb 11 08:05 10 -> /tmp/foo.sh


    you could also use something like:



     % lsof -p PID
    sh 29890 xyz cwd DIR 0,44 4096 77712070 /tmp
    sh 29890 xyz rtd DIR 0,44 4096 74368803 /
    sh 29890 xyz txt REG 0,44 83888 77597729 /bin/dash
    sh 29890 xyz mem REG 0,44 1405508 79888619 /lib/tls/i686/cmov/libc-2.11.1.so
    sh 29890 xyz mem REG 0,44 113964 79874782 /lib/ld-2.11.1.so
    sh 29890 xyz 0r FIFO 0,6 124149866 pipe
    sh 29890 xyz 1u CHR 136,2 4 /dev/pts/2
    sh 29890 xyz 2u CHR 136,2 4 /dev/pts/2
    sh 29890 xyz 10r REG 0,44 66 77712115 /tmp/foo.sh


    so, than you have the inode of the pipe :) you can now search every other process under /proc/ for that pipe. then you will have the command that is piping to you:



     % lsof | grep 124149866 
    cat 29889 xyz 1w FIFO 0,6 124149866 pipe
    sh 29890 xyz 0r FIFO 0,6 124149866 pipe


    in this example, cat piped to wards sh. in /proc/29889 you can find a file called cmdline which tells you, what exactly was called:



     % cat /proc/29889/cmdline
    cat/dev/zero%


    the fields of the command line are separated by NUL, thus it looks a bit ugly :)






    share|improve this answer


























    • I don't know which answer to accept. @Akira, you gave the actual breakdown as to how to determine it, while @Mikel gave me a script. Way to make things awesome + difficult.

      – St. John Johnson
      Feb 11 '11 at 16:59














    10












    10








    10







    the pipe will appear as an entry in the list of open filedescriptors of your process:



     % ls -l /proc/PID/fd
    lr-x------ 1 xyz xyz 64 Feb 11 08:05 0 -> pipe:[124149866]
    lrwx------ 1 xyz xyz 64 Feb 11 08:05 1 -> /dev/pts/2
    lrwx------ 1 xyz xyz 64 Feb 11 08:05 2 -> /dev/pts/2
    lr-x------ 1 xyz xyz 64 Feb 11 08:05 10 -> /tmp/foo.sh


    you could also use something like:



     % lsof -p PID
    sh 29890 xyz cwd DIR 0,44 4096 77712070 /tmp
    sh 29890 xyz rtd DIR 0,44 4096 74368803 /
    sh 29890 xyz txt REG 0,44 83888 77597729 /bin/dash
    sh 29890 xyz mem REG 0,44 1405508 79888619 /lib/tls/i686/cmov/libc-2.11.1.so
    sh 29890 xyz mem REG 0,44 113964 79874782 /lib/ld-2.11.1.so
    sh 29890 xyz 0r FIFO 0,6 124149866 pipe
    sh 29890 xyz 1u CHR 136,2 4 /dev/pts/2
    sh 29890 xyz 2u CHR 136,2 4 /dev/pts/2
    sh 29890 xyz 10r REG 0,44 66 77712115 /tmp/foo.sh


    so, than you have the inode of the pipe :) you can now search every other process under /proc/ for that pipe. then you will have the command that is piping to you:



     % lsof | grep 124149866 
    cat 29889 xyz 1w FIFO 0,6 124149866 pipe
    sh 29890 xyz 0r FIFO 0,6 124149866 pipe


    in this example, cat piped to wards sh. in /proc/29889 you can find a file called cmdline which tells you, what exactly was called:



     % cat /proc/29889/cmdline
    cat/dev/zero%


    the fields of the command line are separated by NUL, thus it looks a bit ugly :)






    share|improve this answer















    the pipe will appear as an entry in the list of open filedescriptors of your process:



     % ls -l /proc/PID/fd
    lr-x------ 1 xyz xyz 64 Feb 11 08:05 0 -> pipe:[124149866]
    lrwx------ 1 xyz xyz 64 Feb 11 08:05 1 -> /dev/pts/2
    lrwx------ 1 xyz xyz 64 Feb 11 08:05 2 -> /dev/pts/2
    lr-x------ 1 xyz xyz 64 Feb 11 08:05 10 -> /tmp/foo.sh


    you could also use something like:



     % lsof -p PID
    sh 29890 xyz cwd DIR 0,44 4096 77712070 /tmp
    sh 29890 xyz rtd DIR 0,44 4096 74368803 /
    sh 29890 xyz txt REG 0,44 83888 77597729 /bin/dash
    sh 29890 xyz mem REG 0,44 1405508 79888619 /lib/tls/i686/cmov/libc-2.11.1.so
    sh 29890 xyz mem REG 0,44 113964 79874782 /lib/ld-2.11.1.so
    sh 29890 xyz 0r FIFO 0,6 124149866 pipe
    sh 29890 xyz 1u CHR 136,2 4 /dev/pts/2
    sh 29890 xyz 2u CHR 136,2 4 /dev/pts/2
    sh 29890 xyz 10r REG 0,44 66 77712115 /tmp/foo.sh


    so, than you have the inode of the pipe :) you can now search every other process under /proc/ for that pipe. then you will have the command that is piping to you:



     % lsof | grep 124149866 
    cat 29889 xyz 1w FIFO 0,6 124149866 pipe
    sh 29890 xyz 0r FIFO 0,6 124149866 pipe


    in this example, cat piped to wards sh. in /proc/29889 you can find a file called cmdline which tells you, what exactly was called:



     % cat /proc/29889/cmdline
    cat/dev/zero%


    the fields of the command line are separated by NUL, thus it looks a bit ugly :)







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 11 '11 at 10:41

























    answered Feb 11 '11 at 7:09









    akiraakira

    48.7k14112152




    48.7k14112152













    • I don't know which answer to accept. @Akira, you gave the actual breakdown as to how to determine it, while @Mikel gave me a script. Way to make things awesome + difficult.

      – St. John Johnson
      Feb 11 '11 at 16:59



















    • I don't know which answer to accept. @Akira, you gave the actual breakdown as to how to determine it, while @Mikel gave me a script. Way to make things awesome + difficult.

      – St. John Johnson
      Feb 11 '11 at 16:59

















    I don't know which answer to accept. @Akira, you gave the actual breakdown as to how to determine it, while @Mikel gave me a script. Way to make things awesome + difficult.

    – St. John Johnson
    Feb 11 '11 at 16:59





    I don't know which answer to accept. @Akira, you gave the actual breakdown as to how to determine it, while @Mikel gave me a script. Way to make things awesome + difficult.

    – St. John Johnson
    Feb 11 '11 at 16:59











    1














    Here's a compact solution using modern lsof on modern Linux distributions:



    cmd=$(lsof -t -p $$ -a -d 0 +E | while read p; do
    [ $p -ne $$ ] && echo "$(tr \000 " " </proc/$p/cmdline)"
    done)


    This lists the endpoint files (+E) of FD 0 on the current shell process (-p $$ -a -d 0), then limits the output to PIDs only (-t), yielding the PIDs on both sides of the pipe.



    Note that:




    1. There may be more than one PID found on the source end, e.g. { echo Hi; sleep 5 ; } | whatpipe.sh will likely yield a bash (the input subshell) and sleep 5.


    2. +E is only available if lsof was compiled with -DHASUXSOCKEPT. That should be true for most modern Linux distros, but check your installation anyway with: lsof -v 2>&1 | grep HASUXSOCKEPT






    share|improve this answer




























      1














      Here's a compact solution using modern lsof on modern Linux distributions:



      cmd=$(lsof -t -p $$ -a -d 0 +E | while read p; do
      [ $p -ne $$ ] && echo "$(tr \000 " " </proc/$p/cmdline)"
      done)


      This lists the endpoint files (+E) of FD 0 on the current shell process (-p $$ -a -d 0), then limits the output to PIDs only (-t), yielding the PIDs on both sides of the pipe.



      Note that:




      1. There may be more than one PID found on the source end, e.g. { echo Hi; sleep 5 ; } | whatpipe.sh will likely yield a bash (the input subshell) and sleep 5.


      2. +E is only available if lsof was compiled with -DHASUXSOCKEPT. That should be true for most modern Linux distros, but check your installation anyway with: lsof -v 2>&1 | grep HASUXSOCKEPT






      share|improve this answer


























        1












        1








        1







        Here's a compact solution using modern lsof on modern Linux distributions:



        cmd=$(lsof -t -p $$ -a -d 0 +E | while read p; do
        [ $p -ne $$ ] && echo "$(tr \000 " " </proc/$p/cmdline)"
        done)


        This lists the endpoint files (+E) of FD 0 on the current shell process (-p $$ -a -d 0), then limits the output to PIDs only (-t), yielding the PIDs on both sides of the pipe.



        Note that:




        1. There may be more than one PID found on the source end, e.g. { echo Hi; sleep 5 ; } | whatpipe.sh will likely yield a bash (the input subshell) and sleep 5.


        2. +E is only available if lsof was compiled with -DHASUXSOCKEPT. That should be true for most modern Linux distros, but check your installation anyway with: lsof -v 2>&1 | grep HASUXSOCKEPT






        share|improve this answer













        Here's a compact solution using modern lsof on modern Linux distributions:



        cmd=$(lsof -t -p $$ -a -d 0 +E | while read p; do
        [ $p -ne $$ ] && echo "$(tr \000 " " </proc/$p/cmdline)"
        done)


        This lists the endpoint files (+E) of FD 0 on the current shell process (-p $$ -a -d 0), then limits the output to PIDs only (-t), yielding the PIDs on both sides of the pipe.



        Note that:




        1. There may be more than one PID found on the source end, e.g. { echo Hi; sleep 5 ; } | whatpipe.sh will likely yield a bash (the input subshell) and sleep 5.


        2. +E is only available if lsof was compiled with -DHASUXSOCKEPT. That should be true for most modern Linux distros, but check your installation anyway with: lsof -v 2>&1 | grep HASUXSOCKEPT







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 12 at 15:53









        AdrianAdrian

        1212




        1212






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Super User!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f244413%2fhow-do-you-determine-the-actual-command-that-is-piping-into-you%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How do I know what Microsoft account the skydrive app is syncing to?

            When does type information flow backwards in C++?

            Grease: Live!