224 lines
6.1 KiB
Bash
224 lines
6.1 KiB
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"
|
|
echo -e " Written by Charlie Silverman"
|
|
echo -e " Version: $VERSION"
|
|
echo -e " Release Date: $FILEDATE"
|
|
echo -e "==============================================="
|
|
|
|
SRCFOLDER=""
|
|
DSTFOLDER=""
|
|
SLEEP=60
|
|
HELP=false
|
|
|
|
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
|
|
|
|
ERROR=0
|
|
|
|
if [[ "$HELP" != "true" ]]; then
|
|
# Check if source folder exists
|
|
if [[ ! -d "${SRCFOLDER}" ]]; then
|
|
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
|
|
|
|
# Help display
|
|
if $HELP; then
|
|
cat << EOF
|
|
|
|
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
|
|
|
|
echo "Calculating size of $SRCFOLDER..."
|
|
|
|
# Getting the mount point that relates to the source path, stripping off
|
|
# 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
|
|
|
|
# Determining the size of the source data. If the source path
|
|
# matches a mount point from df, assuming that mount point data
|
|
# to be accurate.
|
|
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
|
|
|
|
echo "Monitoring $DSTFOLDER..."
|
|
|
|
# Getting the mount point that relates to the destination path, stripping off
|
|
# 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
|
|
|
|
SECONDSLEFT=1
|
|
STARTTIME=$(date +%s)
|
|
# Determining the current size of the destination data. If the
|
|
# destination path matches a mount point from df, assuming that
|
|
# mount point data to be accurate.
|
|
if [ $DSTMOUNT != $DSTFOLDER ]; then
|
|
FIRST=$(du -sm $DSTFOLDER |awk '{print $1}')
|
|
else
|
|
FIRST=$(df $DSTFOLDER | sed -n '2p' | awk '{print $3}')
|
|
FIRST=$(($FIRST / 1024))
|
|
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')
|
|
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
|
|
# 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))
|
|
DOWNLOADED=$(( $END-$START ))
|
|
TOTALDOWNLOADED=$(( $END-$FIRST ))
|
|
if [[ $DOWNLOADED -lt 0 ]]; then
|
|
DOWNLOADED=0
|
|
fi
|
|
|
|
ENDDISPLAY="${END}MB"
|
|
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')/
|
|
CURRENTPCT=$(echo "scale=2;($ENDGB/$MEGSGB)*100" | bc | cut -d . -f 1)
|
|
|
|
if [[ "$DOWNLOADED" == "0" ]]; then
|
|
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..."
|
|
continue
|
|
fi
|
|
|
|
OVERALLMEGSPERSECOND=$(( $TOTALDOWNLOADED/$TIMEDIFF ))
|
|
OVERALLSECONDSLEFT=$(( ($MEGS-$END)/$TOTALDOWNLOADED*$TIMEDIFF ))
|
|
OVERALLDAYS=$(( $OVERALLSECONDSLEFT/60/60/24 ))
|
|
OVERALLHOURS=$(( ($OVERALLSECONDSLEFT-$OVERALLDAYS*60*60*24)/60/60 ))
|
|
OVERALLMINUTES=$(( ($OVERALLSECONDSLEFT-$OVERALLDAYS*60*60*24-$OVERALLHOURS*60*60)/60 ))
|
|
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..."
|
|
|
|
START=$END
|
|
done
|