Mis Particiones y Por qué

El único comentario que haría es que a medida que el tamaño de su disco duro se hace más grande, siempre es mejor particionar el disco en fragmentos más pequeños y manejables, especialmente en computadoras más lentas o menos capaces.

De esa manera, puede realizar copias de seguridad completas como trabajos separados en particiones individuales seleccionadas mientras trabaja en otras particiones durante esas copias de seguridad.

Si algo le sucede al disco y lo daña durante un corte de energía, esa corrupción (posible incluso para Ext4) también se limitaría en su alcance a la partición que estaba activa en el momento del corte.

Además, si está realizando una operación de reparación "fsck", puede limitar el alcance y el resto de los datos se aíslan.

Por último, si mantiene una partición [a] vacía, puede usarla para migrar todo desde cualquiera de las particiones pobladas a esa partición [a], luego copiarlo todo nuevamente para eliminar toda la fragmentación, si alguna vez se volvió tan grave.

Sin embargo, al usar Ext3/4, la fragmentación es insignificante a menos que el uso de su disco esté en el rango por encima de aproximadamente el 92%. Esto se debe a la lógica interna que minimiza la fragmentación durante la asignación de bloques de disco para Ext3/4.

Hablando de copias de seguridad...

==== Estrategia ====

Mi fuerte sugerencia es tener también una unidad externa (disco duro USB o unidad de estado sólido) que pueda reflejar cada partición en su disco duro maestro. De esta manera, sus copias de seguridad se pueden realizar partición a partición. Lo mismo se aplica para la recuperación de disco, la recuperación partición a partición.

==== Método ====

Para aquellos que estén interesados, he incluido a continuación mi script de copia de seguridad. Utiliza rsync como motor.

Sin embargo, tengo lógica para asignar selectivamente el número/etiqueta de partición de un disco de destino, en función del número/etiqueta de partición del disco de origen.

Es de destacar que hago una prueba de la capacidad de "entrada" del disco, para limitar la cantidad de datos que se "almacenan en búfer" en la unidad de copia de seguridad, estableciendo un parámetro de limitación utilizando la opción "--bwlimit" de rsync. El script incluye lógica para determinar un valor apropiado para esa opción.

Además de eso, para poder usar mi computadora de escritorio de manera interactiva sin el impacto del posible abuso de CPU/RAM por parte de rsync, también uso el comando "ionice".

El script de respaldo [quickRSYNC.sh]:

#!/bin/sh

####################################################################################################
###
###	$Id: quickRSYNC.sh,v 1.8 2024/07/18 02:56:26 root Exp root $
###
###	Simplified version of 'rsync' backup without the additional post-backup tasks that are performed by 'OS_Admin__partitionSecondary_Mirror.sh'.
###
####################################################################################################

yellowON="\e[93;1m"
yellowOFF="\e[0m"

redON="\e[91;1m"
redOFF="\e[0m"



	#COM="rsync --one-file-system --recursive --outbuf=Line --links --perms --times --group --owner --devices --specials --verbose --out-format=\"%t|%i|%M|%b|%f|\" ${doCheckSum} ${doUpdate} --delete-after --whole-file --human-readable --protect-args --ignore-errors --msgs2stderr ${showProgress} ./ ${PathMirror}${dirC}/ 2>${SWIP}${LogLABEL}.err | tee ${SWIP}${LogLABEL}.out"

####################################################################################################
buildBatch()
{
	#COM="rsync --one-file-system --recursive --outbuf=Line --links --perms --times --group --owner --devices --specials --verbose --out-format=\"%t|%i|%M|%b|%f|\" ${doCheckSum} ${doUpdate} --delete-after --whole-file --human-readable --protect-args --ignore-errors --msgs2stderr ./ ${PathMirror}${dirC}/"

	##	--delete-delay \
	##	--delete-after \
	COM="ionice -c 2 -n 7 rsync \
		${limitThruput} \
		${doUpdate} \
		${doCheckSum} \
		${showProgress} \
		--one-file-system \
		--recursive \
		--outbuf=Line \
		--links \
		--perms \
		--times \
		--group \
		--owner \
		--devices \
		--specials \
		--verbose --out-format=\"%t|%i|%M|%b|%f|\" \
		--delete-during \
		--whole-file \
		--human-readable \
		--protect-args \
		--ignore-errors \
		--msgs2stderr \
		${EXCLUDES} \
		./ ${PathMirror}${dirC}/"

	START=`date`
	echo "\n\t ${START} |rsync| Start ${dirC} ..." >&2
	#cd ${PathMaster}${dirC}

	echo "
	\necho '${START} |rsync| Start ${dirC} \n\tProcess ID => '\$\$' ...' >&2
	cd ${PathMaster}${dirC}
	\n\trm -f ${SWIP}${LogLABEL}.out
	rm -f ${SWIP}${LogLABEL}.err
	{
	\n${COM}
	\necho 'START = ${START}' ; \necho '  END = '\`date\` 
	} 2>${SWIP}${LogLABEL}.err >${SWIP}${LogLABEL}.out
	RC=\$?
	\nif [ \${RC} -eq 0 ]; then
	\n\ttest -s ${STRT}${LogLABEL}.out  &&  mv -f ${STRT}${LogLABEL}.out ${STRT}${LogLABEL}.out.PREV
	test -s ${STRT}${LogLABEL}.err  &&  mv -f ${STRT}${LogLABEL}.err ${STRT}${LogLABEL}.err.PREV
	\n\tmv ${SWIP}${LogLABEL}.out ${STRT}${LogLABEL}.out
	mv ${SWIP}${LogLABEL}.err ${STRT}${LogLABEL}.err
	\nelse
	\n\tmv ${SWIP}${LogLABEL}.out ${STRT}${LogLABEL}.out.\$RC
	mv ${SWIP}${LogLABEL}.err ${STRT}${LogLABEL}.err.\$RC
	\n\tman rsync | awk -v P=\$RC '{ if( \$1 == P ){ print \$0 ; } ; }' 
	\nfi
	" >${MirrorBatch}

	chmod 700 ${MirrorBatch}
}

doReportLogs(){
	if [ ${doAllDrives} -eq 1 ]
	then
		echo "\n\n Log files:"
		ls -ltr ${PathMirror}${LogLABEL}.* | awk '{ printf("\t %s\n", $0 ) ; }'
	else
		echo "\n\n Expected Log files:"
		echo "\t ${PathMirror}${LogLABEL}.out\n\t ${PathMirror}${LogLABEL}.err\n"
	fi
} >&2


limitBandwidth()
{
	###
	###	Evaluate device speed to limit impact on other system and memory-dependent processes
	###

	if [ -s "${STRT}LIMIT__Bandwidth_rsync.txt" ]
	then
		read bandSpeed < "${STRT}LIMIT__Bandwidth_rsync.txt"
		if [ -n "${bandSpeed}" ]
		then
			if [ \( ${bandSpeed} -gt 30000 \)  -a  \( ${bandSpeed} -lt 150000 \) ]
			then
				echo "\n Using previously determined bandwidth limit for rsync buffer setting ..."
			else
				bandSpeed=""
			fi
		else
			rm -f "${STRT}LIMIT__Bandwidth_rsync.txt"
		fi
	fi

	if [ -z "${bandSpeed}" ]
	then
		echo "\n Performing speed test on backup device ..."

		rm -f "${STRT}LIMIT__Bandwidth_rsync.txt"
		### FORMAT
		#/dev/sdc4:
		# Timing O_DIRECT cached reads:    64 MB in  2.04 seconds =  31.35 MB/sec
		# Timing O_DIRECT disk reads:  98 MB in  3.06 seconds =  32.04 KB/sec
		echo "backDev = ${backDev}"

		devTest=`hdparm -Tt --direct ${backDev} `
		echo "${devTest}\n"

		testSpd=`echo "${devTest}" | tail -1 | awk '{ print $(NF-1), $NF ; }' `

		if [ -n "${testSpd}" ]
		then
			bandSpeed=`echo "${testSpd}" | awk '{ print $1 }' | cut -f1 -d\. `
			bandScale=`echo "${testSpd}" | awk '{ print $2 }' | cut -f1 -d/ `
			case "${bandScale}" in
				[Mm][Bb] )
					### Triple the value AND multiply by 1024
					bandSpeed=`expr ${bandSpeed} \* 6 \* 1024 / 2 `
					;;
				[Kk][Bb] )
					### Triple the value
					bandSpeed=`expr ${bandSpeed} \* 6 / 2 `
					;;
				* )
					### NULL if no recognized value
					bandSpeed=""
					;;
			esac

		fi

		if [ -n "${bandSpeed}" ]
		then
			echo "${bandSpeed}" > "${STRT}LIMIT__Bandwidth_rsync.txt"
		fi
	fi

	if [ -n "${bandSpeed}" ]
	then
		###	Set bandwidth limit for rsync to avoid flooding memory and filling swap
		limitThruput="--bwlimit=${bandSpeed}"
		echo "\n Will apply parameter to limit flooding of I/O, memory and swap ==>>  ${limitThruput}"
	else
		limitThruput=""
		echo "\n No bandwidth limiting was applied to rsync command (to prevent flooding of I/O, memory or swap) ..."
	fi
}


####################################################################################################
####################################################################################################

echo "\n\t NOTE:   This script will ONLY perform synchronization backup (applying differences).\n\t\t It does NOT perform a FULL COPY backup.\n\n\t\t For FULL COPY backup, use 'OS_Admin__partitionSecondary_Mirror.sh' responding 'y' at the appropriate prompt ...\n"

MROOT="${MROOT:-/site}"
horizLine="=============================================================================================="

thisHost=`hostname`

doCheckSum="" ; bProf="DateSize"
doUpdate=""
doShow=0
doAllDrives=0
showProgress=""
indexTypes=0
indexNames=0
bandSpeed=""

while [ $# -gt 0 ]
do
	case ${1} in
		--compareFileData )
			doCheckSum="--checksum"
			bProf="CheckSum"
			shift
			;;
		--keepNewer )
			doUpdate="--update"
			shift
			;;
		--noAction )
			doShow=1
			shift
			;;
		--doFull )
			doAllDrives=1
			shift
			;;
		--indexTypes )
			indexTypes=1
			shift
			;;
		--indexNames )
			indexNames=1
			shift
			;;
#		--monitor )
#			showProgress="--info=progress1"		## Doing this option causes multiple lines per file mirrored.
#			echo "\n\t Note:  Will report progress live ...\n"
#			shift
#			;;
		* ) echo "\n\t Unrecognized command line parameter '${1}'.  Unable to proceed.\n Bye!\n" ; exit 1
			;;
	esac
done



if [ -z "${doUpdate}" ]
then
	echo "\n\t Forcing backup of all files.       Option '--keepNewer' is available to keep backup version of files if newer ..."
fi

if [ -z "${doCheckSum}" ]
then
	echo "\n\t Checksum comparisons is disabled.  Option '--compareFileData' is available to force this check by rsync ..."
fi


case ${thisHost} in
	OasisMega1 )
		PathMaster="/"
		indent="              "
		mirrorGroup=5
		;;
#	OasisMega2 )
#		#OasisMini | OasisMidi )
#		#PathMaster="${MROOT}/"
#		#indent="        "
#		PathMaster="/"
#		indent="              "
#		mirrorGroup=7		### 7 used to avoid accidental cloberring of masterPart==8
#		;;
	* )	echo "\n\t This script is NOT to be used from this host. \n Bye!\n" ; exit 1 ;;
esac


testBK=`lsblk | grep 'disk' | grep '3.6T' `
if [ -z "${testBK}" ]
then
	echo "\n\t 4TB MyBook USB Drive is OFFLINE!  Unable to proceed.\n Bye!\n" ; exit 1
fi

echo "\n\t Following block devices have been identified:\n"
lsblk -l | awk '{ if( length($1) == 3 ){ print $0 } ; }' | awk '{ printf("\t\t %s\n", $0 ) ; }'


STRT=`pwd`

###
###	Values in list for 'masterPart' must be edited to suit the source device being backed up.
###
EXCLUDES=' --exclude=\"./cdrom/*\" --exclude=\"./dev/*\" --exclude=\"./lost+found/*\" --exclude=\"./media/*/*\" --exclude=\"./mnt/*\" --exclude=\"./proc/*\" --exclude=\"./run/*\" --exclude=\"./site/*/*\" --exclude=\"./sys/*\" --exclude=\"./tmp/*\" '


first=1
for masterPart in 1 2 3 4 5 6 7 8
do
	dirC=DB001_F${masterPart}

	case ${masterPart} in
		1 )	case ${thisHost} in
				OasisMega1 )	mirrorPart=8 ;;
				#OasisMega2 )	mirrorPart=9 ;;		# 9 assigned to avoid clobbering OasisMidi
				* )	echo "\n\t Backup for this host is not configured.\n" ; exit 1 ;;
			esac
			;;
		* )	
			case ${masterPart} in
				2 | 3 | 4 | 5 | 6 | 7 )	mirrorPart=${masterPart} ;;
				8 )	if [ ${thisHost} = "OasisMega1" ]
					then
						mirrorGroup=6
						mirrorPart=1
					fi
					;;
			esac
			EXCLUDES=""
			;;
	esac

	PathMirror="${MROOT}/DB00${mirrorGroup}_F${mirrorPart}/"
	STRT="${PathMirror}"
	SWIP="${MROOT}/"

	ROOTdev=`df / | grep '/dev/sd' | awk '{ print $1 }' `
	BDbase=`basename ${PathMirror} `
	testor=`df | grep ${BDbase} | awk '{ print $1 }' `


	if [ -z "${testor}" ]
	then
		pLABEL=`echo "${PathMirror}" | cut -f3 -d/ `
		pUUID=`grep "${MROOT}/${pLABEL}" /etc/fstab | grep -v '^#' | awk '{print $1 }' | cut -f2 -d\=  `
		if [ -n "${pUUID}" ]
		then
			#echo "UUID=${pUUID}"
			pDEVICE=`findfs UUID=${pUUID} 2>>/dev/null `
			if [ -n "${pDEVICE}" ]
			then
				echo "\n\t Partition for BACKUP target '${PathMirror}' is offline ...  Cannot proceed.\n Bye!\n"
			else
				echo "\n\t Disk UUID='${pUUID}' required for BACKUP target '${PathMirror}' is not powered up ...  Cannot proceed.\n Bye!\n"
			fi	
		else
			echo "\n\t Device for ${PathMirror}' not defined in /etc/fstab ...  Cannot proceed.\n\t Please update '/etc/fstab' using info reported by 'Devices__ReportDiskParts.sh --fstab'. \n Bye!\n"
		fi
		exit 1
	fi

	if [ "${testor}" = "${ROOTdev}" ] ; then  echo "\n\t ERROR ** Target BACKUP drive '${PathMirror}' is same as ROOT drive ...  Cannot proceed.\n Bye!\n" ; exit 1 ; fi

	backDev="${testor}"

	if [ ${first} -eq 1 ]
	then
		echo "\n\t External BACKUP disk is online ..."
		first=0
	fi

	echo "\n ${horizLine}"
	echo " ==================================  PARTITION BACKUP START  =================================="
	echo " ${horizLine}\n"

	echo "\t SOURCE=${indent} ${PathMaster}${dirC}"
	echo "\t MIRROR= ${PathMirror}${dirC} ...\n"

	if [ ${doAllDrives} -eq 1 ]
	then
		doit="y"
	else
		echo "\t Proceed with backup of '${yellowON}${dirC}${yellowOFF}' ? [y|N] => \c" ; read doit
		if [ -z "${doit}" ] ; then  doit="N" ; fi
	fi

	case ${doit} in
		y* | Y* )

			echo "\n"
			test ${indexTypes} -eq 1 && echo "\t ${redON}NOTE: ${yellowON} Flag set for Partition Indexing of all File TYPES ...${yellowOFF}"
			test ${indexNames} -eq 1 && echo "\t ${redON}NOTE: ${yellowON} Flag set for Partition Indexing of all File NAMES ...${yellowOFF}"

			if [ ${masterPart} -eq 1 ]
			then
 				echo "\n\t\t Running script 'Appl__Thunderbird__CachePurge.sh' ..."
				Appl__Thunderbird__CachePurge.sh

 				echo "\n\t\t Running script 'Appl__Firefox__CachePurge.sh' ..."
				Appl__Firefox__CachePurge.sh

				echo "\n\t\t Will purge the following quantity of cache data:"
				for cacheDir in /home/ericthered/.cache/thumbnails/fail/mate-thumbnail-factory /home/ericthered/.cache/thumbnails/normal /home/ericthered/.config/ghb/EncodeLogs
				do
					###  TBD:  home/ericthered/.cache/calibre/ev2/f/
					(	cd ${cacheDir}
						du -sh ${cacheDir} 2>&1 | awk '{ printf("\t\t\t %s\n" , $0 ) ; }'
						sleep 2
						find . \( ! -type d \) -exec rm -f {} \; 
						)
				done
			fi

			if [ ${indexTypes} -eq 1 ]
			then
				OS_Admin__PartitionIndex_Make.sh --allTypes --partition "${dirC}"
			fi

			if [ ${indexNames} -eq 1 ]
			then
				UTIL__SysIndex__Build.sh --partition "${dirC}"
			fi

			if [ ! -d "${PathMirror}${dirC}" ]
			then
				mkdir "${PathMirror}${dirC}"
				if [ $RC -eq 0 ]
				then
					echo "\t NOTE:  Created directory '${PathMirror}${dirC}' ..."
					chown root:root "${PathMirror}${dirC}"
				else
					echo "\t FAILURE:  Unable to create required BACKUP directory at '${PathMirror}${dirC}'.  Abandoning!\n"
					exit 1
				fi
			fi

			LogLABEL="Z_backup.${dirC}.${bProf}"

			MirrorBatch="${STRT}${LogLABEL}.batch"
		        rm -f ${MirrorBatch}

			limitBandwidth
			#limitThruput="--bwlimit=${bandSpeed}"
			#--bwlimit=95232	### WesternDigital 4TB USB MyBook

			buildBatch

			if [ ${doShow} -eq 1 ]
			then
				echo "\n${horizLine}\nContents of intended batch script:\n\n`cat ${MirrorBatch}`\n${horizLine}\n"
			else
				rm -f ${MROOT}/Z_backup.DB00*.nohup
				nohup nice -17 ${MirrorBatch} 2>>/dev/null >${SWIP}${LogLABEL}.nohup &
				BatchPID=$!
				#echo "\n Use 'OS_Admin__partitionMirror_Monitor.sh' to monitor rsync process.\n"
				echo "\t Background 'rsync' working ..." >&2

	###
	###  FUTURES
	###
				#sleep 5
				#/usr/bin/mate-terminal -e nice -n -19 bash tail -f ${SWIP}${LogLABEL}.err &
				#/usr/bin/mate-terminal -e nice -n -19 bash tail -f ${SWIP}${LogLABEL}.out &
				#/usr/bin/mate-terminal --working-directory="${SWIP}" --command="nice -n -19 bash ( tail -f '${LogLABEL}.err' ; read k <&2 )" &
				#/usr/bin/mate-terminal --working-directory="${SWIP}" --command="nice -n -19 bash ( tail -f '${LogLABEL}.out' ; read k <&2 )" &
				
			fi

 			;;
		* )	echo "\t\t '${dirC}' skipped ..." ;;
	esac

	if [ ${doAllDrives} -eq 1 ]
	then
		case ${doit} in
			y* | Y* )
				sleep 10
				echo "\t Monitoring for completion of '${dirC}' backup running in background (PID=${BatchPID}) ..."
				#echo "\n Use 'OS_Admin__partitionMirror_Monitor.sh' to monitor rsync process.\n"

				echo "\t \c"
				interval=10
				while [ true ]
				do
					testor=`ps -ef | grep -v grep | awk -v PID="${BatchPID}" '{ if( $2 == PID ){ print $0 ; exit ; } ; }' `
					if [ -n "${testor}" ]
					then
						echo ".\c"
						sleep ${interval}
					else
						BatchPIDs="`ps -ef | grep -v 'grep' | grep rsync | awk '{ print $2 }' `"
						if [ -n "${BatchPIDs}" ]
						then
							echo "+\c"
							sleep ${interval}
						else
							break
						fi
					fi
				done

				echo "\n\t DONE\n"
				sleep 2
				doReportLogs
				echo "\n\t FAILSAFE - PID= $$  for '$0' ..."
				;;
			* ) ;;
		esac
	else
		case ${doit} in
			y* | Y* )
				doReportLogs
				echo "\n Use 'OS_Admin__partitionMirror_Monitor.sh' to monitor rsync process.\n"
				exit
				;;
			* ) ;;
		esac
	fi
done



exit 0
exit 0
exit 0

OS_Admin__partitionMirror_Monitor.sh

#!/bin/sh

##########################################################################################################
###	$Id: OS_Admin__partitionMirror_Monitor.sh,v 1.3 2022/08/05 03:46:55 root Exp root $
###
###	This script is intended to perform an ongoing scan to report when an active RSYNC backup process terminates.
##########################################################################################################

test_STEP1()
{
echo "root        7520    7514 12 20:50 pts/0    00:05:46 rsync --checksum --one-file-system --recursive --outbuf=Line --links --perms --times --group --owner --devices --specials --verbose --out-format=%t|%i|%M|%b|%f| --delete-delay --whole-file --human-readable --protect-args --ignore-errors --msgs2stderr ./ /DB001_F7/
root        7514    7512  0 20:50 pts/0    00:00:25 rsync --checksum --one-file-system --recursive --outbuf=Line --links --perms --times --group --owner --devices --specials --verbose --out-format=%t|%i|%M|%b|%f| --delete-delay --whole-file --human-readable --protect-args --ignore-errors --msgs2stderr ./ /DB001_F7/
root        7512       1 17 20:50 pts/0    00:08:27 rsync --checksum --one-file-system --recursive --outbuf=Line --links --perms --times --group --owner --devices --specials --verbose --out-format=%t|%i|%M|%b|%f| --delete-delay --whole-file --human-readable --protect-args --ignore-errors --msgs2stderr ./ /DB001_F7/" >${TMP}
awk '{ printf("\trsync|%s\n", $0 ) ; }' ${TMP}
echo ""
}

test_STEP2()
{
echo "7520
7514
7512" >${TMP}.pid
awk '{ printf("\t pid |%s\n", $0 ) ; }' ${TMP}.pid
echo ""
}

test_STEP3()
{
echo "7514|7520
7512|7514
1|7512" >${TMP}.ppid
awk '{ printf("\tppid |%s\n", $0 ) ; }' ${TMP}.ppid
echo ""
}



. $Oasis/bin/INCLUDES__TerminalEscape_SGR.bh

BASE=`basename "$0" ".sh" `
TMP="/tmp/tmp.${BASE}.$$"

date | awk '{ printf("\n\t %s\n\n", $0 ) ; }'

if [ "$1" = "--snapshots" ]
then
	SNAP=1
else
	SNAP=0
fi

rm -f ${TMP}
ps -ef 2>&1 | grep -v grep | grep rsync | sort -r >${TMP}
#test_STEP1


if [ ! -s ${TMP} ]
then
	echo "\t RSYNC process is ${redON}not${redOFF} running (or has already ${greenON}terminated${greenOFF}).\n"
	exit 0
fi

awk '{ print $2 }' <${TMP} >${TMP}.pid
#test_STEP2


awk '{ printf("%s|%s\n", $3, $2) }' <${TMP} >${TMP}.ppid
#test_STEP3


for pid in `cut -f1 -d\| ${TMP}.ppid `
do
	PPID=`grep ${pid} ${TMP}.pid `
	PID=`grep '^'${pid} ${TMP}.ppid | cut -f2 -d\| `
	PRNT=`grep '^'${pid} ${TMP}.ppid | cut -f1 -d\| `
	if [ \( -n "${PPID}" \)  -a  \( "${PRNT}" -ne 1 \) ]
	then
		descr="child"
		echo "\t PID ${PID} is RSYNC ${cyanON}${italicON}${descr}${italicOFF}${cyanOFF} process ..."
	else
		descr="MASTER"
		echo "\t PID ${PID} is RSYNC ${yellowON}${descr}${yellowOFF} process ..."
	fi
done

getRsyncProcessStatus()
{
	testor=`ps -ef 2>&1 | awk -v THIS="${PID}" '{ if( $2 == THIS ){ print $0 } ; }' `
	MODE=`echo "${testor}" |
		awk '{ if( $NF ~ /^[/]DB001_F?[/]/ ){ print "2" }else{ print "1" } ; }' 2>>/dev/null ` 
}

getRsyncProcessStatus

if [ ${MODE} -eq 2 ]
then
	echo "\t RSYNC restore process under way ..."
	INTERVAL=60
	group5min=5
else
	echo "\t RSYNC backup process under way ..."
	INTERVAL=10
	group5min=30
fi

if [ -n "${testor}" ]
then
	echo "\n\t ${testor}\n" | sed 's+--+\n\t\t\t\t--+g' | awk '{
		rLOC=index($0,"rsync") ;
		if( rLOC != 0 ){
			sBeg=sprintf("%s", substr($0,1,rLOC-1) ) ;
			sEnd=sprintf("%s", substr($0,rLOC+5) ) ;
			sMid="\033[91;1mrsync\033[0m" ;
			printf("%s%s%s\n", sBeg, sMid, sEnd) ;
		}else{
			pLOC=index($0,"/DB001_") ;
			if( pLOC != 0 ){
				sBeg=sprintf("%s", substr($0,1,pLOC-1) ) ;
				sEnd=sprintf("%s", substr($0,pLOC) ) ;
				printf("%s\033[1m\033[93;1m%s\033[0m\n", sBeg, sEnd) ;
			}else{
				print $0 ;
			} ;
		} ;
	}'
	echo "\n\t Scanning at ${INTERVAL} second intervals ..."
	test ${SNAP} -eq 1 || echo "\t \c"
fi

durationCumulative=0
lapseCount=0
lapse=0

if [ ${SNAP} -eq 1 ]
then
	while true
	do
		getRsyncProcessStatus
		if [ -z "${testor}" ]
		then
			echo "\n\n\t RSYNC process (# ${PID}) has ${greenON}completed${greenOFF}.\n"
			date | awk '{ printf("\t %s\n\n", $0 ) ; }'
			exit 0
		fi
		jobLog=`ls -tr /site/Z_backup.*.err | tail -1 `
		echo "\t `tail -1 ${jobLog}`"
		sleep ${INTERVAL}
	done 2>&1 | uniq
else
	while true
	do
		getRsyncProcessStatus
		if [ -z "${testor}" ]
		then
			echo "\n\n\t RSYNC process (# ${PID}) has ${greenON}completed${greenOFF}.\n"
			date | awk '{ printf("\t %s\n\n", $0 ) ; }'
			exit 0
		fi
		echo ".\c"
		durationCumulative=`expr ${durationCumulative} + 1 `
		if [ ${durationCumulative} -eq ${group5min} ]
		then
			lapseCount=`expr ${lapseCount} + 1 `
			lapse=`expr ${lapseCount} \* 5 `
			echo "   ${lapse} min\n\t \c"
			durationCumulative=0
		fi
		sleep ${INTERVAL}
	done 
fi


exit 0
exit 0
exit 0

INCLUDES__TerminalEscape_SGR.bh

#!/bin/sh

##########################################################################################################
###	$Id: INCLUDES__TerminalEscape_SGR.bh,v 1.2 2022/09/03 01:57:31 root Exp root $
###
###	This includes string variables defined to perform various substitutions for the	ANSI Terminal Escape Sequences, i.e. SGR (Select Graphic Rendition subset)
##########################################################################################################

###	REFERENCE:	https://en.wikipedia.org/wiki/ANSI_escape_code
###	          	https://www.ecma-international.org/publications-and-standards/standards/ecma-48/

###	"\e" is same as "\033"

style_e()
{
boldON="\e[1m"
boldOFF="\e[0m"

italicON="\e[3m"
italicOFF="\e[0m"

underlineON="\e[4m"
underlineOFF="\e[0m"

blinkON="\e[5m"
blinkOFF="\e[0m"

blackON="\e[30;1m"
blackOFF="\e[0m"

cyanON="\e[96;1m"
cyanOFF="\e[0m"

cyanDarkON="\e[36;1m"
cyanDarkOFF="\e[0m"

greenON="\e[92;1m"
greenOFF="\e[0m"

yellowON="\e[93;1m"
yellowOFF="\e[0m"

redON="\e[91;1m"
redOFF="\e[0m"

orangeON="\e[33;1m"
orangeOFF="\e[0m"

blueON="\e[94;1m"
blueOFF="\e[0m"

blueSteelON="\e[34;1m"
blueSteelOFF="\e[0m"

darkBlueON="\e[38:5:12m"
darkBlueOFF="\e[0m"

magentaON="\e[95;1m"
magentaOFF="\e[0m"

redBgON="\e[101;1m"
redBgOFF="\e[0m"

whiteBgON="\e[107;1m"
whiteBgOFF="\e[0m"
}

style_o()
{
boldON="\033[1m"
boldOFF="\033[0m"

italicON="\033[3m"
italicOFF="\033[0m"

underlineON="\033[4m"
underlineOFF="\033[0m"

blinkON="\033[5m"
blinkOFF="\033[0m"

blackON="\033[30;1m"
blackOFF="\033[0m"

cyanON="\033[96;1m"
cyanOFF="\033[0m"

cyanDarkON="\033[36;1m"
cyanDarkOFF="\033[0m"

greenON="\033[92;1m"
greenOFF="\033[0m"

yellowON="\033[93;1m"
yellowOFF="\033[0m"

redON="\033[91;1m"
redOFF="\033[0m"

orangeON="\033[33;1m"
orangeOFF="\033[0m"

blueON="\033[94;1m"
blueOFF="\033[0m"

blueSteelON="\033[34;1m"
blueSteelOFF="\033[0m"

darkBlueON="\033[38:5:12m"
darkBlueOFF="\033[0m"

magentaON="\033[95;1m"
magentaOFF="\033[0m"

redBgON="\033[101;1m"
redBgOFF="\033[0m"

whiteBgON="\033[107;1m"
whiteBgOFF="\033[0m"
}

#style_e
style_o

##########################################################################################################
###	Usage Examples:
##########################################################################################################

#	echo "\t RSYNC process is ${redON}not${redOFF} running (or has already ${greenON}terminated${greenOFF}).\n"
#	echo "\t ${PID} is ${cyanON}${italicON}${descr}${italicOFF}${cyanOFF} process ..."
#	echo "\t ${PID} is ${yellowON}${descr}${yellowOFF} process ..."
#	echo "\n\n\t RSYNC process (# ${pid}) has ${greenON}completed${greenOFF}.\n"

##########################################################################################################
###	Example of scenario where escape codes are hard-coded; \e was not accepted by awk
##########################################################################################################

#	echo "\n\t ${testor}\n" | sed 's+--+\n\t\t\t\t\t\t\t\t--+g' | awk '{
#		rLOC=index($0,"rsync") ;
#		if( rLOC != 0 ){
#			sBeg=sprintf("%s", substr($0,1,rLOC-1) ) ;
#			sEnd=sprintf("%s", substr($0,rLOC+5) ) ;
#			sMid="\033[91;1mrsync\033[0m" ;
#			printf("%s%s%s\n", sBeg, sMid, sEnd) ;
#		}else{
#			print $0 ;
#		} ;
#	}'

##########################################################################################################
	echo "\n Imported LIBRARY:  INCLUDES__TerminalEscape_SGR.bh ...\n"
##########################################################################################################

------------------ English Original --------------------

The only comment I would make is that as your hard disk drive size becomes larger, it is always best to partition the disk into smaller manageable chunks, especially on slower or less capable computers.

That way, you can perform full backups as separate jobs on selected individual partitions while working on other partitions during those backups.

If anything happens to corrupt the disk during a power outage, that corruption (possible even for Ext4) would also be limited in scope to the partition that was active at the time of the outage.

Also, if you are performing an "fsck" repair operation, you can limit the scope, and the rest of data is isolated.

Lastly, if you happen to keep one partition [a] empty, you can use it to migrate everything from any one of the populated partitions onto that partition [a], then copy it all back to eliminate all fragmentation, if it ever got that bad.

However, using Ext3/4, fragmentation is insignificant unless your disk usage is in the range above aprox 92%. That's because of the internal logic that minimizes fragmentation during disk-block allocation for Ext3/4.

Talking about backups ...

==== Strategy ====

My strong suggestion is to also have an external drive (USB hard drive or solid-state drive) that can mirror every partition on your Master hard drive. This way, your backups can be performed partition-to-partition. The same applies for recovery of disk, recovering partition-to-partition.

==== Method ====

For those who are interested, I have included above my backup script. It uses rsync as the engine.

However, I have logic to selectively assign a destination disk's partition number/label, based on the source disk's partition number/label.

Of note, I do a test of disk "intake" capacity, in order to limit how much data is "buffered" to the backup drive, by setting a limiting parameter using rsync's "--bwlimit" option. The script includes logic to determine an appropriate value for that option.

In addition to that, in order to allow me to use my Desktop computer interactively without impact by the rsync's potential abuse of CPU/RAM, I also use the "ionice" command.