Sunday, November 22, 2009

Time Traveler... a sort of Time machine system

This is not a nice script, but it does the job for me in the way I need it to work. I share it with you in the case it can be useful to you.
I did it to store Time Traveler data on a separate disk, it is why I don't use a maximum backuped data size, and instead a free space to keep before starting the backup.
All backups are stored in folders starting with the time_t value, then the date in human readable format.
It is used in a server, so it sends the result to an email address. You can use it with cron for example.

The script is in python, so just copy it in the file timetraveler.py, change source and destination folder and email address at the top of the file, then chmod 700 timetraveler.py, then run it. Be sure you have python and rsync installed. Us only a linux compatible file system as backup folder (ext2, ext3, ext4 or other... not fat32 or ntfs, since I don't know if it will work)

Here is the script.
#!/usr/bin/env python
# coding: utf-8
#  TimeTraveler (c) 2009 Walter  http://computersstoneage.blogspot.com/
#
#
#TODO:
#     Répér dans les logs la sortie des commandes:
#            rm
#            rsync
#
import commands
import datetime
import time
import array
import string
import os


freeSpaceLimit = 50*1024*1024; #required disk space to start the backup in Ko. here it is 50Go.
path = "/mnt/timemachine/"  #folder where to store backups
source = "/mnt/data/"  #rértoire à auvegarder
mail = "/usr/bin/mail" #mail software
email = "timemachine"    #mail address to send the result of the backup


def disk_get_free(path):
    res = commands.getoutput('df -k '+path).splitlines()
    return int(res[1].split()[3])
  
def get_size(val):
    if val < (1024):
        val = str(val)+ ' KB'           
    elif  val < 1048576: #(1024*1024):
        val = str(float(int(val/102.4))/10.0)+ ' MB'       
    elif val < 1073741824 :#(1024*1024*1024):
        val = str(float(int(val/(104857.6)))/10.0)+ ' GB'   
    else:
        val = str(float(int(val/(107374182.4)))/10.0)+ ' TB'
    return val




date = str(datetime.datetime.now())
date = date.split()[0]
total = int(time.time())
#print(str(total)+"_"+date)

dest = path+str(total)+"_"+date

log = "STARTING TIMEMACHINE: "+str(datetime.datetime.now())+"\n"
log=log+"Backup folder: "+path+"\n"
log=log+"Source folder: "+source+"\n"
#lastInt = 0
#lastName = date+"_"+str(total)




#methode 1: je purge en fonction de l'espace disque
#print disk_get_free(path)
freeSpace = disk_get_free(path)
log = log+"Starting disk space recovery:\n"
log = log+"\tActual disk size: "+get_size(freeSpace)+"\n"
log=log+"\tDisk space to keep: "+get_size(freeSpaceLimit)+"\n"
if(freeSpace >= freeSpaceLimit):
    log=log+"\tNo need to free disk space.\n"
empty = False #cela me permet de savoir si j'ai encore des fichiers àffacer
while freeSpace < freeSpaceLimit and empty==False:
    files = os.listdir(path)
    files.sort()
    empty = True
    if len(files)>0:
         tab = files[0].split('_')
         if(len(tab) > 1) and str(tab[0]).isdigit():
            command = "rm -rf "+path+files[0]
            #print(command)
            log = log+commands.getoutput( command )
            freeSpaceNew = disk_get_free(path)
            log=log+"\tRemoving "+files[0]+": "+command+" recovered "+get_size(freeSpaceNew - freeSpace)+" => "+get_size(freeSpaceNew)+" free.\n"
            freeSpace = freeSpaceNew
            empty = False
   
if(empty==True):
    log=log+"ERROR: Can't recover enough space from previous backup. Current free space: "+get_size(freeSpace)+".\nABORTING BACKUP.\n"
    #print(log)
    p = os.popen(mail+" -s  \"Time machine "+str(datetime.datetime.now())+" - ERROR\" "+email, 'w')
    p.write(log)
    exitcode = p.close()
    exit()
log=log+"Disk space recovery finished.\n"



files = os.listdir(path)
files.sort()
found = False
i=0;
lastBackup = ""
size = len(files)
while found==False and i
    #print("i:"+str(i)+" size:"+str(size))
    tab = files[size-i-1].split('_')
    if(len(tab) > 1) and str(tab[0]).isdigit():
        found = True
        lastBackup = files[size-i-1]
    i = i+1
   
   
#lastBackup = "path"+files[len(files)-1]
#La, j'ai plus qu'a faire mon backup
command = ""
if lastBackup != "":
    log=log+"Found previous backup to increment: "+ lastBackup +"\n";
    command = "/usr/bin/rsync -a --safe-links  --stats --link-dest="+path+lastBackup+" "+source+" "+dest
    log=log+"Starting incremental backup:\n"+command+"\n"
else:
    log=log+"No previous backup to increment found.\n";
    command = "/usr/bin/rsync -a --safe-links --stats "+source+" "+dest
    log=log+"Starting complete backup:\n"+command+"\n"

log = log+commands.getoutput( command )
log=log+"\nBACKUP FINISHED!"
#print("Commad: "+command)



log = log+"Time machine finished: "+str(datetime.datetime.now())+"\n"
p = os.popen(mail+" -s  \"Time machine "+str(datetime.datetime.now())+" - OK\" "+email, 'w')
p.write(log)
exitcode = p.close()


 That's it

No comments: