User Tools

Site Tools


restore_menu

Descripcion

Acciones a realizar

Instalar un sistema linux base con las siguientes dependencias:

  • bash >= 4.0
  • sudo
  • dd
  • gzip/gunzip
  • acpi (comprobación de batería en portátil)
  • dmidecode (revisamos el serial, el script hay que configurarlo cada vez)
  • pigz (para proceso en paralelo)

Pasos generales

  • Se particiona el disco.
  • Instalamos windows
  • Instalamos un linux “minimal”, y dependencias necesarias para que el script funcione
  • Añadimos nuestro script.
  • Modificamos los parámetros de configuración necesarios en el mismo
  • Creamos un usuario de sistema sin privilegios, modificamos ~/.bashrc para lanzar automáticamente el script cuando se logue el usuario.
  • Deshabilitamos la posibilidad de salir del script (trap) para evitar problemas.
  • Nos guardamos el pass de root ;-)
  • Modificamos grub para que el menú diga algo como Restore or similar y el usuario no se asuste viendo GNU/Linux
  • Informar al usuario de como funciona el entorno, aunque es muy muy sencillo)

Script

Codigo

restore_menu.sh
#!/bin/bash
 
# Coded by dodger
# More information on
# http://blog.ciberterminal.net/index.php/2012/01/20/script-de-copia-y-restauracion-de-un-sistema-windows
 
 
SNAPSHOTDIR=/home/snapshots
WINDOWSDEV=/dev/sda1
SERIAL="serialnumber"
HOST="hostname"
INITIAL_IMAGE="INITIAL-IMAGE_20120119-115923_mar-eee.img.gz"
COMPRESSOR=/usr/bin/pigz
COMPRESSOPTIONS="-9fc"
UNCOMPRESSOR=/bin/gunzip
UNCOMPRESSOPTIONS="-dc"
NTFSCLONE="/root/ntfs-3g_ntfsprogs-2011.4.12/ntfsprogs/ntfsclone"
NTFSRESIZE="/root/ntfs-3g_ntfsprogs-2011.4.12/ntfsprogs/ntfsresize"
 
 
# AUTOCONFIG
unset IMAGELIST
unset IMAGESIZE
 
[ ! -d ${SNAPSHOTDIR} ] && mkdir $SNAPSHOTDIR
 
 
trap_it()
{
	[[ "$(kill -l | tail -1 | tr '+' '-')" =~ ([0-9]{1,})\)[[:space:]]{1,}[A-Z0-9\-]{3,15}(.|)$ ]]
	local TRAPIT=$(eval echo {1..${BASH_REMATCH[1]}})
	trap 'echo "NO PERMITIDO"' ${TRAPIT}
}
 
print_main_menu()
{
 
	local let OPTION=0
	clear
cat > /dev/stdout <<EOF
##################################################
Menu de restauracion y copia de sistema
1) Restauracion de imagen
2) Generacion de Imagen
3) Borrar imagen
4) Lista las imagenes existentes y su tamanyo
5) Ayuda
99) Reinicio del sistema
##################################################
EOF
	while [[ ! $OPTION =~ ^([1-5]|99)$ ]]
	do
		[ ${OPTION:-0} -ne 0 ] && echo "Seleccion erronea"
		printf "%s" "->  "
		read OPTION
		OPTION=${OPTION:-98}
		[[ ! ${OPTION} =~ ^[0-9]{1,}$ ]] && OPTION=0
	done
	return ${BASH_REMATCH[0]}
}
 
test()
{
 
	local MENU=$1
	local let OPTION=0
	case $MENU in
		"main" )
 
		;;
		"restore" )
		;;
		"clone" )
		;;
		* )
		;;
	esac
}
 
help()
{
clear
cat > /dev/stdout <<EOF
Este menu permite la restauracion de una copia de sistema anterior o
la generacion de una nueva copia.
Lo que se realiza es una copia integral del sistema windows o bien, 
una restauracion de 0 del mismo tal como estaba en el momento de la copia.
Ya que el espacio es limitado, deberian revisarse las imágenes de sistema 
existentes y eliminar las que no sean necesarias.
 
 
Las opciones de menu son las siguientes:
Opcion 1, dara opciones para la restauracion.
Opcion 2, dara opciones para la copia/clonado.
Opcion 3, dara opciones para el borrado de imagenes existentes.
Opcion 99, reinicia el equipo.
 
Recuerde que la opcion 1 elimina todos los datos actuales del sistema windows, dejándolo como cuando se realizó la copia.
 
 
 
Presiona ENTER para continuar
EOF
read
}
 
reboot_machine()
{
	echo "Reiniciando..."
	sleep 2
	#exit 0
	shutdown -r now
}
 
list_images()
{
	let x=0
	unset IMAGELIST
	for i in ${SNAPSHOTDIR}/*img.gz ; do
		IMAGELIST[$x]="$(basename $i)"
		let x++
	done
}
 
list_image_size()
{
	let x=0
	unset IMAGESIZE
	for ((x=0; x<${#IMAGELIST[@]} ; x++)) ; do
		IMAGESIZE[$x]="$(($(stat --format=%s ${SNAPSHOTDIR}/${IMAGELIST[$x]})/1024/1024))"
	done
}
 
check_cable()
{
	while [[ "$(acpi | egrep -i "Discharging")" ]] ; do
		echo "Este proceso tardara MUCHO, es necesario conexion a la red electrica"
		echo "Presione ENTER cuando este conectado"
		read
	done
}
 
show_agree()
{
	local YN=N
	echo "##################################################"
	echo "Este proceso no se puede parar, Estas seguro?"
	printf "%s" "(y/N)->  "
	read YN
	[[ ! ${YN} =~ ^[yY]$ ]] && return 1
	return 0
}
 
 
restore_clone_main()
{
	local ACTION=$1
	local IMAGEFILE=$2
	local DDPID=0
	check_cable
	show_agree
	[ ! $? -eq 0 ] && return 1
	case "$ACTION" in
		"clone")
			${NTFSCLONE} --save-image --output - ${WINDOWSDEV} | $COMPRESSOR $COMPRESSOPTIONS > ${IMAGEFILE}
		;;
		"restore")
			$UNCOMPRESSOR $UNCOMPRESSOPTIONS $IMAGEFILE | ${NTFSCLONE} --restore-image --overwrite ${WINDOWSDEV} - 
		;;
		*)
			echo "Error, REPORT"
			return 1
		;;
	esac
 
	echo "Completado, Pulse ENTER para continuar"
	read
	return 0
}
 
restore_menu()
{
	local let OPTION=99
	local YN=n
	clear
	echo "##################################################"
	echo "Menu de restauracion"
	echo "Paso 1: Elegir imagen:"
	list_images
	for ((x=0; x<${#IMAGELIST[*]} ; x++)) ; do
		echo "${x} ) ${IMAGELIST[$x]}"
	done
	echo -e "\nIntroduce el numero de imagen a restaurar"
	while [ ${OPTION} = 99 ]
	do
		printf "%s" "->  "
		read OPTION
		OPTION=${OPTION:-99}
		[ ${OPTION} -lt 0 ]  || [ ${OPTION} -ge ${#IMAGELIST[*]} ] || [[ ! ${OPTION} =~ ^[0-9]{1,}$ ]] && OPTION=99
	done
	echo "##################################################"
	echo "Paso 2: Restaurar imagen: ${IMAGELIST[$OPTION]}"
	echo "La descripcion de la imagen es:"
	cat ${SNAPSHOTDIR}/$(basename ${IMAGELIST[$OPTION]} .img.gz).description
	echo "Estas seguro?"
	printf "%s" "(y/N)->  "
	read YN
	[[ ${YN} =~ ^[yY]$ ]] && restore_clone_main restore "${SNAPSHOTDIR}/${IMAGELIST[$OPTION]}"
	if [ $? -eq 0 ] ; then
		echo "Es necesario reiniciar el Ordenador..."
		sleep 2
		reboot_machine
	fi
}
 
 
clone_menu()
{
	MYDATE="$(date +%Y%m%d-%H%M%S)"
	local let OPTION=99
	local YN=n
	local DESCRIPTION=""
	local USEDSPACE="$(${NTFSRESIZE} -i --no-action ${WINDOWSDEV} 2>&1 | grep "freeing" | awk '{print $5}')"
	USEDSPACE=$(($USEDSPACE/1024/2))
	local FREESPACE="$(df -P ${SNAPSHOTDIR} | grep "%" | awk '{print $4}')"
	clear
	echo "##################################################"
	echo "Menu de Clonado"
	[ $USEDSPACE -gt $FREESPACE ] && echo "El espacio necesario es mayor que el libre, es necesario hacer espacio (borrar imagenes)" && return 1
	while [[ ! $DESCRIPTION ]] ; do
		echo "Introduce una descripcion para la imagen y pulsa ENTER"
		printf "%s" "->  "
		read DESCRIPTION
		echo "${DESCRIPTION}" > "${SNAPSHOTDIR}/${MYDATE}_${HOST}.description"
	done
	restore_clone_main clone "${SNAPSHOTDIR}/${MYDATE}_${HOST}.img.gz"
	return 0
}
 
delete_menu()
{
	local let OPTION=98
	local YN=n
	clear
	list_images
	list_image_size
	[ ${#IMAGELIST[@]} -eq 1 ] && echo -e "No hay imagenes que borrar,\nPresione ENTER" && read && return 0
	echo "##################################################"
	echo "Menu de Borrado"
	echo "Paso 1: Elegir imagen para borrar:"
	for ((x=0; x<${#IMAGELIST[@]} ; x++)) ; do
		[[ ! "${IMAGELIST[$x]}" =~ ^${INITIAL_IMAGE}$ ]] && echo "$x ) \"${IMAGELIST[$x]}\" , Tamaño : ${IMAGESIZE[$x]} MB"
	done
	echo -e "\nIntroduce el numero de imagen a eliminar o 99 para salir"
	while [ ${OPTION:-98} = 98 ]
	do
		printf "%s" "->  "
		read OPTION
		OPTION=${OPTION:-98}
		[ ${OPTION} -eq 99 ] && return 1
		[ ${OPTION} -lt 0 ]  || [ ${OPTION} -gt ${#IMAGELIST[*]} ] || [[ ! ${OPTION} =~ ^[0-9]{1,}$ ]] && OPTION=98
	done
	echo "Estas seguro?"
	printf "%s" "(y/N)->  "
	read YN
	if [[ ${YN} =~ ^[yY]$ ]]
	then 
		echo "Borrando ${IMAGELIST[$OPTION]}"
		if [[ ! "${IMAGELIST[$OPTION]}" =~ ^${INITIAL_IMAGE}$ ]]
		then
			rm -fv "${SNAPSHOTDIR}/${IMAGELIST[$OPTION]}"
			rm -fv "${SNAPSHOTDIR}/$(basename ${IMAGELIST[$OPTION]} .img.gz).description"
		fi
	fi
}
 
list_menu()
{
	local let OPTION=98
	local YN=n
	clear
	list_images
	list_image_size
	echo "##################################################"
	echo "Lista de imagenes"
	for ((x=0; x<${#IMAGELIST[@]} ; x++)) ; do
		echo "$x ) Nombre: \"${IMAGELIST[$x]}\" , Tamaño : ${IMAGESIZE[$x]} MB"
	done
	echo "##################################################"
	echo "Presiona ENTER para continuar"
	read
}
 
 
main()
{
	trap_it
	while true ; do
		local let OPTION=0
		print_main_menu
		OPTION=$?
		case $OPTION in
			1)
				restore_menu
			;;
			2)
				clone_menu
			;;
			3)
				delete_menu
			;;
			4)
				list_menu
			;;
			5)
				help
			;;
			99)
				reboot_machine
			;;
			*)
			;;
		esac
	done
}
 
main

Variables

Variable Valor por defecto Descripcion
SNAPSHOTDIR /home/snapshots Directorio donde se almacenarán los snapshots y descripciones
WINDOWSDEV /dev/sda1 Partición que contiene Windows
SERIAL “8BOAAQ256174” El nº de serie del equipo, se puede ver con la dependencia dmidecode
HOST “my-hostname” Nombre del host, únicamente se usa para generar un nombre de imagen
COMPRESSOR /usr/bin/pigz Comando usado para comprimir, en este caso pigz para aprovechar los procesadores multi-core.
COMPRESSOPTIONS “-9fc” Opciones para la compresión
UNCOMPRESSOR /bin/gunzip Ídem pero para descomprimir
UNCOMPRESSOPTIONS “-dc” Opciones para la descompresión
NTFSCLONE “/root/ntfs-3g_ntfsprogs-2011.4.12/ntfsprogs/ntfsclone” Donde está el binario de ntfsclone, a veces puede ser necesario compilar (ver Troubleshooting)
NTFSRESIZE “/root/ntfs-3g_ntfsprogs-2011.4.12/ntfsprogs/ntfsresize” Ídem que antes, si hemos compilado

Ejemplo de Configuración restante

grub

menu.lst
# general configuration:
timeout   2
default   0
color light-blue/black light-cyan/blue
 
# (0) Windows
title Windows
rootnoverify (hd0,0)
makeactive
chainloader +1
 
 
# (1) Arch Linux
title  Recovery Mode
root   (hd0,1)
kernel /boot/vmlinuz-linux root=/dev/sda2 ro
initrd /boot/initramfs-linux.img

.bashrc

.bashrc
#
# ~/.bashrc
#
sudo /root/restore_menu.sh

sudoers

sudoers
username     ALL=(ALL) NOPASSWD: /root/restore_menu.sh

Troubleshooting

ntfsclone

ERROR: $Bitmap size is smaller than expected

Solución: http://www.tuxera.com/forum/viewtopic.php?f=2&t=27527

restore_menu.txt · Last modified: 2013/07/08 12:03 by dodger