16 сентября 2009 г.

Простой бэкап, Python + DropBox, часть 2

Новая версия скрипта для бэкапа. Или другая версия...

Логика работы с файлами-списками не поменялась. Поменялся только параметр скрипта - теперь это имя архива без расширения, скрипт сам добавит .tar.gz.

Новое:
  • Создание архива переместилось из внешнего архиватора внутрь скрипта. Создаётся tar.gz архив.
  • Все пути теперь системо-зависимы, т.е. скрипт должен работать на линуксах тоже
Кроме приятного нового, повились неприятный минус - скрипт стал жрать кучу памяти.

Сделать сжатый архив с помощью модуля tarfile не вышло. Архив создаётся и сжимается, но внтури архива пути почему-то съезжают.

Т.е. нужно создать архив d:\dropbox\my dropbox\backup\backup.tar.gz, он там появляется. Но если открыть этот gz архив, tar архив будет глубоко внутри по пути dropbox\my dropbox\backup\backup.tar. Т.е. полный путь до данных получается такой: d:\dropbox\my dropbox\backup\backup.tar.gz\dropbox\my dropbox\backup\backup.tar\.... В принципе с этим можно жить, но некрасиво...

Поэтому сделал по-другому - сначала создаётся tar архив без сжатия со всеми файлами, затем он сжимается. Вот в этом месте функции, сжимающей архив, он, архив, передаётся целиком, т.е. весь файл весом несколько сот Мб засасывается в память.

Надо бы ещё покопать в эту сторону и найти лучшее решение...
import sys
import os
import os.path
import tarfile
import time
import gzip

__author__="race1"
__date__ ="$09.09.2009 19:55:06$"

if __name__ == "__main__":
    if (len(sys.argv) < 2):
        print("Usage: backup.py ")
        print("E.g.: \"backup.py d:\\dropbox\\my dropbox\\backup\"")
        exit(1)

    RootFoldersFile = "tobackup.lst"
    IgnoreFoldersFile = "ignore.lst"
    ExtraFile = "extra.lst"
    OutputArchive = sys.argv[1]
    OutputArchiveTar = OutputArchive + ".tar"
    OutputArchiveTarGz = OutputArchive + ".tar.gz"

    # Only mandatory file is RootFoldersFile, check that it exists
    if (not os.path.isfile(RootFoldersFile)):
        print("%s doesn't exist" % RootFoldersFile)
        exit(1)

    # Read root folders from file
    rootFolders = [i.strip() for i in open(RootFoldersFile, "r").readlines()]

    # Read list of folders that need to be igonred (if specified)
    ignoreList = []
    if (os.path.isfile(IgnoreFoldersFile)):
        ignoreList = [i.strip().lower() for i in open(IgnoreFoldersFile, "r").readlines()]

    # Delete old archive if exists
    if (os.path.isfile(OutputArchiveTar)):
        os.unlink(OutputArchiveTar)

    if (os.path.isfile(OutputArchiveTarGz)):
        os.unlink(OutputArchiveTarGz)

    filesCount = 0

    # Open output archive for writing (we'll gzip it later)
    try:
        tar = tarfile.open(OutputArchiveTar, "w")
    except IOError as err:
        print(err)
        exit(1)

    lastTime = time.time()
    for rootFolder in rootFolders:
        for root, dirs, files in os.walk(rootFolder):
            for file in files:
                tar.add(os.path.join(root, file))
                filesCount += 1

                # Show number of processed files each second
                if (time.time() - lastTime >= 1):
                    print("%d files..." % (filesCount))
                    lastTime = time.time()

            # Skip ignored folders
            for dir in dirs:                
                if (dir.lower() in ignoreList or (os.path.join(root, dir).lower() in ignoreList)):
                    dirs.remove(dir)

    # Add some files from extra files list
    if (os.path.isfile(ExtraFile)):
        for file in [i.strip() for i in open(ExtraFile, "r").readlines()]:
            tar.add(file)
            
    tar.close()

    print("Compressing...")

    # Gzip output archive
    try:
        gz = gzip.open(OutputArchiveTarGz, "wb")
    except IOError as err:
        print(err)
        exit(1)
    
    gz.write(open(OutputArchiveTar, "rb").read())
    gz.close()

    os.unlink(OutputArchiveTar)
        
    print("Output: %s, %d file(s), %d bytes" % (OutputArchiveTarGz, filesCount, os.path.getsize(OutputArchiveTarGz)))
    print("Done")

Комментариев нет:

Отправить комментарий