Re: non-blocking stdin from bash
On Sun, 2018-08-12 at 10:36 +0200, tomas@tuxteam.de wrote:
> On Sun, Aug 12, 2018 at 01:26:40AM -0400, Jim Popovitch wrote:
> > On Sun, 2018-08-12 at 00:48 +0200, tomas@tuxteam.de wrote:
> > > On Sat, Aug 11, 2018 at 06:08:34PM -0400, Jim Popovitch wrote:
> > > > Hello!
> > > >
> > > > What's the best way to grab anything that's in stdin into a
> > > > variable
> > > > inside a bash script, but won't block if stdin is null?
> > >
> > > I think read is your friend (at least in bash). It has an option
> > > -t <timeout>, which you can set to zero, for it to just grab
> > > what's
> > > available at the moment without waiting (cf "help read" while in
> > > the bash for more details, like setting a delimiter, etc.)
> > >
> > > HTH
> > > -- tomás
> >
> > Thanks for the reply tomás. I'm trying to avoid using read because
> > of
> > the 1 sec minimum timeout.
>
> Not on bash, at least. According to the docs, "-t 0" is a timeout of
> zero. Experiments confirm that:
>
> tomas@trotzki:~$ time read -t 0
>
> real 0m0.000s
> user 0m0.000s
> sys 0m0.000s
>
> (Of course, 0 is too optimistic here, but it's sub-millisecond).
> Fractional times work too:
>
> tomas@trotzki:~$ time read -t 0.05
>
> real 0m0.050s
> user 0m0.000s
> sys 0m0.000s
>
> Finally, you can use timeout to read incomplete (i.e. non-terminated)
> input, like so:
>
> tomas@trotzki:~$ time echo -n mumble | bash -c 'read -t 0.01 foo ;
> echo $foo'
> mumble
>
> real 0m0.004s
> user 0m0.000s
> sys 0m0.000s
>
> Note that "-t 0" won't work here: the "read" at the right is there
> before
> the "echo" at the left, so read turns out empty...
>
> > This may seem odd, but 1 sec is 100+
> > times
> > longer than grep'ing/awk'ing/sed'ing the contents of a variable, so
> > I'm
> > trying to find a faster way to read stdin.
>
> No, it doesn't seem odd. Sometimes 1 sec is too much (sometimes 1msec
> is
> too much, too :-)
>
> But I think (used wisely) read is still your friend!
>
> Note that I didn't check how much of this is bashism. Document your
> requirements :-)
:-)
Turns out I had mis-read your first reply as "-t 1", chiefly because
that was all that I had found before posting here. What now works for
me avoids the -t param:
while read stdin_line
do
MSG=$MSG"\n"$stdin_line
done < /dev/stdin
Thanks again,
-Jim P.
Reply to: