I'm trying to achieve a dynamic progress bar in bash script, the kind we see when installing new packages. In order to do this, a randomtask would call a progressbar script as a background task and feed it with some integer values.
The first script uses a pipe to feed the second.
#!/bin/bash
# randomtask
pbar_x=0 # percentage of progress
pbar_xmax=100
while [[ $pbar_x != $pbar_xmax ]]; do
echo "$pbar_x"
sleep 1
done | ./progressbar &
# do things
(( pbar_x++ ))
# when task is done
(( pbar_x = pbar_xmax ))
Hence, the second script needs to constantly receive the integer, and print it.
#!/bin/bash
# progressbar
while [ 1 ]; do
read x
echo "progress: $x%"
done
But here, the second script doesn't receive the values as they are updated. What did I do wrong ?
I'm on WSL, which means I can't use mkfifo. And coproc seemed to perfectly answer my need, so I searched and eventually found this: coproc usage with exemples [bash-hackers wiki].
We start the process with coproc
and redirect its output to stdout:
{ coproc PBAR { ./progressbar; } >&3; } 3>&1
Then we can access its in and out via file descriptors ${PBAR[0]}
(output) and ${PBAR[1]}
(input)
echo "$pbar_x" >&"${PBAR[1]}"
randomtask
#!/bin/bash
pbar_x=0 # percentage of progress
pbar_xmax=100
{ coproc PBAR { ./progressbar; } >&3; } 3>&1
while (( pbar_x <= 10)); do
echo $(( pbar_x++ )) >&"${PBAR[1]}"
sleep 1
done
# do things
echo $(( pbar_x++ )) >&"${PBAR[1]}"
# when task is done
echo $(( pbar_x = pbar_xmax )) >&"${PBAR[1]}"
progressbar
#!/bin/bash
while read x; do
echo "progress: $x%"
done
Please note that :
The coproc keyword is not specified by POSIX(R).
The coproc keyword appeared in Bash version 4.0-alpha