Я пытаюсь выполнить резервное копирование всех своих.x папок в Доме для сохранения конфигураций.
С программой я пишу, можно выбрать любые папки, которые Вы хотите включенный или исключенный из резервного копирования, этот список является динамичным.
Я пытаюсь создать что-то вроде этого:
rsync -aP --exclude $Home/.cache/google-chrome/Default/Cache/* --exclude $Home/.cache/google-chrome/Default/Media\ Cache/* --exclude $Home/.wine $HOME/.* /mnt/ext/
Таким образом в вышеупомянутом примере, все копируется во внешний диск за исключением Вина и кэшей Chrome. Я знаю, что могу, создал текстовый файл, и сказать rsync --exclude-from 'textfile'
но я не должен считать и переписать текстовый файл.
Мое беспокойство - то, что, поскольку это расширяется, список исключения может стать довольно длинным, так как мой проект в конечном счете запустится включая папки за пределами $HOME, и на долях NFS других систем. Я могу запустить команду и использовать, исключает список в переменной:
exlist = "--exclude $Home/.cache/google-chrome/Default/Cache/* --exclude $Home/.cache/google-chrome/Default/Media\ Cache/* --exclude $Home/.wine" etc etc
subprocess.Popen("rsync -options ",exlist," /source /dest")
Но это собирается вызвать проблемы с чрезвычайно долгими командами оболочки, где я должен буду разбить его в меньшие блоки? Я опередил бы потенциальные будущие проблемы и начал бы писать обработчики, чтобы выполнить это теперь, а не попытаться зафиксировать и исправить его позже.
Я обнаружил, что мои ограничения по размеру не обязательно зависят от длины команды, а скорее от длины аргумента. Команды оболочки могут быть длиной от 100 000 до 200 000 символов. Аргументы, однако, ограничены несколькими сотнями символов в зависимости от системы, как обнаружено с помощью getconf ARG_MAX
.
Это приводит меня к возможной проблеме нехватки места, когда я добавил много исключений для папок в мои rsync
аргументы.
Чтобы обойти эту проблему, мне нужно программно разделить процесс rsync
от одного длинного выполнения на множество меньших.
Вот пример списка исключений в процессе его построения:
Этот список называется excludes
(long list items...)
--exclude $Home/.wine
--exclude $Home/.cache/somefolders/*
--exclude $Home/.cache/somefolders/*
--exclude $Home/.cache/somefolders/*
--exclude $Home/.cache/somefolders/*
--exclude $Home/.cache/google-chrome/Default/Cache/*
--exclude $Home/.cache/google-chrome/Default/Media\ Cache/*
**LIMIT EXCEEDED**
Теперь у нас превышен предел ARGS. Программа проанализирует этот список в поисках общих папок и создаст второй список, который будет сохранен для следующего выполнения rsync
.
После синтаксического анализа excludes
перестраивается в список, подобный следующему:
(long list items...)
--exclude $Home/.wine
--exclude $Home/.cache/*
После анализа строки, которые были удалены, были помещены в другой список, назовем его [ 1110] и выглядит следующим образом:
--exclude $Home/.cache/somefolders/*
--exclude $Home/.cache/somefolders/*
--exclude $Home/.cache/somefolders/*
--exclude $Home/.cache/somefolders/*
--exclude $Home/.cache/google-chrome/Default/Cache/*
--exclude $Home/.cache/google-chrome/Default/Media\ Cache/*
Таким образом, все повторяющиеся папки удаляются из excludes
и помещаются в excludesnext
. Когда элементы перемещаются и укороченные широкие папки заменяются на excludes
, создается новый список с именем cutlist
с этими новыми более короткими папками.
Таким образом, список cutlist
включает в себя:
--exclude $Home/.cache/*
rsync
запускается с использованием списка excludes
в качестве аргументов.
После окончания rsync
список excludes
очищается, а список excludesnext
копируется в список excludes
.
Затем rsync
запускается в цикле, используя новый сокращенный список cutlist
в качестве источника, и все соответствующие подпапки из excludes
используются в качестве исключений.
Конечно, в списке cutlist
может быть много элементов, и программа будет перебирать каждый из них. Этот второй прогон rsync
выполняется в цикле. Но в этом цикле, когда достигается максимальная длина, список excludes
анализируется так же, как и раньше, за исключением того, что новые укороченные папки добавляются в cutlist
вместо перехода в excludes
. Таким образом, когда цикл проходит через список вырезок, он может расширяться сам по себе, проходя через список. Поскольку элементы списка excludesnext
используются, они удаляются.
В конечном итоге это приводит к копированию всех папок и подпапок со всеми включенными исключениями независимо от их количества. Завершение последнего пункта в cutlist
означает, что все было выполнено.
Этот метод может заставить rsync
запускаться несколько или даже десятки раз, в зависимости от того, сколько у вас исключений, но он никогда не повторяет папки.
Приносим извинения за то, что не публикуем реальный код, но это грязная работа в процессе, и я не чувствую себя комфортно, публикуя свой код еще до того, как смогу выпустить работающий сервис.
я знаю, что могу, создал текстовый файл, и скажите, что rsync - исключают - из 'текстового файла', но я не должен считать и переписать текстовый файл.
Просто сделайте:
with contextlib.closing(tempfile.NamedTemporaryFile()) as exclude_from:
print(*your_exclude_list, sep="\n", flush=True, file=exclude_from) # etc
subprocess.check_call(['rsync', '--exclude-from', exclude_from.name, ...])
... и не волнуются о временном файле. Я ценю тот временный файл, с которым файлы кажутся грязными для контакта, но с библиотекой Python и менеджерами по контексту это может все быть приятно перенесено в пакет с поклоном, таким образом, Вы не должны волноваться об этом.