bash pipe pid tail netcat

¿Cómo obtener el PID de un proceso que se canaliza a otro proceso en Bash?



pipe tail (12)

Estoy tratando de implementar un servidor de registro simple en Bash. Debe tomar un archivo como parámetro y servirlo en un puerto con netcat.

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

Pero el problema es que cuando el netcat termina, la cola se deja correr. (Aclaración: si no bifurco el proceso de cola, continuará funcionando para siempre incluso cuando termine netcat).

Si de alguna manera conozco el PID de la cola, entonces podría matarlo después.
Obviamente, usando $! devolverá el PID de netcat.

¿Cómo puedo obtener el PID del proceso de cola?


Escriba el PID de cola en el descriptor de archivo 3, y luego capturelo desde allí.

( tail -f $1 & echo $! >&3 ) 3>pid | nc -l -p 9977 kill $(<pid)


Esto funciona para mí (SLES Linux):

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

El truco ps|grep|kill mencionado en este hilo no funcionaría si un usuario puede ejecutar el script para dos "instancias" en la misma máquina.

jobs -x echo %1 no funcionó para mí (página de manual que no tiene el -x ) pero me dio la idea de probar jobs -p .


Finalmente, he logrado encontrar el proceso de cola usando ps . Gracias a la idea de ennuikiller.

He usado el ps para grep tail de los args y lo mato. Es una especie de truco, pero funcionó. :)

Si puede encontrar una mejor manera, por favor comparta.

Aquí está el guión completo:
(La última versión se puede encontrar aquí: http://docs.karamatli.com/dotfiles/bin/logserver )

if [ -z "$1" ]; then echo Usage: $0 LOGFILE [PORT] exit -1 fi if [ -n "$2" ]; then PORT=$2 else PORT=9977 fi TAIL_CMD="tail -f $1" 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 $1 }'') kill $TAIL_PID } trap "kill_tail; exit 0" SIGINT SIGTERM while true; do ( $TAIL_CMD & ) | nc -l -p $PORT -vvv kill_tail done


Has probado:

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

(no probado)

O bien, con un archivo de comandos si su nc no tiene -c . Es posible que deba tener una nc compilada con la opción GAPING_SECURITY_HOLE . Sí, debe inferir advertencias apropiadas de ese nombre de opción.


La opción --pid a la cola es tu mejor amigo aquí. Le permitirá un control total de la tubería que se ejecuta en segundo plano. lea las opciones de comando de cola para obtener más resistencia en caso de que su archivo sea rotado activamente por otro proceso que podría dejarlo siguiendo un inodo inactivo. El siguiente ejemplo, aunque no se utiliza para procesar los datos, demuestra la restricción "impuesta" en la cola y la capacidad de indicarle que salga en cualquier momento. Esto se usa para medir la presión del servicio en 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


No es una respuesta ideal, pero encontré una solución para un daemon logger en el que trabajé:

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

de $ info tail:

--pid=PID with -f, terminate after process ID, PID dies


Otra opción: use un redireccionamiento a subshell. Esto cambia el orden en que se inician los procesos en segundo plano, ¡así que $! da PID del proceso de tail .

tail -f $1 > >(nc -l -p 9977) & wait $!


Puede almacenar el comando pid del tail en una variable usando solo redirecciones Bash I / O (consulte Cómo obtener el PID de un proceso en una canalización ).

# 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


Qué tal esto:

jobs -x echo %1

%1 es para el primer trabajo en la cadena, %2 para el segundo, etc. jobs -x reemplaza el especificador de trabajo con PID.


Tal vez podrías usar un fifo para que puedas capturar el pid del primer proceso, por ejemplo:

FIFO=my_fifo rm -f $FIFO mkfifo $FIFO tail -f $1 > $FIFO & TAIL_PID=$! cat $FIFO | nc -l -p 9977 kill $TAIL_PID rm -f $FIFO


Una forma sería simplemente hacer un ps -ef y grep para cola con su script ppid


ncat termina automáticamente tail -f al salir (en 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