Jak przekonwertować istniejące pliki gz (gzip) na rsyncable

12

Korzystam z rsync do tworzenia kopii zapasowych repozytorium, które zawiera wiele plików GZ, w tym wiele nowych każdego dnia. Kopia zapasowa rsync przebiega wolniej niż powinna, ponieważ te pliki gz nie są budowane z opcją --rsyncable gzip (co czyni pliki gz bardziej „przyjaznymi dla rsync” bez znacznego zwiększenia ich rozmiaru lub wpływu na ich kompatybilność). I nie mogę rozwiązać problemu w czasie tworzenia, ponieważ pliki są generowane przez skrypt Pythona (rdiff-backup), który używa modułu gzip pythona, a to nie obsługuje odpowiednika - gsip - syncable.

Więc przed uruchomieniem rsync mogę zidentyfikować nowe pliki gz w danych źródłowych (tj. Nowe od ostatniego uruchomienia rsync). Teraz chcę ponownie „zgzipować” te pliki, aby były one zgzipowane w formacie rsyncable. Następnie mogę uruchomić rsync ze zoptymalizowanego źródła.

Myślę, że oznacza to uruchomienie każdego pliku przez gunzip, a następnie gzip --rsyncable, ale nie jestem zbyt pewien, jak to zrobić w sposób, który nie ryzykuje utraty danych lub metadanych. Sugestie otrzymane z wdzięcznością.

gogoud
źródło
8
Jedyny sposób --rsyncablepowinien mieć znaczenie, jeśli pliki zostaną zmienione między uruchomieniami i rsyncspróbują wysłać zmiany. Nowe pliki nie dbają o to, czy można je synchronizować, czy nie, ponieważ i rsynctak muszą przesyłać wszystkie dane. Czy pliki są zmieniane między uruchomieniami rsync?
Tom Hunt
Słuszna uwaga. Właściwie nie jestem pewien, sprawdzę to. Załóżmy na razie, że tak, zawartość niektórych plików gz ulega zmianie.
gogoud
Najlepszą rzeczą, jaką mogę wymyślić, jest uruchomienie skryptu, który sprawdza nowe pliki, rozpakowuje je, a następnie ponownie zgzipuje --rsyncable.
Tom Hunt
Zgadzam się, że jeśli pliki się nie zmienią, nie powinno to stanowić problemu. W szczególności, dla prędkości, pamiętaj o pomijaniu sum kontrolnych na podstawie czasu, zachowując czasy za pomocą -aflagi. Ponadto moja wersja gzip nie ma --rsyncableflagi, ale zawiera program o nazwie znew, który prawdopodobnie mógłby zostać użyty do tego, czego potrzebujesz.
user3188445,
2
Okazuje się, że, jak pomyślał Tom, pliki gz utworzone przez rdiff-backup nie zmieniają się po utworzeniu, więc użycie --rsyncablenie pomogłoby. Miałem nadzieję na linię kodu lub krótki skrypt, który bezpiecznie rozpakowałby archiwum gz i ponownie go spakował --rsyncable. Ale teraz jest to dla mnie tylko pytanie akademickie.
gogoud

Odpowiedzi:

1
#! /bin/bash

set -euo pipefail

##  TOKEN's creation time marks the time since last recompression
TOKEN=.lastRecompression   

if [ -f ${TOKEN} ]
then
    find -name '*.gz' -cnewer "${TOKEN}"
else
    # Process all compressed files if there is no token.
    find -name '*.gz'
fi | while read f
do
    # Do it in two steps
    gunzip < "$f" | gzip --rsyncable > "$f.tmp"

    # Preserve attributes
    cp "$f" "$f.tmp" --attributes-only

    # and rename atomically.
    # set -e ensures that a problem in the previous step 
    # will stop the full script. 
    mv -v "$f.tmp" "$f"
done

# Update the token
touch ${TOKEN}
Raúl Salinas-Monteagudo
źródło
1
W ten sposób gunzip | gziptracisz nieskompresowaną nazwę i czas zapisane w pliku gz (i widziane z gzip -vNl)
Stéphane Chazelas
@ Stéphane Chazelas: Masz rację: jeśli te informacje są istotne (nigdy nie były dla mnie istotne), tracimy je. Być może najlepszym rozwiązaniem byłoby, aby gunzip bezpośrednio wspierał tę ponowną kompresję. Może przekazać wszystkie metadane wewnętrznie.
Raúl Salinas-Monteagudo
@ StéphaneChazelas Czy znasz kogoś, kto robi to bez strat?
Tom Hale