Below I have a script that is collecting the process ids of individual commands, and appending them to an array in bash. For some reason as you can see stdout below, the end resulting array just contains one item, the latest id. How can the resulting PROCESS_IDS
array at the end of this script contain all four process ids?
PROCESS_IDS=()
function append {
echo $1
PROCESS_IDS=("${PROCESS_IDS[@]}" $1)
}
sleep 1 && echo 'one' & append $! &
sleep 5 && echo 'two' & append $! &
sleep 1 && echo 'three' & append $! &
sleep 5 && echo 'four' & append $!
wait
echo "${PROCESS_IDS[@]}"
Here is the stdout:
83873
83875
83879
83882
three
one
four
two
83882
Don't send the
append
operation itself to the background. Putting an&
after the content you want to background but before theappend
suffices: Thesleep
andecho
are still backgrounded, but theappend
is not.My guess is thatwhenever you send a function call to the background, it has a copy of the global variable on its own, so they're appending the PID to four independent copies ofPROCESS_IDS
. That's why every function call finds that it is empty and stores a single PID in it.http://www.gnu.org/software/bash/manual/bashref.html#Lists
If you want to collect the outputs from all four function calls, let them write to disk and read the output at the end:
Edit: this is just a proof of concept - don't do it with file system anyway (as William pointed out, this is going to be error prone unless you take care of uniqueness and synchronization). I only wanted to illustrate that you need to find another way of getting the information out of the subshells.