Why does 'jobs' always return a line for finished processes when run in a subshell within a script?
6
votes
1
answer
999
views
Normally, when a job is launched in the background,
jobs
will report that it is finished the first time it is run after the job's completion, and nothing for subsequent executions:
$ ping -c 4 localhost &>/dev/null &
[1] 9666
$ jobs
[1] + Running ping -c 4 localhost &> /dev/null &
$ jobs
[1] + Done ping -c 4 localhost &> /dev/null
$ jobs ## returns nothing
$
However, when run in a subshell within a script it seems to always return a value. This script will never exit:
#!/usr/bin/env bash
ping -c 3 localhost &>/dev/null &
while [[ -n $(jobs) ]]; do
sleep 1;
done
If I use tee
in the [[ ]]
construct to see the output of jobs
, I see that it is always printing the Done ...
line. Not only once as I expected but, apparently, for ever.
What is even stranger is that running jobs
within the loop causes it to exit as expected:
#!/usr/bin/env bash
ping -c 3 localhost &>/dev/null &
while [[ -n $(jobs) ]]; do
jobs
sleep 1;
done
Finally, as pointed out by @muru, the first script works as expected and exits if run from the commandline:
$ ping -c 5 localhost &>/dev/null &
[1] 13703
$ while [[ -n $(jobs) ]]; do echo -n . ; sleep 1; done
...[1] + Done ping -c 5 localhost &> /dev/null
$
This came up when I was answering a question on Super User so please don't post answers recommending better ways of doing what that loop does. I can think of a few myself. What I am curious about is
1. Why does jobs
act differently within the [[ ]]
construct? Why will it always return the Done...
line while it doesn't when run manually?
2. Why does running jobs
within the loop change the behavior of the script?
Asked by terdon
(251605 rep)
Mar 24, 2015, 11:23 AM
Last activity: Jun 11, 2024, 05:51 PM
Last activity: Jun 11, 2024, 05:51 PM