Na miejscu wypakuj archiwum tar

14

Mam tu mały dylemat ...

Musiałem przenieść pliki o wartości około 70 GB z jednego serwera na drugi, więc zdecydowałem, że przyspieszenie ich i wysłanie archiwum będzie najszybszym sposobem.

Jednak na serwerze odbierającym pozostało tylko 5 GB miejsca po otrzymaniu archiwum tar.

Czy jest jakiś sposób, aby wyodrębnić smołę „na miejscu”? Nie muszę przechowywać archiwum po rozpakowaniu, więc zastanawiałem się, czy można to zrobić.

Edycja: Należy zauważyć, że archiwum zostało już wysłane i chciałbym uniknąć ponownego wysyłania za pomocą innej metody.

anonimowy tchórz
źródło

Odpowiedzi:

11
% tar czf - stuff_to_backup | ssh backupmachine tar xvzf -

to przekłada się na:

  • tar i skompresuj 'stuff_to_backup' na standardowe wyjście
  • zaloguj się do „backupmachine” przez ssh
  • uruchom „tar” na „backupmachine” i rozpakuj rzeczy przychodzące ze standardowego wejścia

osobiście użyłbym „rsync over ssh” do przesłania rzeczy, ponieważ możesz kontynuować przesyłanie rzeczy, jeśli połączenie zostanie zerwane:

% rsync -ar --progress -e 'ssh' 'stuff_to_backup' user@backupmachine:/backup/

który przeniesie wszystko z „stuff_to_backup” do folderu „backup” w „backupmachine”. jeśli połączenie zostanie zerwane, po prostu powtórz polecenie. jeśli niektóre pliki w „stuff_to_backup” zmienią się, powtórz to, tylko różnica zostanie przeniesiona.

akira
źródło
Zobacz moje zredagowane pytanie
anonimowy tchórz
@Charlie Somerville: tak, najważniejszą część pozostawiłeś na pierwszym miejscu. :)
akira,
6

Jeśli druga maszyna ma ssh, polecam rsync jako inną alternatywę, która nie korzysta z pliku tar:

rsync -avPz /some/dir/ user@machine:/some/other/dir/

I bądź ostrożny z prowadzącym /

Edytuj aktualizację

Cóż, widzę, że jest to teraz świetny pikiel, jeśli nie możesz go usunąć i wznowić z rsync. Prawdopodobnie spróbowałbym selektywnego wyciągu i usunięcia ze smoły.

ekstrakt selektywny:

$ tar xvf googlecl-0.9.7.tar googlecl-0.9.7/README.txt
googlecl-0.9.7/README.txt

selektywne usuwanie:

$ tar --delete --file=googlecl-0.9.7.tar googlecl-0.9.7/README.txt

Wydaje się jednak, że poświęcisz dużo czasu na kodowanie skryptu dla tego ...

YuppieNetworking
źródło
Zobacz moje zredagowane pytanie
anonimowy tchórz
Zobacz moją zredagowaną odpowiedź ... powodzenia: - /
YuppieNetworking
Dzięki za edycję. Pliki są w rzeczywistości nazywane liczbami, więc szybka pętla for bash może po prostu załatwić sprawę.
anonimowy tchórz
1
@Charlie Somerville: być może będziesz musiał zacząć od plików przechowywanych na końcu tar, w przeciwnym razie możesz skończyć tworzeniem nowego archiwum przez tar ... więc najpierw usuń pliki z końca tar.
akira
5

Zasadniczo potrzebna jest możliwość potokowania pliku do pliku tar i „obcinania” frontu podczas pracy.

Na StackOverflow ktoś zapytał, jak obciąć plik z przodu , ale wydaje się, że nie jest to możliwe. Nadal możesz wypełnić początek pliku zerami w specjalny sposób, aby plik stał się plikiem rzadkim , ale nie wiem, jak to zrobić. Możemy jednak obciąć koniec pliku. Ale tar musi czytać archiwum do przodu, a nie do tyłu.

Rozwiązanie 1

Poziom pośredni rozwiązuje każdy problem. Najpierw odwróć plik na miejscu, a następnie przeczytaj go wstecz (co spowoduje odczytanie oryginalnego pliku do przodu) i obcinaj koniec odwróconego pliku podczas pracy.

Musisz napisać program (c, python, cokolwiek), aby wymienić początek i koniec pliku, fragment po kawałku, a następnie potokować te fragmenty do tar, jednocześnie obcinając plik po kawałku. Jest to podstawa rozwiązania 2, które może być łatwiejsze do wdrożenia.

Rozwiązanie 2

Inną metodą jest podzielenie pliku na małe fragmenty w miejscu , a następnie usunięcie tych fragmentów podczas ich wyodrębniania. Poniższy kod ma wielkość jednego megabajta, dostosuj go w zależności od potrzeb. Większy jest szybszy, ale zajmie więcej pośredniej przestrzeni podczas podziału i podczas ekstrakcji.

Podziel plik archive.tar:

archive="archive.tar"
chunkprefix="chunk_"
# 1-Mb chunks :
chunksize=1048576

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    currentchunk=$((currentchunk-1))
done

Prześlij te pliki do tar (uwaga: potrzebujemy zmiennej chunkprefix w drugim terminalu):

mkfifo fifo
# In one terminal :
(while true; do cat fifo; done) | tar -xf -
# In another terminal :
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done > fifo
# When second terminal has finished :
# flush caches to disk :
sync
# wait 5 minutes so we're sure tar has consumed everything from the fifo.
sleep 300
rm fifo
# And kill (ctrl-C) the tar command in the other terminal.

Ponieważ używamy nazwanego potoku ( mkfifo fifo), nie musisz potokować wszystkich porcji jednocześnie. Może to być przydatne, jeśli masz mało miejsca. Możesz wykonać następujące kroki:

  • Przenieś, powiedzmy, ostatnie 10 Gb na inny dysk,
  • Rozpocznij ekstrakcję kawałkami, które wciąż masz,
  • Po zakończeniu while [ -e … ]; do cat "$chunk…; donepętli (drugi terminal):
  • NIE zatrzymuj tarpolecenia, NIE usuwaj fifo (pierwszego terminala), ale możesz uruchomić sync, na wszelki wypadek,
  • Przenieś niektóre wyodrębnione pliki, o których wiesz, że są kompletne (tar nie jest zablokowany, czekając, aż dane zakończą rozpakowywanie tych plików) na inny dysk
  • Przenieś pozostałe fragmenty do tyłu,
  • Wznów ekstrakcję while [ -e … ]; do cat "$chunk…; done, ponownie uruchamiając linie.

Oczywiście to wszystko haute voltige , najpierw sprawdź, czy wszystko w porządku w archiwum fikcyjnym , bo jeśli popełnisz błąd, to pożegnaj się z danymi .

Nigdy nie dowiesz się, czy pierwszy terminal ( tar) faktycznie zakończył przetwarzanie zawartości fifo, więc jeśli wolisz, możesz uruchomić to zamiast tego, ale nie będziesz mieć możliwości płynnej wymiany fragmentów na inny dysk:

chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done | tar -xf -

Zrzeczenie się

Pamiętaj, że aby wszystko to działało, twoja powłoka, ogon i obcięcie muszą poprawnie obsługiwać 64-bitowe liczby całkowite (nie potrzebujesz do tego 64-bitowego komputera ani systemu operacyjnego). Mój tak, ale jeśli uruchomisz powyższy skrypt w systemie bez tych wymagań, stracisz wszystkie dane w pliku archive.tar .

W każdym razie coś innego nie działa, i tak stracisz wszystkie dane w pliku archive.tar, więc upewnij się, że masz kopię zapasową danych.

Suzanne Dupéron
źródło
0

Jeśli masz pliki obiektów do przeniesienia, spróbuj je rozebrać. Pozwoli to zaoszczędzić znaczną ilość miejsca.

$ strip `find . -name "*.bin"`
kumar
źródło