Jak mogę ustalić, czy uruchomienie tar spowoduje zapełnienie dysku

22

Jeśli uruchomię tar -cvfkatalog o rozmiarze 937 MB, aby utworzyć łatwą do pobrania kopię głęboko zagnieżdżonej struktury folderów, czy ryzykuję zapełnienie dysku, biorąc pod uwagę następujące df -hdane wyjściowe:

/dev/xvda1            7.9G  3.6G  4.3G  46% /
tmpfs                 298M     0  298M   0% /dev/shm

Powiązane pytania:

  • Jeśli dysk może się zapełnić, dlaczego np. Co Linux (Amazon AMI) i / lub tarbędzie robił pod maską?
  • Jak mogę dokładnie ustalić te informacje bez pytania?
codecowboy
źródło
Nie jestem pewien, czy jest to możliwe bez przetworzenia archiwum, ale możesz bawić się z --totalsopcją. Tak czy inaczej, jeśli zapełnisz dysk, możesz po prostu usunąć archiwum, imho. Aby sprawdzić wszystkie dostępne opcje, możesz przejść tar --help.
UVV
4
Stycznie: nie twórz pliku tar jako root, pewien procent miejsca na dysku jest zarezerwowany wyłącznie dla roota, dokładnie dla rodzaju: „Zapełniłem dysk i teraz nie mogę się zalogować, ponieważ to by zapisało. bash_history lub jakakolwiek inna sytuacja.
Ulrich Schwarz,

Odpowiedzi:

24

tar -c data_dir | wc -c bez kompresji

lub

tar -cz data_dir | wc -c z kompresją gzip

lub

tar -cj data_dir | wc -c z kompresją bzip2

wypisze rozmiar archiwum, które zostanie utworzone w bajtach, bez zapisywania na dysku. Następnie możesz porównać to z ilością wolnego miejsca na urządzeniu docelowym.

Możesz sprawdzić rozmiar samego katalogu danych, w przypadku niepoprawnego założenia jego rozmiaru, za pomocą następującego polecenia:

du -h --max-depth=1 data_dir

Jak już odpowiedziano, tar dodaje nagłówek do każdego rekordu w archiwum, a także zaokrągla rozmiar każdego rekordu do wielokrotności 512 bajtów (domyślnie). Koniec archiwum jest oznaczony przez co najmniej dwa kolejne rekordy wypełnione zerami. Tak więc zawsze jest tak, że nieskompresowany plik tar jest większy niż same pliki, liczba plików i sposób ich wyrównania do granic 512 bajtów determinuje wykorzystanie dodatkowej przestrzeni.

Oczywiście, same systemy plików używają rozmiarów bloków, które mogą być większe niż zawartość pojedynczego pliku, więc bądź ostrożny tam, gdzie je rozpakowujesz, system plików może nie być w stanie pomieścić wielu małych plików, nawet jeśli ma wolne miejsce większe niż rozmiar tar!

https://en.wikipedia.org/wiki/Tar_(computing)#Format_details

FantasticJamieBurns
źródło
Dzięki Jamie! Co tu robi „- mysql”? Czy to twoja nazwa pliku?
codecowboy
Właśnie to zmieniłem ... jest to ścieżka do twojego katalogu danych.
FantasticJamieBurns
1
Nie znaczy to, że to naprawdę ma znaczenie, ale użycie kombinacji argumentów -f -do tar jest zbędne, ponieważ możesz po prostu -fcałkowicie pominąć argument, aby zapisać wynik na stdout (tj tar -c data_dir.).
6

Rozmiar pliku tar będzie wynosił 937 MB plus rozmiar metadanych potrzebnych dla każdego pliku lub katalogu (512 bajtów na obiekt) oraz dopełnienie dodane w celu wyrównania plików do granicy 512 bajtów.

Bardzo przybliżone obliczenia mówią nam, że kolejna kopia twoich danych pozostawi ci 3,4 GB wolnego miejsca. W 3,4 GB mamy miejsce na około 7 milionów rekordów metadanych, przy założeniu braku dopełniania, lub mniej, jeśli założymy, że dopełnianie wynosi średnio 256 bajtów na plik. Więc jeśli masz miliony plików i katalogów do tarowania, możesz napotkać problemy.

Możesz złagodzić problem przez

  • kompresowanie w locie za pomocą opcji zlubjtar
  • robiąc to tarjak zwykły użytkownik, aby zarezerwowane miejsce na /partycji nie zostało zmienione, jeśli zabraknie miejsca.
Flup
źródło
2

tarsam może zgłaszać rozmiar swoich archiwów z --testopcją:

tar -cf - ./* | tar --totals -tvf -

Powyższe polecenie nie zapisuje nic na dysk i ma tę dodatkową zaletę, że wyświetla listę indywidualnych rozmiarów każdego pliku zawartego w archiwum. Dodanie różnych z/j/xzoperandów po obu stronach |pipeporadzi sobie z kompresją.

WYDAJNOŚĆ:

...
-rwxr-xr-x mikeserv/mikeserv         8 2014-03-13 20:58 ./somefile.sh
-rwxr-xr-x mikeserv/mikeserv        62 2014-03-13 20:53 ./somefile.txt
-rw-r--r-- mikeserv/mikeserv       574 2014-02-19 16:57 ./squash.sh
-rwxr-xr-x mikeserv/mikeserv        35 2014-01-28 17:25 ./ssh.shortcut
-rw-r--r-- mikeserv/mikeserv        51 2014-01-04 08:43 ./tab1.link
-rw-r--r-- mikeserv/mikeserv         0 2014-03-16 05:40 ./tee
-rw-r--r-- mikeserv/mikeserv         0 2014-04-08 10:00 ./typescript
-rw-r--r-- mikeserv/mikeserv       159 2014-02-26 18:32 ./vlc_out.sh
Total bytes read: 4300943360 (4.1GiB, 475MiB/s)

Nie jestem do końca pewien swojego celu, ale jeśli chcesz pobrać archiwum, może to być bardziej istotne:

ssh you@host 'tar -cf - ./* | cat' | cat >./path/to/saved/local/tarball.tar

Lub po prostu skopiować za pomocą tar:

ssh you@host 'tar -cf - ./* | cat' | tar -C/path/to/download/tree/destination -vxf -
mikeserv
źródło
Powodem tego jest to, że uważam, że dany katalog spowodował, że wyjście df -i osiągnęło 99%. Chcę zachować kopię katalogu do dalszej analizy, ale chcę wyczyścić miejsce
codecowboy
@codecowboy W takim przypadku zdecydowanie powinieneś najpierw zrobić coś takiego jak wyżej. Będzie on tarnastępnie skopiować drzewo na dysku lokalnym w strumieniu bez zapisywania czegokolwiek na dysku zdalnym wcale, po którym można go usunąć ze zdalnym hostem i przywrócić go później. Prawdopodobnie powinieneś dodać -zdo kompresji, jak wskazuje goldilocks, aby zaoszczędzić na przepustowości w trakcie transferu.
mikeserv
@ TAFKA „złote złociki” Nie, ponieważ to 99% i-węzłów, a nie 99% przestrzeni.
Gilles „SO- przestań być zły”
-itak, przepraszam!
złotowłosa
@ mikeserv twój wiersz początkowy wspomina o opcji --test, ale wydaje się, że nie używasz go w poleceniu, które następuje zaraz po nim (używa --totals)
codecowboy
2

Przeprowadziłem wiele badań w tym zakresie. Możesz wykonać test na pliku z liczbą słów, ale nie da ci tego samego numeru jak du -sb adir.

tar -tvOf afile.tar | wc -c

duliczy każdy katalog jako 4096 bajtów i tarliczy katalogi jako 0 bajtów. Musisz dodać 4096 do każdego katalogu:

$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096)))

musisz dodać wszystkie postacie. Dla czegoś, co wygląda tak:

$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096 + $(tar -xOf afile.tar | wc -c) ))

Nie jestem pewien, czy jest to idealne, ponieważ nie próbowałem dotkniętych plików (pliki 0 bajtów) lub plików, które mają 1 znak. To powinno cię przybliżyć.

tass6773
źródło
1

-cvfnie obejmuje żadnej kompresji, więc zrobienie tego w folderze ~ 1 GB spowoduje utworzenie pliku tar ~ 1 GB (odpowiedź Fluba zawiera więcej szczegółów na temat dodatkowego rozmiaru pliku tar, ale pamiętaj, że nawet jeśli jest 10 000 plików, to tylko 5 MB). Ponieważ masz 4 GB wolnego miejsca, nie, nie zapełnisz partycji.

łatwo dostępna do pobrania kopia

Większość osób uważa, że ​​„łatwiej” jest synonimem „mniejszego” pod względem pobierania, więc powinieneś użyć tutaj kompresji. bzip2myślę, że teraz powinien być dostępny w dowolnym systemie z / w tar, więc myślę, że włączenie jprzełączników jest prawdopodobnie najlepszym wyborem. z( gzip) jest być może jeszcze bardziej powszechne i istnieją inne (mniej wszechobecne) możliwości z większą liczbą squashów.

Jeśli masz na myśli, że tartymczasowo wykorzystuje dodatkowe miejsce na dysku do wykonania zadania, jestem pewien, że nie robi tego z kilku powodów, z których jeden pochodzi z czasów, gdy napędy taśm były formą podstawowej pamięci, a dwie z nich mają musiałem ewoluować przez dziesięciolecia (i jestem pewien, że nie jest konieczne stosowanie tymczasowej przestrzeni pośredniej, nawet jeśli wymagana jest kompresja).

Złotowłosa
źródło
0

Jeśli prędkość jest ważna i kompresja nie jest potrzebna, można zahaczyć syscall obwolut używanych przez tarużyciem LD_PRELOAD, aby zmienić targo obliczyć dla nas. Reimplementując kilka z tych funkcji w celu zaspokojenia naszych potrzeb (obliczając rozmiar potencjalnej wyjściowej danych smoły), jesteśmy w stanie wyeliminować wiele z nich readi writejest to wykonywane przy normalnym działaniu tar. To sprawia, że ​​jest tarznacznie szybszy, ponieważ nie musi kontekstowo przełączać się w jądro tam iz powrotem tak blisko, a tylko statżądany plik / folder (pliki) wejściowy musi zostać odczytany z dysku zamiast z rzeczywistych danych pliku.

Poniższy kod zawiera implementacje close, readoraz writefunkcji POSIX. Makro OUT_FDkontroluje, którego deskryptora pliku będziemy tarużywać jako pliku wyjściowego. Obecnie jest ustawiony na standardowe wyjście.

readzostał zmieniony tak, aby zwracał wartość sukcesu countbajtów zamiast wypełnienia bufora danymi, biorąc pod uwagę, że rzeczywiste dane nie zostały odczytane, buf nie zawierałby prawidłowych danych do przekazania na kompresję, a zatem gdyby zastosowano kompresję, obliczilibyśmy niepoprawne rozmiar.

writezostał zmieniony, aby sumować countbajty wejściowe do zmiennej globalnej totali zwracać wartość sukcesu countbajtów tylko wtedy, gdy deskryptor pliku jest zgodny OUT_FD, w przeciwnym razie wywołuje pierwotne opakowanie pozyskane przez, dlsymaby wykonać wywołanie systemowe o tej samej nazwie.

closenadal wykonuje wszystkie oryginalne funkcje, ale jeśli deskryptor pliku pasuje do OUT_FD, wie, że tarpróbowano zapisać plik tar, więc totalnumer jest ostateczny i wypisuje go na standardowe wyjście.

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>

#define OUT_FD 1
uint64_t total = 0;
ssize_t (*original_write)(int, const void *, size_t) = NULL;
int (*original_close)(int) = NULL;
void print_total(void)
{
    printf("%" PRIu64 "\n", total);
}

int close(int fd)
{
    if(! original_close)
    {
        original_close = dlsym(RTLD_NEXT, "close");
    }
    if(fd == OUT_FD)
    {
        print_total();
    }
    return original_close(fd);
}

ssize_t read(int fd, void *buf, size_t count)
{
    return count;
}

ssize_t write(int fd, const void *buf, size_t count)
{
    if(!original_write)
    {
        original_write = dlsym(RTLD_NEXT, "write");
    }
    if(fd == OUT_FD)
    {
        total += count;
        return count;
    }
    return original_write(fd, buf, count);
}

Benchmark porównujący rozwiązanie, w którym dostęp do dysku odczytu i wszystkie wywołania systemowe normalnej operacji tar wykonywane są przeciwko LD_PRELOADrozwiązaniu.

$ time tar -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/ | wc -c
332308480
real    0m0.457s
user    0m0.064s
sys     0m0.772s
tarsize$ time ./tarsize.sh -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/
332308480
real    0m0.016s
user    0m0.004s
sys     0m0.008s

Powyższy kod, podstawowy skrypt do budowania powyższego jako biblioteka współdzielona oraz skrypt LD_PRELOADwykorzystujący go w „ technice” znajduje się w repozytorium: https://github.com/G4Vi/tarsize

Kilka informacji na temat korzystania z LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/

G4Vi
źródło
Kod jest dobry, jeśli działa, ale czy możesz opisać, co on robi? Proszę nie odpowiadać w komentarzach; edytuj  swoją odpowiedź, aby była jaśniejsza i bardziej kompletna.
G-Man mówi „Przywróć Monikę”