Updated to version 4.1.0
# v4.1.0 - 2026-10-18 # - Converted to getopts # - Added configurable logfile (-l) # - Added required option validation # - Improved error handling # # v4.0.0 - 2026-10-18 # - Added logging framework # - Added trap handlers # - Added standardized help # - Fixed syntax issues
This commit is contained in:
1 parent
899eb11a2d
commit
fc26387aeb
1 file changed
+342
-189
+342
-189
@@ -1,223 +1,376 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
SCRIPTNAME="$(basename "$0")"
|
|
||||||
VERSION=3.5.0
|
|
||||||
FILEDATE="2026-07-26"
|
|
||||||
|
|
||||||
echo -e "\033[0m==============================================="
|
###############################################################################
|
||||||
echo -e " $SCRIPTNAME - rsync progress monitor"
|
# Script Name : RsyncMonitor.sh
|
||||||
echo -e " Written by Charlie Silverman"
|
# Author : Charlie Silverman
|
||||||
echo -e " Version: $VERSION"
|
# Version : 4.1.0
|
||||||
echo -e " Release Date: $FILEDATE"
|
# Date : 2026-10-18
|
||||||
echo -e "==============================================="
|
#
|
||||||
|
# Description:
|
||||||
|
# Monitor rsync copy progress by comparing source and destination sizes.
|
||||||
|
# Calculates completion percentage, transfer rate, and estimated time
|
||||||
|
# remaining.
|
||||||
|
#
|
||||||
|
# Revision History
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# v4.1.0 - 2026-10-18
|
||||||
|
# - Converted to getopts
|
||||||
|
# - Added configurable logfile (-l)
|
||||||
|
# - Added required option validation
|
||||||
|
# - Improved error handling
|
||||||
|
#
|
||||||
|
# v4.0.0 - 2026-10-18
|
||||||
|
# - Added logging framework
|
||||||
|
# - Added trap handlers
|
||||||
|
# - Added standardized help
|
||||||
|
# - Fixed syntax issues
|
||||||
|
#
|
||||||
|
# v3.5.0 - 2026-07-26
|
||||||
|
# - Original release
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
SCRIPT_NAME="$(basename "$0")"
|
||||||
|
SCRIPT_VERSION="4.1.0"
|
||||||
|
SCRIPT_DATE="2026-10-18"
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Defaults
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
SRCFOLDER=""
|
SRCFOLDER=""
|
||||||
DSTFOLDER=""
|
DSTFOLDER=""
|
||||||
SLEEP=60
|
SLEEP=60
|
||||||
HELP=false
|
LOGFILE="/tmp/RsyncMonitor.log"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Logging Functions
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
log_info() {
|
||||||
|
local MESSAGE="$1"
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO ] $MESSAGE" | tee -a "$LOGFILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warn() {
|
||||||
|
local MESSAGE="$1"
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN ] $MESSAGE" | tee -a "$LOGFILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
local MESSAGE="$1"
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $MESSAGE" | tee -a "$LOGFILE" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Error Handling
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
error_handler() {
|
||||||
|
local LINE="$1"
|
||||||
|
log_error "Unexpected error on line ${LINE}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
interrupt_handler() {
|
||||||
|
log_warn "Execution interrupted."
|
||||||
|
exit 130
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'error_handler $LINENO' ERR
|
||||||
|
trap interrupt_handler SIGINT SIGTERM
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Banner
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
show_banner() {
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
|
==================================================
|
||||||
|
${SCRIPT_NAME}
|
||||||
|
rsync Progress Monitor
|
||||||
|
|
||||||
|
Author : Charlie Silverman
|
||||||
|
Version : ${SCRIPT_VERSION}
|
||||||
|
Date : ${SCRIPT_DATE}
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Help
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
|
NAME
|
||||||
|
${SCRIPT_NAME}
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
|
||||||
|
${SCRIPT_NAME} -s <source> -d <destination> [options]
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
|
||||||
|
-s <path>
|
||||||
|
Source folder to monitor.
|
||||||
|
|
||||||
|
-d <path>
|
||||||
|
Destination folder to monitor.
|
||||||
|
|
||||||
|
-t <seconds>
|
||||||
|
Sleep interval between scans.
|
||||||
|
|
||||||
|
Default: 60
|
||||||
|
|
||||||
|
-l <file>
|
||||||
|
Log file path.
|
||||||
|
|
||||||
|
Default:
|
||||||
|
/tmp/RsyncMonitor.log
|
||||||
|
|
||||||
|
-h
|
||||||
|
Display help.
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
|
||||||
|
${SCRIPT_NAME} \\
|
||||||
|
-s /home/olduser \\
|
||||||
|
-d /home/newuser
|
||||||
|
|
||||||
|
${SCRIPT_NAME} \\
|
||||||
|
-s /source \
|
||||||
|
-d /destination \
|
||||||
|
-t 300 \
|
||||||
|
-l /var/log/RsyncMonitor.log
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Utilities
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
get_directory_size_mb() {
|
||||||
|
|
||||||
|
local DIR="$1"
|
||||||
|
local MOUNT
|
||||||
|
|
||||||
|
if [[ "${DIR: -1}" == "/" ]]; then
|
||||||
|
MOUNT=$(df "${DIR%?}" | awk 'NR==2 {print $6}')
|
||||||
|
else
|
||||||
|
MOUNT=$(df "$DIR" | awk 'NR==2 {print $6}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$MOUNT" != "$DIR" ]]; then
|
||||||
|
du -sm "$DIR" | awk '{print $1}'
|
||||||
|
else
|
||||||
|
local USED_KB
|
||||||
|
USED_KB=$(df "$DIR" | awk 'NR==2 {print $3}')
|
||||||
|
echo $(( USED_KB / 1024 ))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
format_size() {
|
||||||
|
|
||||||
|
local SIZE_MB="$1"
|
||||||
|
|
||||||
|
if (( SIZE_MB >= 1024 )); then
|
||||||
|
local SIZE_GB
|
||||||
|
SIZE_GB=$(echo "scale=3;$SIZE_MB/1024" | bc)
|
||||||
|
printf "%'.3fGB" "$SIZE_GB"
|
||||||
|
else
|
||||||
|
echo "${SIZE_MB}MB"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Option Processing
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
while getopts ":s:d:t:l:h" opt; do
|
||||||
|
|
||||||
|
case "${opt}" in
|
||||||
|
|
||||||
|
s)
|
||||||
|
SRCFOLDER="$OPTARG"
|
||||||
|
;;
|
||||||
|
|
||||||
|
d)
|
||||||
|
DSTFOLDER="$OPTARG"
|
||||||
|
;;
|
||||||
|
|
||||||
|
t)
|
||||||
|
SLEEP="$OPTARG"
|
||||||
|
;;
|
||||||
|
|
||||||
|
l)
|
||||||
|
LOGFILE="$OPTARG"
|
||||||
|
;;
|
||||||
|
|
||||||
|
h)
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
|
||||||
|
:)
|
||||||
|
echo "Missing argument for -${OPTARG}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
\?)
|
||||||
|
echo "Invalid option: -${OPTARG}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
echo $1
|
|
||||||
IFS="=" read -r command value <<< "$1"
|
|
||||||
echo "Command: $command"
|
|
||||||
echo "Value: $value"
|
|
||||||
echo "Value length: ${#value}"
|
|
||||||
case "$command" in
|
|
||||||
--source)
|
|
||||||
if [ "${#value})" -gt 0 ]; then
|
|
||||||
SRCFOLDER="$value"
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
SRCFOLDER="$2"
|
|
||||||
shift 2
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
--destination)
|
|
||||||
if [ "${#value})" -gt 0 ]; then
|
|
||||||
DSTFOLDER="$value"
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
DSTFOLDER="$2"
|
|
||||||
shift 2
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
--sleep)
|
|
||||||
if [ "${#value})" -gt 0 ]; then
|
|
||||||
SLEEP="$value"
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
SLEEP="$2"
|
|
||||||
shift 2
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
--help)
|
|
||||||
HELP=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "ERROR: Unknown argument: $1"
|
|
||||||
HELP=true
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Startup
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
show_banner
|
||||||
|
|
||||||
|
touch "$LOGFILE" 2>/dev/null || {
|
||||||
|
echo "Unable to write logfile: $LOGFILE"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Validation
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
ERROR=0
|
ERROR=0
|
||||||
|
|
||||||
if [[ "$HELP" != "true" ]]; then
|
if [[ -z "$SRCFOLDER" ]]; then
|
||||||
# Check if source folder exists
|
log_error "Source folder not specified."
|
||||||
if [[ ! -d "${SRCFOLDER}" ]]; then
|
ERROR=1
|
||||||
echo -e "\n\033[0;31mE\e[4mRROR: Source Folder $SRCFOLDER does not exist.\e[0m"
|
|
||||||
ERROR=1
|
|
||||||
fi
|
|
||||||
# Check if destination folder exists
|
|
||||||
if [[ ! -d "${DSTFOLDER}" ]]; then
|
|
||||||
echo -e "\n\033[0;31mE\e[4mRROR: Destination Folder $DSTFOLDER does not exist.\e[0m"
|
|
||||||
ERROR=1
|
|
||||||
fi
|
|
||||||
# Verify that a sleep value was supplied
|
|
||||||
if [ -z "${SLEEP}" ]; then
|
|
||||||
echo -e "\n\033[0;31mE\e[4mRROR: Sleep delay not specified.\e[0m"
|
|
||||||
ERROR=1
|
|
||||||
else
|
|
||||||
# Verify that the supplied sleep value is actually a Number
|
|
||||||
re='^[0-9]+$'
|
|
||||||
if ! [[ $SLEEP =~ $re ]]; then
|
|
||||||
echo -e "\n\033[0;31m\e[4mERROR: Sleep delay invalid.\e[0m"
|
|
||||||
ERROR=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Help display
|
if [[ -z "$DSTFOLDER" ]]; then
|
||||||
if $HELP; then
|
log_error "Destination folder not specified."
|
||||||
cat << EOF
|
ERROR=1
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
./$SCRIPTNAME --source <SRCFOLDER> --destination <DSTFOLDER> --sleep <SECONDS> [OPTIONS]"
|
|
||||||
|
|
||||||
OPTIONS
|
|
||||||
--source <SRCFOLDER>
|
|
||||||
Full or relative path to the source rsync folder to monitor
|
|
||||||
|
|
||||||
--destination <DSTFOLDER>
|
|
||||||
Full or relative path to the destination rsync folder to monitor
|
|
||||||
|
|
||||||
--sleep <SECONDS>
|
|
||||||
The number of seconds to sleep between scanning passes.
|
|
||||||
Default: 60
|
|
||||||
|
|
||||||
--help
|
|
||||||
Display this help message and exit.
|
|
||||||
|
|
||||||
EXAMPLE
|
|
||||||
./$SCRIPTNAME --source /home/olduser --destination /home/newuser --sleep 300"
|
|
||||||
EOF
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Calculating size of $SRCFOLDER..."
|
if [[ ! -d "$SRCFOLDER" ]]; then
|
||||||
|
log_error "Source folder does not exist: $SRCFOLDER"
|
||||||
# Getting the mount point that relates to the source path, stripping off
|
ERROR=1
|
||||||
# the trailing slash if found
|
|
||||||
if [[ "${SRCFOLDER: -1}" = "/" ]]; then
|
|
||||||
SRCMOUNT=$(df ${SRCFOLDER%?} | sed -n '2p' | awk '{print $6}')
|
|
||||||
else
|
|
||||||
SRCMOUNT=$(df $SRCFOLDER | sed -n '2p' | awk '{print $6}')
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Determining the size of the source data. If the source path
|
if [[ ! -d "$DSTFOLDER" ]]; then
|
||||||
# matches a mount point from df, assuming that mount point data
|
log_error "Destination folder does not exist: $DSTFOLDER"
|
||||||
# to be accurate.
|
ERROR=1
|
||||||
if [ $SRCMOUNT != $SRCFOLDER ]; then
|
|
||||||
MEGS=$(du -sm $SRCFOLDER |awk '{print $1}')
|
|
||||||
else
|
|
||||||
MEGS=$(df $SRCFOLDER | sed -n '2p' | awk '{print $3}')
|
|
||||||
MEGS=$(($MEGS / 1024))
|
|
||||||
fi
|
|
||||||
MEGSDISPLAY="${MEGS}MB"
|
|
||||||
MEGSGB=$(echo "scale=2;$MEGS/1024" | bc)
|
|
||||||
if [ $(echo "$MEGSGB > 0" | bc) -ne 0 ]; then
|
|
||||||
NUMFMT=$(printf "%'.3f\n" ${MEGSGB})
|
|
||||||
MEGSDISPLAY="${NUMFMT}GB"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Monitoring $DSTFOLDER..."
|
if ! [[ "$SLEEP" =~ ^[0-9]+$ ]]; then
|
||||||
|
log_error "Sleep value must be numeric."
|
||||||
# Getting the mount point that relates to the destination path, stripping off
|
ERROR=1
|
||||||
# the trailing slash if found
|
|
||||||
if [[ "${$DSTFOLDER: -1}" = "/" ]]; then
|
|
||||||
DSTMOUNT=$(df ${DSTFOLDER%?} | sed -n '2p' | awk '{print $6}')
|
|
||||||
else
|
|
||||||
DSTMOUNT=$(df $DSTFOLDER | sed -n '2p' | awk '{print $6}')
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SECONDSLEFT=1
|
if (( ERROR > 0 )); then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Calculate Source Size
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
log_info "Calculating source size."
|
||||||
|
|
||||||
|
MEGS=$(get_directory_size_mb "$SRCFOLDER")
|
||||||
|
MEGSGB=$(echo "scale=3;$MEGS/1024" | bc)
|
||||||
|
MEGSDISPLAY=$(format_size "$MEGS")
|
||||||
|
|
||||||
|
log_info "Source size: $MEGSDISPLAY"
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Initialize Destination
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
FIRST=$(get_directory_size_mb "$DSTFOLDER")
|
||||||
|
FIRSTGB=$(echo "scale=3;$FIRST/1024" | bc)
|
||||||
|
FIRSTDISPLAY=$(format_size "$FIRST")
|
||||||
|
|
||||||
STARTTIME=$(date +%s)
|
STARTTIME=$(date +%s)
|
||||||
# Determining the current size of the destination data. If the
|
START="$FIRST"
|
||||||
# destination path matches a mount point from df, assuming that
|
|
||||||
# mount point data to be accurate.
|
if (( $(echo "$MEGSGB > 0" | bc) )); then
|
||||||
if [ $DSTMOUNT != $DSTFOLDER ]; then
|
CURRENTPCT=$(echo "scale=0;($FIRSTGB/$MEGSGB)*100" | bc)
|
||||||
FIRST=$(du -sm $DSTFOLDER |awk '{print $1}')
|
|
||||||
else
|
else
|
||||||
FIRST=$(df $DSTFOLDER | sed -n '2p' | awk '{print $3}')
|
CURRENTPCT=0
|
||||||
FIRST=$(($FIRST / 1024))
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FIRSTDISPLAY="${FIRST}MB"
|
|
||||||
FIRSTGB=$(echo "scale=2;$FIRST/1024" | bc)
|
|
||||||
if [ $(echo "$FIRSTGB > 0" | bc) -ne 0 ]; then
|
|
||||||
NUMFMT=$(printf "%'.3f\n" ${FIRSTGB})
|
|
||||||
FIRSTDISPLAY="${NUMFMT}GB"
|
|
||||||
fi
|
|
||||||
|
|
||||||
CURRENTPCT=$(echo "scale=2;($FIRSTGB/$MEGSGB)*100" | bc | cut -d . -f 1)
|
|
||||||
|
|
||||||
START=$FIRST
|
|
||||||
CMDTIME=0
|
|
||||||
CURRENTTIME=$(date '+%Y-%m-%d %H:%M:%S')
|
CURRENTTIME=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
echo -e "[${CURRENTTIME}] \033[0;32m${FIRSTDISPLAY}\e[0m of \033[0;32m${MEGSDISPLAY}\e[0m (\033[0;32m${CURRENTPCT}%\e[0m)\tStarting\t\t| Sleeping ${SLEEP}s..."
|
|
||||||
while (( $SECONDSLEFT > 0 )); do
|
|
||||||
sleep $SLEEP
|
|
||||||
|
|
||||||
# Determining the current size of the destination data. If the
|
echo -e "[${CURRENTTIME}] ${FIRSTDISPLAY} of ${MEGSDISPLAY} (${CURRENTPCT}%) Starting | Sleeping ${SLEEP}s..."
|
||||||
# destination path matches a mount point from df, assuming that
|
|
||||||
# mount point data to be accurate.
|
|
||||||
if [ $DSTMOUNT != $DSTFOLDER ]; then
|
|
||||||
END=$(du -sm $DSTFOLDER |awk '{print $1}')
|
|
||||||
else
|
|
||||||
END=$(df $DSTFOLDER | sed -n '2p' | awk '{print $3}')
|
|
||||||
END=$(($END / 1024))
|
|
||||||
fi
|
|
||||||
|
|
||||||
TIMENOW=$(date +%s)
|
###############################################################################
|
||||||
TIMEDIFF=$(($TIMENOW-$STARTTIME))
|
# Monitor Loop
|
||||||
DOWNLOADED=$(( $END-$START ))
|
###############################################################################
|
||||||
TOTALDOWNLOADED=$(( $END-$FIRST ))
|
|
||||||
if [[ $DOWNLOADED -lt 0 ]]; then
|
|
||||||
DOWNLOADED=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
ENDDISPLAY="${END}MB"
|
while true; do
|
||||||
ENDGB=$(echo "scale=2;$END/1024" | bc)
|
|
||||||
if [[ $(echo "$END > 0" | bc) -ne 0 ]]; then
|
|
||||||
NUMFMT=$(printf "%'.3f\n" ${ENDGB})
|
|
||||||
ENDDISPLAY="${NUMFMT}GB"
|
|
||||||
fi
|
|
||||||
|
|
||||||
CURRENTTIME=$(date '+%Y-%m0%d %H:%M:%S')/
|
sleep "$SLEEP"
|
||||||
CURRENTPCT=$(echo "scale=2;($ENDGB/$MEGSGB)*100" | bc | cut -d . -f 1)
|
|
||||||
|
|
||||||
if [[ "$DOWNLOADED" == "0" ]]; then
|
END=$(get_directory_size_mb "$DSTFOLDER")
|
||||||
echo -e "[${CURRENTTIME}] \033[0;32m${ENDDISPLAY}\e[0m of \033[0;32m${MEGSDISPLAY}\e[0m (\033[0;32m${CURRENTPCT%}\e[0m)\t| No change since last check | Sleeping ${THISSLEEP}s..."
|
ENDDISPLAY=$(format_size "$END")
|
||||||
continue
|
ENDGB=$(echo "scale=3;$END/1024" | bc)
|
||||||
fi
|
|
||||||
|
|
||||||
OVERALLMEGSPERSECOND=$(( $TOTALDOWNLOADED/$TIMEDIFF ))
|
TIMENOW=$(date +%s)
|
||||||
OVERALLSECONDSLEFT=$(( ($MEGS-$END)/$TOTALDOWNLOADED*$TIMEDIFF ))
|
TIMEDIFF=$(( TIMENOW - STARTTIME ))
|
||||||
OVERALLDAYS=$(( $OVERALLSECONDSLEFT/60/60/24 ))
|
|
||||||
OVERALLHOURS=$(( ($OVERALLSECONDSLEFT-$OVERALLDAYS*60*60*24)/60/60 ))
|
DOWNLOADED=$(( END - START ))
|
||||||
OVERALLMINUTES=$(( ($OVERALLSECONDSLEFT-$OVERALLDAYS*60*60*24-$OVERALLHOURS*60*60)/60 ))
|
TOTALDOWNLOADED=$(( END - FIRST ))
|
||||||
OVERALLSECONDS=$(( $OVERALLSECONDSLEFT-$OVERALLDAYS*60*60*24-$OVERALLHOURS*60*60-$OVERALLMINUTES*60 ))
|
|
||||||
echo -e "[${CURRENTTIME}] \033[0;32m${ENDDISPLAY}\e[0m of \033[0;32m${MEGSDISPLAY}\e[0m (\033[0;32m${CURRENTPCT}%\e[0m)\t ~${OVERALLMEGSPERSECOND}MB/s\t| ${OVERALLDAYS}d ${OVERALLHOURS}h ${OVERALLMINUTES}m ${OVERALLSECONDS}s remaining\t| Sleeping ${SLEEP}s..."
|
CURRENTTIME=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
if (( DOWNLOADED <= 0 )); then
|
||||||
|
echo "[${CURRENTTIME}] ${ENDDISPLAY} of ${MEGSDISPLAY} (${CURRENTPCT}%) No change detected | Sleeping ${SLEEP}s..."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( TIMEDIFF <= 0 || TOTALDOWNLOADED <= 0 )); then
|
||||||
|
START="$END"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
OVERALLMEGSPERSECOND=$(( TOTALDOWNLOADED / TIMEDIFF ))
|
||||||
|
|
||||||
|
if (( OVERALLMEGSPERSECOND < 1 )); then
|
||||||
|
OVERALLMEGSPERSECOND=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
REMAINING=$(( MEGS - END ))
|
||||||
|
|
||||||
|
if (( REMAINING < 0 )); then
|
||||||
|
REMAINING=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
OVERALLSECONDSLEFT=$(( REMAINING / OVERALLMEGSPERSECOND ))
|
||||||
|
|
||||||
|
OVERALLDAYS=$(( OVERALLSECONDSLEFT / 86400 ))
|
||||||
|
OVERALLHOURS=$(( (OVERALLSECONDSLEFT % 86400) / 3600 ))
|
||||||
|
OVERALLMINUTES=$(( (OVERALLSECONDSLEFT % 3600) / 60 ))
|
||||||
|
OVERALLSECONDS=$(( OVERALLSECONDSLEFT % 60 ))
|
||||||
|
|
||||||
|
if (( $(echo "$MEGSGB > 0" | bc) )); then
|
||||||
|
CURRENTPCT=$(echo "scale=0;($ENDGB/$MEGSGB)*100" | bc)
|
||||||
|
else
|
||||||
|
CURRENTPCT=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[${CURRENTTIME}] ${ENDDISPLAY} of ${MEGSDISPLAY} (${CURRENTPCT}%) ~${OVERALLMEGSPERSECOND}MB/s | ${OVERALLDAYS}d ${OVERALLHOURS}h ${OVERALLMINUTES}m ${OVERALLSECONDS}s remaining | Sleeping ${SLEEP}s..."
|
||||||
|
|
||||||
|
START="$END"
|
||||||
|
|
||||||
START=$END
|
|
||||||
done
|
done
|
||||||
Reference in new issue
Block a user