Discussion:
[Help-bash] How to get stdin from the parent process?
Peng Yu
2018-02-22 04:31:16 UTC
Permalink
Hi,

The `read` in the following example is not able to read from the stdin
of the script.

$ cat main.sh
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:

(
while read -r i
do
echo "$i"
done
) &
wait
$ seq 3 | ./main.sh

I come up with the following solution using a fifo.

$ cat main.sh
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:

fifo=$(mktemp -u)
mkfifo "$fifo"

cat < /dev/stdin > "$fifo" &

(
while read -r i
do
echo "$i"
done < "$fifo"
) &
wait
$ seq 3 | ./main.sh
1
2
3

Does anybody have any better way to solve this problem? Thanks.
--
Regards,
Peng
Pierre Gaston
2018-02-22 07:34:14 UTC
Permalink
Post by Peng Yu
Hi,
The `read` in the following example is not able to read from the stdin
of the script.
$ cat main.sh
#!/usr/bin/env bash
(
while read -r i
do
echo "$i"
done
) &
wait
$ seq 3 | ./main.sh
you can save stdin in another fd that will be inherited, then redirect
stdin explicitely :

#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:
exec 3<&0
(
while read -r i
do
echo "$i"
done
) <&3 &
wait


PS: the relevant part of the manual is:
If a command is followed by a & and job control is not active, the default
standard input for the command is the empty file /dev/null. Otherwise, the
invoked command inherits the file descriptors of the calling shell
as modified by redirections.

So interactively, where job control is enabled, stdin is not redirected
Peng Yu
2018-02-22 14:24:09 UTC
Permalink
you can save stdin in another fd that will be inherited, then redirect stdin
#!/usr/bin/env bash
exec 3<&0
(
while read -r i
do
echo "$i"
done
) <&3 &
wait
Thanks.

In this specific case, I can move "<&3" into "()"? In other words, are
the file handles shared by the parent and the child?

My test case indicates so. But I want to make sure.

exec 3<&0
(
while read -r i
do
echo "$i"
done <&3
) &
wait
--
Regards,
Peng
Pierre Gaston
2018-02-22 14:56:44 UTC
Permalink
Post by Peng Yu
Post by Pierre Gaston
you can save stdin in another fd that will be inherited, then redirect
stdin
Post by Pierre Gaston
#!/usr/bin/env bash
exec 3<&0
(
while read -r i
do
echo "$i"
done
) <&3 &
wait
Thanks.
In this specific case, I can move "<&3" into "()"? In other words, are
the file handles shared by the parent and the child?
My test case indicates so. But I want to make sure.
exec 3<&0
(
while read -r i
do
echo "$i"
done <&3
) &
wait
--
Regards,
Peng
Yes you can, all the file descriptors are generally inherited by the child
processes, what happens with stdin and & is an exception.

Loading...