I have a bash script : my.sh
#!/bin/bash
do_sth()
{
sleep 5
}
main()
{
do_sth >/dev/null &
echo do sth in background ...
}
if [ "$1" = "1st_way" ]; then
main
elif [ "$1" = "2nd_way" ]; then
main >/dev/null
fi
The following command returns immediately
./my.sh 1st_way | cat
But, the following command blocks for 5 seconds
./my.sh 2nd_way | cat
I wonder why it is blocking for 5 seconds in the 2nd way.
Consider this script:
#!/bin/bash
main() {
cd /tmp
}
main > /dev/null
echo goodbye
Before bash runs the main
function, it needs to redirect its own standard output to /dev/null
. Then it needs to run the main
function. Then, before executing the echo
command, it needs to restore its standard output to whatever it was before the redirect.
Here's how it does that. To do the redirect, it opens /dev/null
, getting (let's say) file descriptor 3. Then it duplicates its file descriptor 1 (standard output) to the first available fd ≥ 10, getting (let's say) 10. Then it duplicates fd 3 (open on /dev/null
) to fd 1, and closes fd 3.
Later, to undo the redirect, it duplicates fd 10 (open on bash's original standard output) onto fd 1, and closes fd 10.
Okay, now back to your script. All the same things happen when your script says main >/dev/null
, so while main
is executing, fd 10 is open on the shell's original standard output, which is the writable end of the pipe to cat
.
When your main
says do_sth >/dev/null &
, the shell forks. The child shell inherits fd 10, so both the parent and child shells have fd 10 open on the pipe. (Note that the shell knows that it doesn't need to save its standard output here because of the &
making it fork.)
When the child shell, in do_sth
, runs sleep
, it forks to run sleep
and waits for sleep
to exit. So the child shell hangs around for five seconds, and during that time it has fd 10 open on the writable end of the pipe.
The cat
process doesn't read EOF on the readable end of the pipe until all file descriptors on the writable end are closed, which doesn't happen until that child shell exits, which doesn't happen until sleep
exits.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With