Comment obtenir le PID d'un processus qui est pipé à un autre processus dans Bash?

j'essaie d'implémenter un simple serveur de log à Bash. Il devrait prendre un fichier comme paramètre et le servir sur un port avec netcat.

( tail -f  & ) | nc -l -p 9977

mais le problème est que lorsque le netcat se termine, la queue est laissée derrière. (Clarification: si Je ne bifurque pas le processus de queue, il continuera à fonctionner pour toujours, même le netcat se termine.)

si je connais le PID de la queue, je pourrais le tuer après.

De toute évidence, à l'aide de $! retournera le PID de netcat.

Comment puis-je obtenir le PID du processus de queue?

43
demandé sur codeforester 2009-10-31 01:43:22

12 réponses

Ecrivez le PID de tail au descripteur de fichier 3, puis capturez-le à partir de là.

( tail -f  & echo $! >&3 ) 3>pid | nc -l -p 9977
kill $(<pid)
30
répondu bobbogo 2014-07-16 15:35:26

une autre option: Utiliser une redirection vers subshell. Cela change l'ordre dans lequel les processus de fond sont lancés, donc $! donne PID du processus tail .

tail -f  > >(nc -l -p 9977) &
wait $!
32
répondu VladV 2017-02-12 20:34:12

que pensez-vous de ceci:

jobs -x echo %1

%1 est pour un premier emploi dans la chaîne d', %2 pour le deuxième, etc. jobs -x remplace job specifier par PID.

10
répondu przemas 2012-01-18 09:53:09

cela fonctionne pour moi (SLES Linux):

tail -F xxxx | tee -a yyyy &
export TAIL_PID=`jobs -p`
# export TEE_PID="$!"

l'astuce ps|grep|kill mentionnée dans ce thread ne fonctionnerait pas si un utilisateur peut exécuter le script pour deux "instances" sur la même machine.

jobs -x echo %1 n'a pas fonctionné pour moi (page de manuel n'ayant pas le drapeau -x ) mais m'a donné l'idée d'essayer jobs -p .

9
répondu James Shau 2012-10-05 18:33:12

peut-être que vous pourriez utiliser un fifo , de sorte que vous pouvez capturer le pid du premier processus, par exemple:

FIFO=my_fifo

rm -f $FIFO
mkfifo $FIFO

tail -f  > $FIFO &
TAIL_PID=$!

cat $FIFO | nc -l -p 9977

kill $TAIL_PID

rm -f $FIFO
6
répondu martin clayton 2009-10-30 22:59:15

enfin, j'ai réussi à trouver le processus de queue en utilisant ps . Grâce à l'idée d'ennuikiller.

j'ai utilisé le ps pour attraper la queue des args et la tuer. C'est un peu un piratage, mais ça a marché. :)

si vous pouvez trouver un meilleur moyen s'il vous plaît partager.

voici le script complet:

(La dernière version peut être trouvée ici: http://docs.karamatli.com/dotfiles/bin/logserver )

if [ -z "" ]; then
    echo Usage: "151900920" LOGFILE [PORT]
    exit -1
fi
if [ -n "" ]; then
    PORT=
else
    PORT=9977
fi

TAIL_CMD="tail -f "

function kill_tail {
    # find and kill the tail process that is detached from the current process
    TAIL_PID=$(/bin/ps -eo pid,args | grep "$TAIL_CMD" | grep -v grep | awk '{ print  }')
    kill $TAIL_PID
}
trap "kill_tail; exit 0" SIGINT SIGTERM

while true; do
    ( $TAIL_CMD & ) | nc -l -p $PORT -vvv
    kill_tail
done
2
répondu Ertuğ Karamatlı 2009-10-31 12:08:25

ncat se termine automatiquement tail -f à la sortie (sur Mac OS X 10.6.7)!

# simple log server in Bash using ncat
# cf. http://nmap.org/ncat/
touch file.log
ncat -l 9977 -c "tail -f file.log" </dev/null   # terminal window 1
ncat localhost 9977 </dev/null                  # terminal window 2
echo hello > file.log                           # terminal window 3
2
répondu pjil 2011-07-07 08:59:10

une façon serait de simplement faire un ps-ef et grep pour tail avec votre script ppid

1
répondu ennuikiller 2009-10-30 22:49:16

avez-vous essayé:

nc -l -p 9977 -c "tail -f "

(non testé)

Ou -e avec un fichier si votre nc n'a pas -c . Vous devrez peut-être avoir un nc compilé avec l'option GAPING_SECURITY_HOLE . Oui, vous devez déduire les mises en garde appropriées de ce nom d'option.

1
répondu Dennis Williamson 2009-10-30 23:50:38

vous pouvez stocker le pid de la commande tail dans une variable en utilisant les redirections Bash I/O seulement (voir Comment obtenir le PID d'un processus dans un pipeline ).

# terminal window 1
# using nc on Mac OS X (FreeBSD nc)
: > /tmp/foo
PID=$( { { tail -f /tmp/foo 0<&4 & echo $! >&3 ; } 4<&0 | { nc -l 9977 ;} & } 3>&1 | head -1 )
kill $PID

# terminal window 2
nc localhost 9977

# terminal window 3
echo line > /tmp/foo
1
répondu chad 2017-05-23 12:17:56

ce n'est pas une réponse idéale, mais j'ai trouvé une solution pour contourner un démon logger sur lequel j'ai travaillé:

#!/bin/sh
tail -f /etc/service/rt4/log/main/current --pid=$$ | grep error

à partir de $info queue:

--pid=PID
          with -f, terminate after process ID, PID dies
0
répondu edibleEnergy 2012-07-24 01:48:41

l'option -- pid à suivre est votre meilleur ami ici. Il vous permettra de contrôler totalement le pipeline en arrière-plan. lisez les options de la commande tail pour plus de résilience dans le cas où votre fichier est activement tourné par un autre processus qui pourrait vous laisser le suivi d'un inode inactif. L'exemple ci-dessous, bien qu'il ne soit pas utilisé pour traiter les données, démontre la restriction "imposée" sur la queue et la capacité de lui dire de quitter à tout moment. Il est utilisé pour mesurer la pression de service sur httpd .

  # Set the tail to die in 100 second even if we die unexpectedlly.
sleep 100 & ;  ctlpid=$!
tail -q -n 0 --follow=name --retry --max-unchanged-stats=1 --pid=$ctlpid -f  /var/log/httpd/access_log 2>/dev/null | wc –l > /tmp/thisSampleRate &
…. Do some other work
….  Can kill the pipe at any time by killing $ctlpid 
…. Calculate preassure if /tmp/thisSampleRate is ready
0
répondu Danny 2015-01-09 13:29:32