#1 Le 25/04/2015, à 08:08
- papy88140
[Script / Python] À tester : sauvegarde facile ... où pas ;-)
Bonjour les ubunteros,
Je vous propose de tester la sauvegarde "nouvelle génération" . j'ai créé un paquet .deb pour l'installation facile, il est disponible sur ce lien : https://drive.google.com/file/d/0B0ChFm … sp=sharing
Il suffit de l'enregistrer et de l'installer.
Pour lancer le programme de sauvegarde, c'est : Applications / Accessoires / Sauvegarde automatique facile (un icône coffre fort jaune apparaît dans la zone de notification).
Pour initialiser une sauvegarde : clic droit sur l’icône, Créer / Modifier une sauvegarde. un pop-up vous demande d'insérer un support de sauvegarde, connectez votre support (carte SD, clé USB, disque externe, ...)
Une fenêtre apparaît avec la liste de vos dossiers personnels, cochez ceux que vous voulez sauvegarder et validez. Une fois fini, il suffit de retirer le support.
Pour les prochaines sauvegardes, si le programme est déjà lancé (icône coffre fort jaune), il suffit d'insérer le support et le retirer quand indiqué.
J'ai essayé d'enlever le maximum d'erreurs mais je soupçonne certaines de s'être malicieusement cachées dans des endroits impossibles,
aussi n'utilisez ce programme que dans le cadre de tests pour le moment. Le programme ne fait encore pas de roulement dans les sauvegardes (il crée un nouveau dossier horodaté à chaque fois) et il est prévu pour fonctionner sur des supports formatés en NTFS, même si l'utilisation de FAT32 ne semble pas (trop) le déranger.
J'attends d'éventuels retours.
A bientôt
Linux à Contrexéville ?
http://leclug.free.fr/forum/
Hors ligne
#2 Le 25/04/2015, à 08:13
- Shanx
Re : [Script / Python] À tester : sauvegarde facile ... où pas ;-)
Salut,
ce ne serait pas possible d'avoir les sources plutôt ?
Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied
Hors ligne
#3 Le 25/04/2015, à 09:40
- papy88140
Re : [Script / Python] À tester : sauvegarde facile ... où pas ;-)
Il suffit d'ouvrir le paquet .deb comme une archive et d'extraire le script safe.py
sinon, le script c'est :
#!/usr/bin/env python
# -*- coding: utf8 -*-
import subprocess,string,pyinotify, getpass, time
import appindicator,os,shutil
from PyQt4 import QtCore, QtGui
from datetime import datetime
import dbus
class Safe(QtCore.QObject):
# hostname : le nom de la machine
# user: nom de l'utilisateur courant
signalOpenConfig = QtCore.pyqtSignal()
signalOpenAttente = QtCore.pyqtSignal()
signalCloseConfig = QtCore.pyqtSignal()
signalCloseAttente = QtCore.pyqtSignal()
signalOpenFini = QtCore.pyqtSignal()
signalCloseFini = QtCore.pyqtSignal()
def handler(self, event):
time.sleep(2)
self.spath=event.pathname
mtab=open("/etc/mtab")
lignes=mtab.readlines()
# print lignes
self.partname=string.split(lignes[len(lignes)-1], " ",)[0]
mtab.close
self.diskname=self.partname[:-1]
print self.spath, " ", self.partname,self.diskname
configFileName="%s/.safe/%s/%s.safe" % (self.spath,self.hostname,self.user)
# nouvelle sauvegarde ?
if self.action == "config" :
self.signalCloseConfig.emit()
# on liste les dossiers personnels
home="/home/%s" % getpass.getuser()
try :
fichier=open(configFileName)
dossiersConfig=string.split(fichier.read(),"\n")
fichier.close()
except :
dossiersConfig=[]
dossiers=os.listdir(home)
## print dossiers
dossiersPerso=[]
for dossier in dossiers:
if dossier[0] != "." and os.path.isdir("%s/%s" % (home,dossier)):
dossiersPerso = dossiersPerso + [dossier]
## print dossiersPerso
commande = ['zenity','--height','800','--width','400','--list','--text','Sélectionnez les dossiers à sauvegarder\n','--checklist','--column','Sél.','--column','Dossiers']
for ligne in dossiersPerso :
if ligne in dossiersConfig:
commande=commande+['TRUE',ligne]
else :
commande=commande+['FALSE',ligne]
commande=commande+['--separator=:']
try :
dossiers=subprocess.check_output(commande)
subprocess.call(["mkdir","-p","%s/.safe/%s" % (self.spath,self.hostname)])
fichierConfig = open(configFileName,"w")
for dossier in string.split(dossiers,":") :
fichierConfig.write("%s\n"%(dossier))
fichierConfig.close()
self.action="backup"
except subprocess.CalledProcessError, e:
print "configuration annulée"
# ejection du support
subprocess.call(["udisksctl","unmount","-b","%s" % (self.partname)])
subprocess.call(["udisksctl","power-off","-b","%s" % (self.diskname)])
os.system('notify-send -t 3000 -i /opt/safe/safe-icon.svg "Sauvegarde Automatique Facile" "Vous pouvez retirer votre support de sauvegarde"')
return
# analyse du support inséré
# recherche de la configuration de l'utilisateur actuel
# .safe/hostname/utilisateur.conf
## configFileName="%s/.safe/%s/%s.safe" % (self.spath,self.hostname,self.user)
## print os.path.exists(configFileName)
## print configFileName
if os.path.exists(configFileName) :
fichier=open(configFileName)
dossiers=string.split(fichier.read(),"\n")
fichier.close()
## print dossiers
# os.system('notify-send -t 3000 -i /opt/safe/safe-icon.svg "Sauvegarde Automatique Facile" "Sauvegarde en cours,\nveuillez patienter svp ..."')
self.signalOpenAttente.emit()
# code de la sauvegarde
dossierHost="%s/.safe/%s" % (self.spath,self.hostname)
dossierUser="%s/%s" % (dossierHost,self.user)
## print dossierUser
if not(os.path.exists(dossierUser)):
try:
os.mkdir(dossierUser)
except:
pass
if not(os.path.exists("%s/%s@%s" % (self.spath,self.user,self.hostname))):
try:
os.symlink(".safe/%s/%s" % (self.hostname,self.user),"%s/%s@%s" % (self.spath,self.user,self.hostname))
except:
pass
# dernière sauvegarde et roulement
try:
sauvegardes=os.listdir(dossierUser)
## print len(sauvegardes)
## print sauvegardes
last = sauvegardes[-1]
if len(sauvegardes) == 5:
shutil.rmtree("%s/.safe/%s/%s/%s" % (self.spath,self.hostname,self.user,sauvegardes[0]))
except:
last="none"
## print last
# date actuelle
date=datetime.now()
date="%.4d.%.2d.%.2d-%.2d.%.2d.%.2d" % (date.year,date.month,date.day,date.hour,date.minute,date.second)
try:
os.mkdir("%s/%s" % (dossierUser,date))
except:
pass
for dossier in dossiers :
dossier=string.lstrip(string.rstrip(dossier))
if os.path.exists("/home/%s/%s" % (self.user,dossier)) and len(dossier)>0 :
try:
commande=["rsync","-r","-t","-q","--safe-links","--link-dest=%s/.safe/%s/%s/%s" % (self.spath,self.hostname,self.user,last),"/home/%s/%s" % (self.user,dossier),"%s/.safe/%s/%s/%s" % (self.spath,self.hostname,self.user,date)]
subprocess.check_output(commande)
except:
commande=["rsync","-r","-t","-q","--safe-links","/home/%s/%s" % (self.user,dossier),"%s/.safe/%s/%s/%s" % (self.spath,self.hostname,self.user,date)]
subprocess.check_output(commande)
print commande
# ejection du support
subprocess.call(["udisksctl","unmount","-b","%s" % (self.partname)])
subprocess.call(["udisksctl","power-off","-b","%s" % (self.diskname)])
# notification de fin
self.signalCloseAttente.emit()
self.signalOpenFini.emit()
time.sleep(3)
self.signalCloseFini.emit()
def quit(self):
self.notifier.stop()
QtGui.qApp.quit()
exit(0)
def safeConfig(self):
# on redéfini l'action à exécuter à l'insertion du support
self.action="config"
# on demande le support
self.signalOpenConfig.emit()
def __init__(self):
QtCore.QObject.__init__(self)
## Initialisation : pour connaitre la machine sur laquelle on travaille
self.hostname=subprocess.check_output(["hostname"])[:-1]
self.user=getpass.getuser()
## print self.user
# mise en place de la surveillance de l'insertion d'un support de stockage
self.wm=pyinotify.WatchManager()
wmpath='/media/%s' % (self.user)
# action à exécuter lors de l'insertion du support
self.action="backup"
self.wm.add_watch(wmpath,pyinotify.IN_CREATE)
self.notifier=pyinotify.ThreadedNotifier(self.wm, self.handler)
self.notifier.start()
#
# indicateur
# et interface grapĥique
#
self.app = QtGui.QApplication([])
self.icon = QtGui.QSystemTrayIcon(QtGui.QIcon("/opt/safe/safeGold.png"), self.app)
self.menu = QtGui.QMenu()
self.menu.addAction("Creer/Modifier une sauvegarde", self.safeConfig)
self.menu.addAction("Quit", self.quit)
self.icon.setContextMenu(self.menu)
self.icon.show()
self.imageSplashAttente = QtGui.QPixmap('/opt/safe/splashAttente.png')
self.splashAttente = QtGui.QSplashScreen(self.imageSplashAttente, QtCore.Qt.WindowStaysOnTopHint)
self.signalCloseAttente.connect(self.splashAttente.close)
self.signalOpenAttente.connect(self.splashAttente.show)
self.imageSplashFini = QtGui.QPixmap('/opt/safe/splashFini.png')
self.splashFini = QtGui.QSplashScreen(self.imageSplashFini, QtCore.Qt.WindowStaysOnTopHint)
self.signalCloseFini.connect(self.splashFini.close)
self.signalOpenFini.connect(self.splashFini.show)
self.imageSplashConfig = QtGui.QPixmap('/opt/safe/splashConfig.png')
self.splashConfig = QtGui.QSplashScreen(self.imageSplashConfig, QtCore.Qt.WindowStaysOnTopHint)
self.signalCloseConfig.connect(self.splashConfig.close)
self.signalOpenConfig.connect(self.splashConfig.show)
self.app.exec_()
#
#
#
if __name__=='__main__':
mySafe=Safe()
Il a été empaqueté car il utilise quelques images / icones
Linux à Contrexéville ?
http://leclug.free.fr/forum/
Hors ligne