bash - redirect specific output from 2nd script back to stdin of 1st program?
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 +---------------+ +---------------+
--------->| 开发者_如何学JAVA |--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
An additional expect
-like software tool would be empty
!
http://empty.sourceforge.net
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..
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.sh
is 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
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
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
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
精彩评论