I got into thinking about this example...

> while read rivi; do ssh oiva echo "'$rivi'"</dev/stdin | tr a a; done < 
> tmp/koe.c

One could be tempted to think that this '</dev/stdin' here does completely
nothing (we're redirecting STDIN from wherever it happened to be in the first
place). But the point is, this way we don't end up reading it out. We actually
have a copy of the STDIN of the parent shell. One way to confirm this:

--clip--
t...@aulis:~$ while read rivi; do ssh oiva "echo -ne '$rivi\t';while read line; 
do echo; done|wc -l"</dev/stdin | tr a a; done < tmp/koe.c
void f( char ** const w ) {};   9
        9
int main( int argc, char * argv[] ) {   9
        9
char foo[10];   9
char * p = &foo[0];     9
        9
f(&p);  9
};      9
--clip--

Notice how the number of lines waiting to be read is always 9, the length of
the original file. And how reading all those lines doesn't exhaust the original
stream. So, same file, different FD, like I said before...

Also:

--clip--
t...@aulis:~$ while read rivi; do ssh oiva "echo -ne '$rivi\t';while read line; 
do echo; done|wc -l" | tr a a; done < tmp/koe.c
void f( char ** const w ) {};   8
t...@aulis:~$ 
--clip--

This always yields the same result: the outer shell loop reads the first line,
the one executed remotely reads the remaining 8 lines. So the lines should be
there to be read, so the parent shell cannot actually read them out...

Also, if I insert a sleep in the remote command, like this:

--clip--
t...@aulis:~$ while read rivi; do ssh oiva "echo '$rivi'; sleep 1" | tr a a; 
done < tmp/koe.c
void f( char ** const w ) {};
t...@aulis:~$ 
--clip--

I end up constantly seeing only the first line. So it appears that it isn't a
case of buffering, if what happens is that with a slow ssh process, I never see
more than one line (should be the other way around).  I would guess that as the
ssh command (echo '$rivi') exits, it stops reading the lines from stdin, and
the next iteration of the loop begins where we were left in stdin. But
apparently this isn't so, because we always see n /first/ lines of input, not
the first line and then some other lines. So another guess: bash keeps track of
its position in the file (stream) and seeks back after its child ssh process
exits (or more likely, the bash process probably has its own idea of file
position, separate from its child ssh process), but if the ssh process has time
to read until EOF, the ssh process closes the file, and as it's the same FD as
in the parent process, 'read rivi' fails and the while loop ends.

(As a side note: if the line read contains a "'", we're likely to end up in
trouble if the rest of the line contains something that bash interprets.)


--Janne
-- 
Janne Peltonen <janne.pelto...@sange.fi> PGP Key ID: 0x9CFAC88B



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to