le tube apparaîtra comme une entrée dans la liste des descripteurs de fichiers ouverts de votre processus :
% 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
vous pouvez également utiliser quelque chose comme :
% 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
donc, que vous avez l'inode du tuyau :) vous pouvez maintenant rechercher tous les autres processus sous /proc/
pour ce tuyau. alors vous aurez la commande qui vous est dirigée :
% lsof | grep 124149866
cat 29889 xyz 1w FIFO 0,6 124149866 pipe
sh 29890 xyz 0r FIFO 0,6 124149866 pipe
dans cet exemple, cat
canalisé vers les quartiers sh
. en /proc/29889
vous pouvez trouver un fichier appelé cmdline
qui vous dit, comment s'appelait exactement :
% cat /proc/29889/cmdline
cat/dev/zero%
les champs de la ligne de commande sont séparés par NUL, donc ça a l'air un peu moche :)
Akira a suggéré d'utiliser lsof
.
Voici comment vous pourriez le scripter :
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
Exécution :
$ tail -f /var/log/messages | ./whatpipe2.sh
tail -f /var/log/messages
^C
Une autre méthode consiste à utiliser des groupes de processus.
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
Exécution :
$ tail -f /var/log/messages | ./whatpipe1.sh
tail -f /var/log/messages
^C
Notez qu'ils ne fonctionnent tous les deux que si la commande sur le côté gauche du tuyau s'exécute suffisamment longtemps pour ps
voir ça. Vous avez dit que vous l'utilisiez avec tail -f
, donc je doute que ce soit un problème.
$ sleep 0 | ./whatpipe1.sh
$ sleep 1 | ./whatpipe1.sh
sleep 1