Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to redirect stdout of 2nd process back to stdin of 1st process?

Tags:

bash

shell

pipe

I have two processes which I need to connect like this:

proc1 -- sends output to proc2 proc2 -- sends output to proc1

So far, all pipe examples are of this kind: proc1 | proc2

That's nice, but how do I make the output of proc2 go to proc1?

A bash example would be nice. A Windows shell example would be great :)

Thanks in advance, Adrian.

Adding more details:

The system is expected to work as client-server system in which the client works with the server in a request-response interaction model. The interaction ends when the client has no more requests.

Interaction example: client: request1; server: response1; client: request2; server: response2; . . . . client: closeRequest; server: closeApproved;

At this point the server exits following a client exit. End of example.

It seems that a solution like (assuming pipe is available) client < pipe | server > pipe would not work (please correct me) because in this arrangement the client produces one big request, the shell pipes this big request to the server, then the server produces one big response, and finally the shell pipes this big response to the client.

like image 725
Adrian Herscu Avatar asked Feb 26 '11 19:02

Adrian Herscu


People also ask

How to redirect the output of ls command in a file?

to redirect the output of the ls command into a file called "ls. out" in your home directory. Remember that the tilde (~) is Unix shorthand for your home directory. In this command, the ls command will list the contents of the /tmp directory.

How do you redirect stdin stdout and stderr to a file?

Redirecting stdout and stderr to a file: The I/O streams can be redirected by putting the n> operator in use, where n is the file descriptor number. For redirecting stdout, we use “1>” and for stderr, “2>” is added as an operator.

Is stdout shared between processes?

Yes they share the same location.

Does each process have its own Stdin?

A process executes a program; you can have multiple processes executing the same program, but each process has its own copy of the program within its own address space and executes it independently of the other copies.” Every process is initialized with three open file descriptors called stdin , stdout , and stderr .

What happens when you redirect stdin and stdout to pipes?

A common problem when people create a process and redirect both stdin and stdout to pipes is that they fail to keep the pipes flowing. Once a pipe clogs, the disturbance propagates backward until everything clogs up. Here is a common error, in pseudocode:

How do I redirect a stderr file to stdout?

It is a common practice to redirect the stderr with the standard output of a program to store everything in a single file. Here is the command syntax for redirecting stderr to stdout: > out redirects redirect the stdout to samplefile.txt, and 2>&1 will redirect the stderr to the current location of stdout.

How does it work with stdin and stdout in Linux?

It uses the inherited handles for STDIN and STDOUT to access the pipe created by the parent. The parent process reads from its input file and writes the information to a pipe. The child receives text through the pipe using STDIN and writes to the pipe using STDOUT.

How do I redirect process I/O using named pipes?

Note that named pipes can also be used to redirect process I/O. The CreatePipe function uses the SECURITY_ATTRIBUTES structure to create inheritable handles to the read and write ends of two pipes.


1 Answers

It looks like a bash coprocess may be what you want. Look up the coproc reserved word in the bash manual.


(Edit: adding simple usage scheme)

It works like this:

# 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

If you may have multiple coprocesses, give your process a name like this:

coproc NAME {
    proc1
}

Then you can use NAME wherever COPROC was used before.


Here is a complete example program using a ping function as proc1 and 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

It uses two invocations of a shell function instead of external programs, but it would work with such programs too. Here is the output (on 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
like image 163
Paŭlo Ebermann Avatar answered Nov 09 '22 23:11

Paŭlo Ebermann