bash - for - pipe linux command
¿Cómo redirigir la salida estándar del segundo proceso a la entrada estándar del primer proceso? (5)
Tengo dos procesos que necesito para conectar así:
proc1 - envía salida a proc2 proc2 - envía salida a proc1
Hasta ahora, todos los ejemplos de tuberías son de este tipo: proc1 | proc2
Eso está bien, pero ¿cómo puedo hacer que la salida de proc2 vaya a proc1?
Un buen ejemplo sería bueno. Un ejemplo de shell de Windows sería genial :)
Gracias de antemano, Adrian.
Añadiendo más detalles:
Se espera que el sistema funcione como sistema cliente-servidor en el que el cliente trabaja con el servidor en un modelo de interacción solicitud-respuesta. La interacción termina cuando el cliente no tiene más solicitudes.
Ejemplo de interacción: cliente: solicitud1; servidor: respuesta1; cliente: request2; servidor: respuesta2; . . . . cliente: closeRequest; servidor: closeApproved;
En este punto, el servidor sale después de una salida de cliente. Fin del ejemplo.
Parece que una solución como (suponiendo que la tubería está disponible) cliente <tubería | server> pipe no funcionaría (por favor, corríjame) porque en este acuerdo el cliente produce una gran solicitud, la shell canaliza esta gran solicitud al servidor, luego el servidor produce una gran respuesta y finalmente la shell canaliza esta gran respuesta cliente.
Aquí hay un ejemplo de bash que usa echo para proporcionar una entrada inicial y una canalización con nombre para permitir el bucle de retroalimentación:
mkfifo fifo
echo "fifo forever" | cat - fifo | tee fifo
- proc1 (cat) toma entrada desde stdin y fifo
- proc2 (tee) pasa la salida a stdout y fifo
Este es un ejemplo que muestra lo que desea, con dos procesos que toman un solo argumento:
mkfifo fifo
./process1 argument1 < fifo | ./process2 argument1 > fifo
Primero creamos una tubería con nombre llamada fifo
en el directorio actual. Luego ejecutamos process1
con fifo
como entrada, cuya salida pasará por el conducto anónimo |
a la entrada de process2
, cuya salida irá a fifo
, cerrando el ciclo.
Después de salir de ambos procesos, debe eliminar la tubería, de la misma manera que borra un archivo normal:
rm fifo
La mayoría de los shells hacen que esto sea difícil de hacer, por una buena razón: es muy fácil hacer que sus programas se bloqueen, donde cada uno está esperando la entrada del otro. ¿Puede decirnos más sobre qué información está tratando de transmitir? Si solo está tratando de hacer un sistema similar a RPC, probablemente debería usar una biblioteca diseñada para eso.
Parece que un coproceso de bash puede ser lo que quieres. Busque la palabra reservada en el manual de bash.
(Editar: añadiendo esquema de uso simple)
Funciona así:
# start first process as a coprocess to the current shell
coproc proc1
# now ${COPROC[0]} contains the number of an open (input) file descriptor
# connected to the output of proc1, and ${COPROC[1]} the number of an
# open (output) file descriptor connected to the input of proc1.
# start second process, connecting its input- and outputstreams
# to the output- and inputstreams of the first process
proc2 <&${COPROC[0]} >&${COPROC[1]}
# wait on the first process to finish.
wait $COPROC_PID
Si puede tener varios coprocesos, asigne a su proceso un nombre como este:
coproc NAME {
proc1
}
Luego, puede usar NAME
donde se usó COPROC
antes.
Aquí hay un programa de ejemplo completo que usa una función de ping
como proc1 y proc2:
#!/bin/bash
#
# Example program using a bash coprocess to run two processes
# with their input/output streams
#
#
# A function which reads lines of input and
# writes them back to standard output with the
# first char cut off, waiting 5s inbetween.
#
# It finishes whenever an empty line is read or written,
# or at end-of-file.
#
# The parameter $1 is used in debugging output on stderr.
#
function ping ()
{
while read
do
local sending
echo "ping $1: received ''$REPLY''" >&2
[[ -n $REPLY ]] || break
sleep 5s
sending=${REPLY:1}
echo "ping $1: sending ''$sending''" >&2
echo $sending
[[ -n $sending ]] || break
done
echo "ping $1: end" >&2
}
#
# Start first ping process as a coprocess with name ''p1''.
#
coproc p1 {
ping 1
}
# send some initial data to p1. (Not needed if one of the processes
# starts writing before first reading.)
echo "Hello World" >&${p1[1]}
sleep 2.5s
#
# Run second ping process, connecting its default input/output
# to the default output/input of p1.
#
ping 2 <&${p1[0]} >&${p1[1]}
# wait for the coprocess to finish too.
wait $p1_PID
Utiliza dos invocaciones de una función de shell en lugar de programas externos, pero también funcionaría con tales programas. Aquí está la salida (en stderr):
ping 1: received ''Hello World''
ping 1: sending ''ello World''
ping 2: received ''ello World''
ping 2: sending ''llo World''
ping 1: received ''llo World''
ping 1: sending ''lo World''
ping 2: received ''lo World''
ping 2: sending ''o World''
ping 1: received ''o World''
ping 1: sending '' World''
ping 2: received ''World''
ping 2: sending ''orld''
ping 1: received ''orld''
ping 1: sending ''rld''
ping 2: received ''rld''
ping 2: sending ''ld''
ping 1: received ''ld''
ping 1: sending ''d''
ping 2: received ''d''
ping 2: sending ''''
ping 2: end
ping 1: received ''''
ping 1: end
#!/bin/bash
fifo=$(/bin/mktemp -u)
/usr/bin/mkfifo $fifo
# register resources cleanup trap
trap "/bin/unlink $fifo" INT TERM EXIT
# start a background shell redirecting its output to the pipe
(for ((i=0; i < 5; ++i)); do echo "pam pam, i = $i"; sleep 1; done ) 1> $fifo&
# read the output of the background shell from the pipe
while read line 0< $fifo; do
echo "param $line"
done
# wait for child process to terminate
wait