Простой самодельный бэкап данных 2 (Python + DropBox)

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

    Логика работы с файлами-списками не поменялась. Поменялся только параметр скрипта — теперь это имя архива без расширения, скрипт сам добавит .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 архив без сжатия со всеми файлами, затем он сжимается. Вот в этом месте функции, сжимающей архив, он, архив, передаётся целиком, т.е. весь файл весом несколько сот Мб засасывается в память.

    Надо бы ещё покопать в эту сторону и найти лучшее решение…

    Copy Source | Copy HTML
    1. import sys
    2. import os
    3. import os.path
    4. import tarfile
    5. import time
    6. import gzip
    7.  
    8. if __name__ == "__main__":
    9.     if (len(sys.argv) < 2):
    10.         print("Usage: backup.py <output archive filename>")
    11.         print("E.g.: \"backup.py d:\\dropbox\\my dropbox\\backup\"")
    12.         exit(1)
    13.  
    14.     RootFoldersFile = "tobackup.lst"
    15.     IgnoreFoldersFile = "ignore.lst"
    16.     ExtraFile = "extra.lst"
    17.     OutputArchive = sys.argv[1]
    18.     OutputArchiveTar = OutputArchive + ".tar"
    19.     OutputArchiveTarGz = OutputArchive + ".tar.gz"
    20.  
    21.     # Only mandatory file is RootFoldersFile, check that it exists
    22.     if (not os.path.isfile(RootFoldersFile)):
    23.         print("%s doesn't exist" % RootFoldersFile)
    24.         exit(1)
    25.  
    26.     # Read root folders from file
    27.     rootFolders = [i.strip() for i in open(RootFoldersFile, "r").readlines()]
    28.  
    29.     # Read list of folders that need to be igonred (if specified)
    30.     ignoreList = []
    31.     if (os.path.isfile(IgnoreFoldersFile)):
    32.         ignoreList = [i.strip().lower() for i in open(IgnoreFoldersFile, "r").readlines()]
    33.  
    34.     # Delete old archive if exists
    35.     if (os.path.isfile(OutputArchiveTar)):
    36.         os.unlink(OutputArchiveTar)
    37.  
    38.     if (os.path.isfile(OutputArchiveTarGz)):
    39.         os.unlink(OutputArchiveTarGz)
    40.  
    41.     filesCount =  0
    42.  
    43.     # Open output archive for writing (we'll gzip it later)
    44.     try:
    45.         tar = tarfile.open(OutputArchiveTar, "w")
    46.     except IOError as err:
    47.         print(err)
    48.         exit(1)
    49.  
    50.     lastTime = time.time()
    51.     for rootFolder in rootFolders:
    52.         for root, dirs, files in os.walk(rootFolder):
    53.             for file in files:
    54.                 tar.add(os.path.join(root, file))
    55.                 filesCount += 1
    56.  
    57.                 # Show number of processed files each second
    58.                 if (time.time() - lastTime >= 1):
    59.                     print("%d files..." % (filesCount))
    60.                     lastTime = time.time()
    61.  
    62.             # Skip ignored folders
    63.             for dir in dirs:
    64.                 if (dir.lower() in ignoreList or (os.path.join(root, dir).lower() in ignoreList)):
    65.                     dirs.remove(dir)
    66.  
    67.     # Add some files from extra files list
    68.     if (os.path.isfile(ExtraFile)):
    69.         for file in [i.strip() for i in open(ExtraFile, "r").readlines()]:
    70.             tar.add(file)
    71.  
    72.     tar.close()
    73.  
    74.     print("Compressing...")
    75.  
    76.     # Gzip output archive
    77.     try:
    78.         gz = gzip.open(OutputArchiveTarGz, "wb")
    79.     except IOError as err:
    80.         print(err)
    81.         exit(1)
    82.  
    83.     gz.write(open(OutputArchiveTar, "rb").read())
    84.     gz.close()
    85.  
    86.     os.unlink(OutputArchiveTar)
    87.  
    88.     print("Output: %s, %d file(s), %d bytes" % (OutputArchiveTarGz, filesCount, os.path.getsize(OutputArchiveTarGz)))
    89.     print("Done")
    Поделиться публикацией

    Комментарии 3

      0
      Мне это кажется программированием ради программирования: в несжатом виде объём данных конечно больше, но он и меняется не целиком — т.е. расходуется меньше трафика и пространства на сервере; удалённая копия обновляется не по расписанию, а по факту изменения файлов, т.е. потенциально более актуальна.

      Ну и оговорка, что дескать работать с ftp сложнее… Не настолько сложнее, чтобы сразу ставить крест на разработке такого скрипта ;-)
        0
        Спасибо :)

        Ага, я постоянно думал в фоне, что копировать файлы по отдельности было бы не так плохо :) Но там встаёт проблема синхронизации оригинальной папки и папки dropbox'а.

        С ftp как-нибудь потом разберусь, но мне очень понравилось как просто и быстро решилась проблема заливки данных на dropbox, что на эту часть сразу перестал обращать внимание.
        0

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое