What I want to achieve is to have a shell script hooked up onto a fifo and react to certain commands that would read out (with the usual read command). Now this seems trivial but , by my surprise, the read command does not react as I expected it to. See following simple script :
#!/bin/bash
while true; do
read ONE_SENTENCE
echo Simon says : ${ONE_SENTENCE}
sleep 1
done
I launch this by "./test.sh < in.pipe", where in.pipe is "mkfifo in.pipe"
Now, if I write sthing in the pipe with "echo test1 > in.pipe" I get the following result :
stc@host:~$ ./test.sh < in.pipe
Simon says : test1
Simon says :
Simon says :
Simon says :
Simon says :
Simon says :
Simon says :
Simon says :
In other words, read doesn't block, it find always sthing to read out. What am I missing ? Obviously, I want read to block until new data
CodePudding user response:
The key is to only output ONE_SENTENCE
upon a successful read, e.g.
while :; do
if read ONE_SENTENCE; then
[ "$ONE_SENTENCE" = quit ] && break ## convenient quit ability
printf "Simon says : %s\n" "$ONE_SENTENCE" ## output only on good read
fi
sleep 1
done
No output from the pipe is produced except on a valid read of a line from the fifo.
A slight variation that conveniently sets the fifo up for you and deletes it on script exit. (upper-case variables are avoided below)
#!/bin/bash
pipe=in.pipe
trap "rm -r $pipe" EXIT
[ -p "$pipe" ] || mkfifo "$pipe"
while :; do
if read line; then
[ "$line" = quit ] && break
printf "Simon says : %s\n" "$line"
fi
sleep .5
done < "$pipe"
The script does the exact same thing (other than a 1/2 sec sleep
, but it creates the fifo and sets a trap
to remove it before entering the read-loop.
CodePudding user response:
Many thx for the answer. In the meanwhile I've managed to get what I wanted this way
#!/bin/bash
while true; do
read ONE_SENTENCE < in.pipe
echo Simon says : ${ONE_SENTENCE}
sleep 1
done
The above code blocks (as expected)... but I still don't understand why the first script didn't block... anyways, one way or the other, it works