How do you determine the actual command that is piping into you?
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
add a comment |
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
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
add a comment |
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
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
linux bash pipe
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
add a comment |
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
add a comment |
3 Answers
3
active
oldest
votes
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
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
add a comment |
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 :)
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
add a comment |
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:
- There may be more than one PID found on the source end, e.g.
{ echo Hi; sleep 5 ; } | whatpipe.sh
will likely yield abash
(the input subshell) andsleep 5
.
+E
is only available iflsof
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
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
add a comment |
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
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
add a comment |
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
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
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
add a comment |
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
add a comment |
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 :)
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
add a comment |
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 :)
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
add a comment |
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 :)
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 :)
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
add a comment |
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
add a comment |
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:
- There may be more than one PID found on the source end, e.g.
{ echo Hi; sleep 5 ; } | whatpipe.sh
will likely yield abash
(the input subshell) andsleep 5
.
+E
is only available iflsof
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
add a comment |
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:
- There may be more than one PID found on the source end, e.g.
{ echo Hi; sleep 5 ; } | whatpipe.sh
will likely yield abash
(the input subshell) andsleep 5
.
+E
is only available iflsof
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
add a comment |
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:
- There may be more than one PID found on the source end, e.g.
{ echo Hi; sleep 5 ; } | whatpipe.sh
will likely yield abash
(the input subshell) andsleep 5
.
+E
is only available iflsof
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
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:
- There may be more than one PID found on the source end, e.g.
{ echo Hi; sleep 5 ; } | whatpipe.sh
will likely yield abash
(the input subshell) andsleep 5
.
+E
is only available iflsof
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
answered Jan 12 at 15:53
AdrianAdrian
1212
1212
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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