urriellu.net => Proyectos => Software => LocalBackuper

LocalBackuper es un programa escrito en C# y ejecutado sobre mono diseñado para montar un disco duro externo, desencriptarlo, limpiar copias de seguridad viejas cuando sea necesario y crear nuevas copias de seguridad de los directorios encriptados.

¿Por qué?

Existen multitud de sistemas de copias de seguridad: algunos muy simples, otros demasiado complejos, y ninguno que me convenciese. Además me gusta programar y siempre quiero reimplementar aplicaciones existentes... porque quiero, no necesariamente porque mi implementación vaya a ser mejor ni más completa. LocalBackuper no pretende ser una solución para todo el mundo, ni siquiera para unos pocos, está pensada exclusivamente para que funcione como a mí me interesa. Si quieres más funcionalidades podría ampliarse pero probablemente sea mejor utilizar otros sistemas de copias de seguridad.

Cómo funciona

  • Se ejecuta como root MakeBackups.sh
    • Monta, pide contraseña y desencripta la partición usada para hacer las copias de seguridad
    • Desmonta los directorios que puedan molestar al hacer las copias
    • Ejecuta LocalBackuper.exe
    • Desmonta la partición montada anteriormente
  • LocalBackuper.exe (diseñado para ser ejecutado sin usar MakeBackups.sh)
    • Crea una lista de archivos y directorios que van a ser copiados, ordenados de mayor a menor importancia
    • Se calcula cuánto ocupan las copias de seguridad preexistentes
    • Se calcula cuánto ocupan los nuevos archivos que van a ser copiados
    • Si no hay espacio en disco suficiente se empiezan a borrar los archivos de menos importancia de la copia de seguridad más vieja que haya. Si se llega a borrar una de las viejas copias de seguridad completamente y sigue sin haber espacio suficiente entonces se empiezan a borrar archivos de la penúltima copia de seguridad (al haber borrado la anterior, ahora la "penúltima" es la más vieja). De esta manera se mantienen la mayor cantidad posible de copias de seguridad completas (para tener tantas copias como sea posible) y sólo quedará incompleta la copia de seguridad más vieja
    • Se copian los archivos y directorios especificados al directorio de copias de seguridad. Cada copia completa irá en un directorio de nombre AÑOMESDIA-NNN, siendo NNN el índice usado para ordenar las copias hechas en un mismo día.

Ejemplo de salida por consola:

$ /usr/local/bin/MakeBackups.sh
Decrypting backups HD...
Enter LUKS passphrase:
key slot 0 unlocked.
Command successful.
Mounting decrypted backups partition...
Unmounting some other things before backing up...
    [...]
Backing up...
Total space: 152619 MiB (149 GiB)
Used space: 117351 MiB (114 GiB)
Free space: 35268 MiB (34 GiB)
Needed space for the new backup: 20085 MiB (19 GiB)
We are keeping all the old backups :-D
Creating a new backup in /mnt/backups/backups-servidor_principal/20070817000
        Copying /home/datos to /mnt/backups/backups-servidor_principal/20070817000/home_datos
        Copying /home/Fotos to /mnt/backups/backups-servidor_principal/20070817000/home_Fotos
        Copying /home/urriellu/.mailfilter to /mnt/backups/backups-servidor_principal/20070817000/home_urriellu_.mailfilter
Unmounting backups partition...
Reencrypting backups partition...
You can turn off the backups partition now :-D

A tener en cuenta

  • Sólo funciona en sistemas operativos que incluyan los binarios externos necesarios
  • Tanto MakeBackups.sh como LocalBackuper.exe deben ejecutarse como root para poder montar, desencriptar y leer archivos de cualquier usuario sin problemas. Antes de borrar archivos automáticamente se comprueba el directorio que va a ser borrado para evitar fallos del propio programa
  • Por distintas razones (algunas explicadas en el código fuente) se utilizan algunos binarios externos que deben estar instalados, como du, df y rm. Por ejemplo fue necesario reimplementar Directory.Delete() usando rm porque la máquina virtual tiene problemas al acceder a archivos cuyo nombre contiene caracteres codificados en un charset incorrecto
  • La lista de directorios y archivos a copiar, la ruta a los binarios externos utilizados, la ruta a la partición encriptada y la ruta al directorio donde se monta la partición encriptada están hardcoded en MakeBackups.sh y config.cs

Código fuente

MakeBackups.sh, 25 líneas      [descargar]

  1. #!/bin/bash
  2.  
  3. #this script must be executed as root (chmod 740 <this_script.sh> is a good choice)
  4.  
  5. echo -e "Decrypting backups HD..."
  6. while [ ! -e /dev/mapper/backup_crypt ]; do
  7. cryptsetup luksOpen /dev/sdc1 backup_crypt
  8. done
  9.  
  10. echo -e "Mounting decrypted backups partition..."
  11. mount /dev/mapper/backup_crypt /mnt/backups
  12.  
  13. echo -e "Unmounting some other things before backing up..."
  14. #whatever you want
  15.  
  16. echo -e "Backing up..."
  17. /usr/bin/mono /usr/local/bin/LocalBackuper.exe
  18.  
  19. echo -e "Unmounting backups partition..."
  20. umount /mnt/backups/
  21.  
  22. echo -e "Reencrypting backups partition..."
  23. cryptsetup remove backup_crypt
  24.  
  25. echo -e "You can turn off the backups HD now :-D"
  26.  

Program.cs, 33 líneas      [descargar]

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace LocalBackuper {
  5.         class Program {
  6.                 static void Main(string[] args) {
  7.                         if(Environment.UserName == "root") {
  8.                                 Console.WriteLine("Total space: {0} MiB ({1} GiB)" , general.DriveInfo.TotalSpace / 1024 / 1024 , general.DriveInfo.TotalSpace / 1024 / 1024 / 1024);
  9.                                 Console.WriteLine("Used space: {0} MiB ({1} GiB)" , general.DriveInfo.UsedSpace / 1024 / 1024 , general.DriveInfo.UsedSpace / 1024 / 1024 / 1024);
  10.                                 Console.WriteLine("Free space: {0} MiB ({1} GiB)" , general.DriveInfo.FreeSpace / 1024 / 1024 , general.DriveInfo.FreeSpace / 1024 / 1024 / 1024);
  11.                                 Console.WriteLine("Needed space for the new backup: {0} MiB ({1} GiB)" , general.NewBackupSize / 1024 / 1024 , general.NewBackupSize / 1024 / 1024 / 1024);
  12.                                 if(general.NewBackupSize + config.KeepFreeSpace >= general.DriveInfo.TotalSpace) {
  13.  
  14. [...]

general.cs, 244 líneas      [descargar]

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.Diagnostics;
  6. using System.IO;
  7. namespace LocalBackuper {
  8.         public static class general {
  9.                 private static UInt64 pNewBackupSize;
  10.                 /// <summary>
  11.                 /// Gets the size needed for the new backup.
  12.                 /// </summary>
  13.                 public static UInt64 NewBackupSize {
  14.  
  15. [...]

config.cs, 43 líneas      [descargar]

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace LocalBackuper {
  5.         public static class config {
  6.                 /// <summary>
  7.                 /// List of files and directories to be backuped
  8.                 /// </summary>
  9.                 /// BE CAREFUL: PATHS SHOULDN'T END WITH A SLASH ("/")
  10.                 public static string[] ListToBackup = {
  11.                         "/home/data" ,
  12.                         "/home/Pictures",
  13.                         "/home/urriellu.net" ,
  14.                         "/var/lib/mysql",
  15.  
  16. [...]