Help with Bash piped while-read and a read user input at the same time


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Help with Bash piped while-read and a read user input at the same time
# 8  
Old 02-24-2012
If this were C, you'd set the file descriptors non-blocking and use the select() system call to tell when one file descriptor or the other has data ready to be read at any particular time.

The closest shell has to non-blocking I/O is terminal timeouts, which really isn't the same thing.

You could read both and cram them into a fifo I suppose... A bit of a kludge but fifos can combine two writers into one reader. As long as you write entire lines to the fifo, they ought to come out in the order you wrote them.

(That's why I didn't use cat to read from the terminal. It might not care about line boundaries. It might even block until it has x lines input or EOF...)

Code:
#!/bin/sh

# Create fifo
mkfifo /tmp/$$.fifo

# Read the logfile in the background, cram into fifo
( tail -f server.log > /tmp/$$.fifo ) &
P1="$!"

# Read from the fifo and use it here, in the background
(       while [ -e /tmp/$$.fifo ] && IFS="" read LINE
        do
                echo "got line $LINE"

                [ "$LINE" = "USER quit" ] && break
        done < /tmp/$$.fifo

        echo "Quitting" >&2

        rm /tmp/$$.fifo
        kill "$P1"
        kill "$$"       ) &

# Save its PID in case we need to kill it
P2="$!"

# Guarantee we kill all our background processes on exit
trap "rm -f /tmp/$$.fifo ; kill $P1 $P2 ; wait" EXIT

# Read from terminal, write to fifo.
# this MUST happen in the foreground!
while [ -e "/tmp/$$.fifo" ] && IFS="" read LINE
do
        echo "USER $LINE"
done > /tmp/$$.fifo

This will spam error messages when you quit about killing nonexistent processes, and things dying uncleanly... but if it didn't at least try to kill them there's situation it could leave things hanging around.

---------- Post updated at 12:46 PM ---------- Previous update was at 12:23 PM ----------

Here's a less kludgy version which avoids the spammy messages, uses a pipe instead of a fifo, and puts the combined read at the bottom:

Code:
#!/bin/bash

(       tail -f server.log &
        trap "" SIGPIPE

        while read LINE && echo "USER $LINE"
        do
                true
        done

        echo "SIGPIPE happened I guess, quitting" >&2

        kill $!
        wait 
) | while read INPUT
do
        [ "$INPUT" = "USER quit" ] && break
        echo "got $INPUT"
done

'tail -f' runs in the background, writing to standard output -- i.e. the pipe -- by itself.

I trap SIGPIPE so that the subshell doesn't get killed instantly when the 'while read INPUT' loop quits. That might prevent it from killing the background 'tail -f', or at the very least, print warning messages about the subshell being killed abnormally.

Meanwhile the other while loop reads from the terminal and echoes lines straight back out to standard output -- i.e. the pipe again, the same pipe.

The subshell should detect when the main reading loop quits by detecting when 'echo' fails, allowing it to kill the 'tail -f' cleanly before terminating normally.
This User Gave Thanks to Corona688 For This Post:
# 9  
Old 02-26-2012
Thanks, just what I needed to know!
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Unable to read user input inside a loop

Hi, This query is a part of a much more lengthy script. I wish to look for all the files in a folder named "data" which in this case has two files i.e. plan.war and agent.properties. For all the files found under data I wish to ask the user as to where they wish copy the files to. Below,... (14 Replies)
Discussion started by: mohtashims
14 Replies

2. Shell Programming and Scripting

Shell read command is not waiting for user input

Hi, i am working on one automation , for that i have writing one shell program that take user input in "while read line" block. but read command is taking value that is readed by While block. while read line; do command 1; command 2 echo -n "Do you want to continute > " read rsp... (2 Replies)
Discussion started by: ranvijaidba
2 Replies

3. Shell Programming and Scripting

Perl to read user input

I am creating a bash that uses perl . The below code closes before the input is entered. If I run the perl as a .pl it is fine. What am I doing wrong? Thank you :). #!/bin/bash cd 'C:\Users\cmccabe\Desktop\wget' wget -O getCSV.txt http://xxx.xx.xxx.xxx/data/getCSV.csv print... (4 Replies)
Discussion started by: cmccabe
4 Replies

4. Shell Programming and Scripting

BASH - read does not wait for user input in some circumstances

Hello. I am running 2 scripts : script_1 and script_2 These scripts are run as root Script 2 contains : #!/bin/bash # # ~/bin/script_2 # E_BAD_PARAM=115 # date2stamp () { date --date "$1" +%Y-%m-%d___%H:%M:%S } # USER_NAME=$1 NB_PARAM=$# PARAM0=$0 (2 Replies)
Discussion started by: jcdole
2 Replies

5. Shell Programming and Scripting

Using read to prompt for editable user input in Bash 3

Below is a simple script to prompt for user input while suggesting an editable default value at the prompt: shortname=user1 read -e -i $shortname -p "Please enter the username you would like to add: " input USERNAME="${input:-$shortname}" Please enter the username you would like to add:... (3 Replies)
Discussion started by: woodson2
3 Replies

6. Shell Programming and Scripting

Solaris- Read command from user input

I need to write a bourne shell script (solaris 10) that accepts input from the user. The input will be a command- any command like ls/ pwd/ mv etc. After the input is read, the shell must execute the command supplied by the user. I know we use read to play with user inputs. Just not sure how to... (2 Replies)
Discussion started by: PDManc
2 Replies

7. AIX

Read input data within a specified period of time

Hi All, I am working on a script which requires an input from user within one 1 min. So if the user gives the required input within 1 min., it will execute on the basis of input provided by the user.Other wise it will execute on a default value(hard coded inside the script). Now, I am... (19 Replies)
Discussion started by: rajsharma
19 Replies

8. Shell Programming and Scripting

BASH - read use a path as input

I am trying to script simply data transfer. I would like to have the user input the source "SRC" (/Volumes/DriveName/Users/johnq123) and then name the directory that the copied information will go to, "DST" . put I can't get it to work - #!/bin/bash ... (8 Replies)
Discussion started by: dropkick888
8 Replies

9. UNIX for Dummies Questions & Answers

How to read a line of text from user input?

Hiii I wanna a read a line of text from standard input. The user enter data like this way name phone_no month1_salary month2_salary that is user enter the name ,phone no and salary of 2 months in a single line by giving spaces. I wanna add the 3rd and 4th fields ...ie add both... (4 Replies)
Discussion started by: krishnampkkm
4 Replies

10. UNIX for Dummies Questions & Answers

getline to read input from a user

Hi, The gcc compiler has warned about using gets(), so I've been trying my hand at getline. Problem is that I've been able to read from a file, but what I really need is to read from a user's input. I want to use getline like a scanf() command, but I can't figure what to substitute for the fp... (6 Replies)
Discussion started by: sdsd
6 Replies
Login or Register to Ask a Question