bash - redirect specific output from 2nd script ba

2019-08-02 15:15发布

问题:

I have a little program, let's call it "program" by simplicity which has "normal" behaviour. It takes information from the stdin (normally typed in by the user in the keyboard) and prints out via stdout/stderr. I want to automate a process and therefore redirect stdout/stderr into "my little bash script" (which could also be another program in C/C++). It takes it as it's standard input and filters it. This means leaving out unimportant information.. and adding further information generated by the bash script itself. The output is shown on the sreen (printed out by the echo command).

This is working so far:

program --verbose 2>&1 | ./mylittlebashscript.sh

Scheme:

 stdin     +---------------+              +---------------+
 --------->|               |--stdout--+-->|      my       |-->screen
           |    program    |          |   |    little     |
           |               |--stderr--|   |  bash script  |
           +---------------+              +---------------+

Now I want to go one step further: The program expects input from the user which I want to give automatically by my little bash script. For example it prompts the user to enter the path to a specific file. The path is known by my little bash script and the bash script knows when the program is waiting for input (as the last line being printed out contains something which is "greped"). How can I pipe back some information out of my bash script? I do not want to pipe back all the stdout because several information only needs to be displayed on the screen and the program would not like this output.

New scheme:

 (stdin?)  +---------------+              +---------------+   (stdout?)
 -------+->|               |--stdout--+-->|      my       |-->screen
        |  |    program    |          |   |    little     |
        |  |               |--stderr--+   |  bash script  |----+(maybe
        |  +---------------+              +---------------+    | stderr?)
        |                                                      |
        +------------------------------------------------------+

At the moment I am not very familiar with Linux yet. I guess there is a possibility working with cat, fifos, tee and pipes/redirections. Unfortunately I haven't brought it to life so far.

I'd really be happy about a little example! Thank you very much!

Cheers Matthias

PS: I think this thread is related: how to redirect stdout of 2nd process back to stdin of 1st process?

Edit: Ok, for fruther explanation I took my test files from my test machine:

I replaced "program" by another batch file called input.sh:

#!/bin/bash
echo "input.sh: give me input, waiting for input 1"
read x
echo $x
echo "input.sh: give me input, waiting for input 2"
read x
echo $x

And I got a second one ("mylittlebashscript.sh"), now called inter.sh to process:

#!/bin/bash
echo "inter.sh: start"
while read line ; do
  echo "inter.sh: line>$line"
  notfound=$(echo $line | grep "waiting")
  if [[ "$notfound" ]]; then
    echo "inter.sh: input sh seems to wait for input! putting something in the fifo"
    #echo "banana" > testfile
    #echo "I am the stderr" >&2
  fi

done
echo "inter.sh: end"
exit

回答1:

An additional expect-like software tool would be empty!

http://empty.sourceforge.net



回答2:

Did you try, as an answer the thread you linked states:

mkfifo fifo
program --verbose < fifo 2>&1 | ./mylittlebashscript.sh | tee fifo

?

Maybe, you should make your script print out some text before waiting for input, in order to avoid getting stuck in a waiting loop..



回答3:

You may also want to consider a client / server model for this kind of task.

See: BASH: Best architecture for reading from two input streams

On a general note, if the stdin of input.shis not a terminal (but rather redirected from a fifo), you have to read explicitly from the controlling terminal device /dev/tty to enable / get user input.

read x < /dev/tty  # in input.sh

./input.sh < fifo 2>&1 | ./inter.sh 2>fifo


回答4:

This sounds like a job for expect! With an expect script, you launch the program from the expect script, which acts as a wrapper that listens for certain patterns in stdout and types stuff into stdin in response. For example, an excerpt that would answer your input.sh script:

#!/usr/bin/expect -f

spawn input.sh
expect ".+input 1"
send "something cool\r"
expect ".+input 2"
send "also cool\r"
expect eof


回答5:

Here's a small empty snippet scripting a simple telnet session in Bash.

# http://empty.sourceforge.net
cd empty-0.6.18b && man ./empty.1
empty -h 
empty -f -L >(tee empty.log) telnet
empty -l

empty -s <<EOF
display
status
help
quit
EOF

empty -k
cat empty.log


回答6:

Maybe also play around with the following approach if your automatic user input requirements are not too complex.

#!/bin/bash
# input.sh
echo "input.sh being busy ..."
sleep 10
echo "input.sh: give me input, waiting for input 1"
read x #</dev/tty
echo $x
echo "input.sh: give me input, waiting for input 2"
read x #</dev/tty
echo $x
echo "input.sh continuing ..."


(
echo a
sleep 1
echo b
sleep 1
exec 1>/dev/tty  # redirect anything that would go to stdout/pipe to the screen
ls
#./mylittlebashscript.sh
#./inter.sh
) | ./input.sh   # do not read from /dev/tty in input.sh