How to keep script from swallowing all of stdin?
I have a script that reads from a pipe in a loop and runs an expect script and a normal shell script in the loop. Both scripts run ssh to another server to grab a piece of data. For example:
cat /tmp/file |
while read a b c d
do
s=`expect-script server1 $b`
c=`ssh $b normal-script`
echo $s $c
done
Even though there are many lines in /tmp/file, the script quits after processing the first line. I suspect that the expect script is swallowing all of stdin so that when it returns, there is nothing left to read. How can I avoid this? I don't want any of the scripts I call to read from the stdin of the main script.
Solution 1:
cat /tmp/file |
while read a b c d
do
{
s=`expect-script server1 $b`
c=`ssh $b normal-script`
echo $s $c
} < /dev/null
done
The { command... }
syntax allows you to apply redirection or piping to a sequence of commands.
I'll also note that you don't need cat
in your example. You could do this:
while read a b c d
do
...
done < /tmp/file
Solution 2:
It's actually ssh
that's slurping up stdin. Just add the -n
option:
c=$( ssh -n $b normal-script )
If you don't want to do that, you can have your shell while
loop read from a different file descriptor, leaving stdin untouched:
while read -u3 a b c d
do
s=$( expect-script server1 $b )
c=$( ssh $b normal-script )
echo $s $c
done 3< /tmp/file
(assuming bash/ksh/zsh for the read -u
option)