This is a proposed version of progress_bar.sh which is backward
compatible with the standard version and adds the capability to show
percentage complete and advance according to the percentage. For the
added behavior 2 additional arguments are the number of SBUs as seen
in the book and the number of seconds in 1 SBU. A third optional
additional argument dubbed slowpoke is whole number of seconds to
sleep if a large percentage of time sleeping is desired. Without the
additional arguments, it behaves like the standard version.
# $Id: progress_bar.sh 3336 2007-03-19 18:27:00Z manuel $
set -e
# Be sure that we know the taget name
[[ -z $1 ]] && exit
TARGET=$1 # Remember the target build we are looking for
MAKE_PPID=$2
# For percentage progress, supply $3,$4 = #SBUs,1SBU
# and optionally supply $5 = slowpoke (see below).
# e.g., sh progress_bar.sh foo $PPID .3 540
#
# If either $3 or $4 is not supplied, this will perform the usual way.
#
# Examples of valid #SBUs: 1, 1.5, 0.1, .5
#
# 1SBU must be a whole number of seconds
#
# External code (or typist) must supply the #SBUs and 1SBU - a difficult job.
#
# Anything supplied in $5 makes it slowpoke -- at least 1 second sleep
# If a number is supplied in $5 -- that many seconds sleep
# e.g., sh progress_bar.sh foo $PPID .1 540 slow (1 second sleep)
# e.g., sh progress_bar.sh foo $PPID .1 540 5 (5 second sleep)
#
# Note: slowpoke
# There are 5 graphic characters per cycle and it sleeps on each one.
# e.g., if 1 second sleep, then 1 second between tests for exit,
# and 5 seconds between position jumps and time/percentage updates.
# Monitored proceess (e.g., Makefile segment) preferably might ensure
# that it (e.g., houskeeping) sleeps at least slowpoke seconds
# to avoid possible sloppy multiple progress_bars behaviors,
# although when one ends the other will continue (so no calamity).
declare -r CSI=$'\e[' # DEC terminology, Control Sequence Introducer
declare -r CURSOR_OFF=${CSI}$'?25l'
declare -r CURSOR_ON=${CSI}$'?25h'
declare -r ERASE_LINE=${CSI}$'2K'
declare -r FRAME_OPEN=${CSI}$'2G['
declare -r FRAME_CLOSE=${CSI}$'63G]'
declare -r TS_POSITION=${CSI}$'65G'
declare -r LINE_WRAP_OFF=${CSI}$'?7l'
declare -r LINE_WRAP_ON=${CSI}$'?7h'
declare -a RESET_LINE=${CURSOR_OFF}${ERASE_LINE}${FRAME_OPEN}${FRAME_CLOSE}
declare -a GRAPHIC_STR="| / - \\ + "
declare -a GRAPHIC_STR10="/ | - \\ - " #backwards STR
declare -i SEC=0 # Seconds accumulator
declare -i PREV_SEC=0
# Prevent segfault on stripping phases
if [[ "$BASHBIN" = "/tools/bin/bash" ]] ; then
SLEEP=/tools/bin/sleep
else
SLEEP=/bin/sleep
fi
function get_eta() {
if [ -z "$1" ] || [ -z "$2" ]; then
return
fi
SBUS=$1
SBU=$2
if [ "${SBUS%.*}.${SBUS#*.}" == $SBUS ]; then
SBUS10=${SBUS%.*}${SBUS#*.} # multiply by 10: bash math has no decimal
else
SBUS10="${SBUS}0" # multiply by 10: bash math has no decimal
fi
SBUS10=$(( 10#$SBUS10 + 0 )) # strip leading zeros
ETA10=$(( $SBUS10 * $SBU))
}
function catch_up_slowpoke() {
if [ -z "$1" ] || [ -z "$2" ]; then
return
fi
# It jumps a bunch and thats what you get for going slow.
# The tradeoff is a high percentage of time spent sleeping.
GET_TO=$1
WE_AT=$2
while [ $GET_TO -gt $WE_AT ]; do
if [ $TOFRO -eq -1 ] && [ $SCREENPOS -gt 3 ]; then
SCREENPOS=$(( $SCREENPOS + $TOFRO ))
write_or_exit "${CSI}${SCREENPOS}G-"
elif [ $TOFRO -eq 1 ] && [ $SCREENPOS -lt 62 ]; then
SCREENPOS=$(( $SCREENPOS + $TOFRO ))
write_or_exit "${CSI}${SCREENPOS}G+"
fi
WE_AT=$(( $WE_AT + 1 ))
done
}
ETA10=0
PCNT=0
PPCNT=0
MOD_PCNT=0
PMOD_PCNT=0
SCREENPOS=3
TOFRO=1
SLOWPOKE=$5
if [ -n "$SLOWPOKE" ]; then
# maybe got a number
SLOWPOKE=${SLOWPOKE##*[^0-9]}
SLOWPOKE=${SLOWPOKE%%[^0-9]*}
SLOWPOKE="0${SLOWPOKE}"
SLOWPOKE=$(( 10#$SLOWPOKE + 0 ))
if [ $SLOWPOKE -eq 0 ]; then
SLOWPOKE=1 # slowpokes have to go a least 1 second
fi
fi
get_eta $3 $4
write_or_exit() {
# make has been killed or failed or run to completion, leave
[[ ! -e /proc/${MAKE_PPID} ]] && echo -n "${CURSOR_ON}" && exit
# Target build complete, leave.
[[ -f ${TARGET} ]] && echo -n "${CURSOR_ON}" && exit
# It is safe to write to the screen
echo -n "$1"
}
# initialize screen
write_or_exit "${RESET_LINE}${TS_POSITION}0 min. 0 sec"
# loop forever..
while true ; do
if [ $ETA10 -gt 0 ]; then
if [ $TOFRO -eq 1 ]; then
GSTRING=${GRAPHIC_STR}
else
GSTRING=${GRAPHIC_STR10}
fi
else
GSTRING=${GRAPHIC_STR}
fi
# Loop through the animation string
for GRAPHIC_CHAR in ${GSTRING}; do
SLEEP_TIME=.1
if [ $ETA10 -gt 0 ]; then
write_or_exit "${CSI}${SCREENPOS}G${GRAPHIC_CHAR}"
if [ $ETA10 -lt 400 ]; then
SLEEP_TIME=.05 # unlikely
fi
if [ -n "$SLOWPOKE" ]; then
SLEEP_TIME=$SLOWPOKE # for some like it slow
fi
else
write_or_exit "${CSI}$((SEC + 3))G${GRAPHIC_CHAR}"
fi
#$SLEEP .12 # This value MUST be less than .2 seconds.
#$SLEEP .1 # Sleep time is also part of the fudgework
$SLEEP $SLEEP_TIME # Sleep time is also part of the fudgework
done
# A BASH internal variable, the number of seconds the script
# has been running. modulo convert to 0-59
SEC=$(($SECONDS % 60))
# Detect rollover of the seconds.
if [ $ETA10 -eq 0 ]; then
(( PREV_SEC > SEC )) && write_or_exit "${RESET_LINE}"
(( PREV_SEC = SEC ))
fi
# Display the accumulated time. div minutes.. modulo seconds.
write_or_exit "${TS_POSITION}$(($SECONDS / 60)) min. $SEC sec "
if [ $ETA10 -gt 0 ]; then
PCNT=$(( $SECONDS * 1000 / $ETA10 ))
if [ $PCNT -gt $PPCNT ]; then
if [ $SCREENPOS -gt 7 ]; then
# print percentage within left bracket
write_or_exit "${CSI}3G${PCNT}% "
fi
fi
PPCNT=$PCNT
# Allow the thing to go back and forth since elapsed time
# might exceed SBU estimates and/or fudgework.
# It would rarely be exactly 100% because SBU times are approximate.
MOD_PCNT=$(( $PCNT % 100 ))
if [ $PMOD_PCNT -gt $MOD_PCNT ]; then
TOFRO=$(( $TOFRO * -1 ))
fi
PMOD_PCNT=$MOD_PCNT
SCRN_PCNT=$(( $SCREENPOS - 3 ))
if [ $TOFRO -eq -1 ]; then
SCRN_PCNT=$(( 60 - $SCREENPOS ))
fi
SCRN_PCNT=$(( $SCRN_PCNT * 100 / 60 ))
if [ $(( $PCNT % 100 )) -gt $SCRN_PCNT ]; then
# advance if stays in bounds
if [ -n "$SLOWPOKE" ]; then
catch_up_slowpoke $(( $PCNT % 100 )) $SCRN_PCNT
fi
if [ $TOFRO -eq -1 ] && [ $SCREENPOS -gt 3 ]; then
SCREENPOS=$(( $SCREENPOS + $TOFRO ))
elif [ $TOFRO -eq 1 ] && [ $SCREENPOS -lt 62 ]; then
SCREENPOS=$(( $SCREENPOS + $TOFRO ))
fi
fi
fi
done
exit
--
http://linuxfromscratch.org/mailman/listinfo/alfs-discuss
FAQ: http://www.linuxfromscratch.org/faq/
Unsubscribe: See the above information page