dd na całym dysku, ale nie chcę pustej części


33

Mam dysk, powiedzmy / dev / sda.

Oto fdisk -l:

 Disk /dev/sda: 64.0 GB, 64023257088 bytes
255 heads, 63 sectors/track, 7783 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0000e4b5

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          27      209920   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2              27         525     4000768    5  Extended
Partition 2 does not end on cylinder boundary.
/dev/sda5              27         353     2621440   83  Linux
/dev/sda6             353         405      416768   83  Linux
/dev/sda7             405         490      675840   83  Linux
/dev/sda8             490         525      282624   83  Linux

Muszę zrobić obraz do przechowywania na naszym serwerze plików do użycia w flashowaniu innych urządzeń, które produkujemy, więc chcę tylko zajętego miejsca (tylko około 4 GB). Chcę zachować MBR itp., Ponieważ to urządzenie powinno być gotowe do rozruchu, gdy tylko kopia zostanie ukończona.

Jakieś pomysły? Wcześniej używałem dd if=/dev/sda of=[//fileserver/file], ale w tym czasie moja główna kopia była na idei flash 4GB.


2
Wszystkie poniższe odpowiedzi są nieprawidłowe, z wyjątkiem @sudoer. Prawidłowa odpowiedź to użycie dd conv=sparse.
bahamat

@bahamat, nie, gzip jest lepszy, ponieważ kompresuje dane.
psusi

1
To nie to samo, co rzadkie.
bahamat

@ bahamat, pytanie nie dotyczy konkretnie sprase; jak sprawić, by obraz zajmował mniej miejsca.
psusi

Odpowiedzi:


37

Kiedyś miałem podobny problem z osadzonymi dystrybucjami Linuksa - pozbyć się wszystkich śmieci przed skompresowaniem obrazu.

dd if=/dev/zero of=asdf.txt. Poczekaj, aż umrze. Usuń plik asdf.txt.

Właśnie napisałeś zera do całego wolnego miejsca na urządzeniu.

Teraz weź obraz dysku i uruchom go przez gzip. Voila, rzadki obraz.

Prawdopodobnie nie skaluje się zbyt dobrze i może powodować problemy, jeśli rzeczywiście chcesz zapisać na dysk, ale hej.

Możesz wziąć migawkę rsync dysku na inny wolumin, wyzerować go, a następnie wziąć obraz dysku.

Uwaga: może to być niebezpieczne dla dysku SSD, użytkownik powinien rozważyć tę operację przed zatwierdzeniem.


jeśli uruchomię go przez gzip, czy muszę go rozpakować przed użyciem? I uruchamiając go przez gzip, czy po prostu sipuluję go podczas procesu dd?
Jonathan Henson

3
Tak. dd if=sda2.gz | gunzip > /dev/sda2orazdd if=/dev/sda2 | gzip > sda2.gz
Rob Bos

3
„Właśnie napisałeś zera do całego wolnego miejsca na urządzeniu”. Myślę, że masz na myśli partycję, a nie urządzenie. Musisz więc uruchomić to polecenie ze ofścieżką dla każdej partycji.
jiggunjer

Jeśli nośnikiem fizycznym jest dysk SSD, może teraz wydawać się, że wykorzystano każdy sektor na urządzeniu. To da dyskowi SSD mniej sektorów zapasowych do pracy i może w rezultacie obniżyć wydajność. Jeśli sterownik i oprogramowanie wewnętrzne obsługują TRIM, warunek ten będzie obowiązywał tylko do momentu ponownego usunięcia pliku. Jeśli plik zostanie zachowany podczas tworzenia obrazu, po przywróceniu obrazu konieczne będzie jego ponowne usunięcie. Może to być przydatne, jeśli obraz zostanie przywrócony na dysk SSD.
kasperd

Należy pamiętać o kilku dodatkowych kwestiach. Ponieważ ta metoda wymaga zamontowania systemu plików w trybie odczytu i zapisu, istnieje ryzyko, że zmiany w podstawowym systemie plików podczas kopiowania doprowadzą do niespójnego obrazu. Pewnego razu widziałem, że powstały egzemplarz jest tak niespójny, że fsck faktycznie segfault przy próbie naprawy niespójności na kopii. Również wypełnienie urządzenia może spowodować niepowodzenia innych procesów wymagających zapisu na nośniku.
kasperd

17

Zakładając, że chcesz zapisać /dev/sdXNsię /tgtfs/image.rawi jesteś root:

  1. mkdir /srcfs && mount /dev/sdXN /srcfs

  2. Użyj zerofill lub po prostu: dd if=/dev/zero of=/srcfs/tmpzero.txtaby wypełnić nieużywane bloki zerem (poczekaj, aż całkowicie wypełni system plików rm /srcfs/tmpzero.txt)

  3. Zrób zdjęcie za pomocą dd i użyj conv = sparse, aby zerować zera w locie: dd conv=sparse if=/dev/sdxn of=/tgtfs/image.raw

Jeśli chcesz użyć kompresji, nie musisz dziurkować zer za pomocą dd, ponieważ bloki zerowe są wysoce ściśliwe:

dd if=/dev/sdxn | gz -c | dd of=/tgtfs/image.raw

PS: Należy pamiętać, że nie jest to dobry pomysł na nośnikach pamięci opartych na pamięci flash (tzn. Źródłowym systemem plików jest SSD)


5
To jest poprawna odpowiedź. Zastosowanie dd conv=sparse.
bahamat

1
Co jest złego w robieniu tego w pamięci flash?
Dan

2
@Dan (w zależności od projektu i konfiguracji sprzętu i oprogramowania) może powodować znaczny zapis na dysku SSD i skrócić jego żywotność. i ogólnie rzecz biorąc, można przenosić dane ze starego dysku na nowy (lub to, co chciał zrobić OP), ale tworzenie kopii zapasowych na poziomie dysku / partycji nie jest dobrym rozwiązaniem do regularnego tworzenia kopii zapasowych i przywracania, nawet na dyskach twardych. plik kopii zapasowej poziom (czyli kopiowanie plików z jednego systemu plików do innego), lub tworzenia kopii zapasowych na poziomie systemu plików (z systemów plików Btrfs z jak btrfs snapshoti btrfs sendnarzędzi) jest lepszym rozwiązaniem IMHO.
Sudoer,

Wskazówka: jeśli nie masz gzna swoim PATH(tak jak ja, na GParted Live), możesz użyć gzip -czamiast tego.
XtraSimplicity

11

Użyj dd z opcją liczenia.

W twoim przypadku korzystałeś z fdisk, więc przyjmuję to podejście. Twój „sudo fdisk -l” wyprodukował:

    Disk /dev/sda: 64.0 GB, 64023257088 bytes
    255 heads, 63 sectors/track, 7783 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x0000e4b5

    Device Boot      Start         End      Blocks   Id  System
    /dev/sda1   *           1          27      209920   83  Linux
    Partition 1 does not end on cylinder boundary.
    /dev/sda2              27         525     4000768    5  Extended
    Partition 2 does not end on cylinder boundary.
    /dev/sda5              27         353     2621440   83  Linux
    /dev/sda6             353         405      416768   83  Linux
    /dev/sda7             405         490      675840   83  Linux
    /dev/sda8             490         525      282624   83  Linux

Należy zwrócić uwagę na dwie rzeczy: 1) rozmiar jednostki i 2) kolumnę „Koniec”. W twoim przypadku masz cylindry, które są równe 8225280 bajtów. W kolumnie „Koniec” sda8 kończy się na 525 (czyli 525 [jednostkach] * 16065 * 512 = ~ 4,3 GB)

dd może robić wiele rzeczy, takich jak rozpoczynanie po przesunięciu lub zatrzymywanie po określonej liczbie bloków. Zrobimy to drugie, używając opcji count w dd. Polecenie wyglądałoby następująco:

    sudo dd if=/dev/sda of=/your_directory/image_name.iso bs=8225280 count=526

Gdzie -bs jest rozmiarem bloku (najłatwiej jest użyć jednostki używanej przez fdisk, ale dowolna jednostka zrobi to tak długo, jak długo opcja liczenia jest zadeklarowana w tych jednostkach), a liczba to liczba jednostek, które chcemy skopiować (uwaga zwiększamy liczbę o 1, aby przechwycić ostatni blok).


FYI: aby wyświetlić jednostki w cylindrach, użyjfdisk -l -u=cylinders /dev/sda
xinthose

3
Dlaczego nie jest to zaakceptowana odpowiedź? Wydaje się, że jest to najmniej inwazyjna opcja, ponieważ nie modyfikuje źródła.
user33326

@ user33326, ponieważ ta odpowiedź jest dobra, aby nie kopiować niepartycjonowanego miejsca na dysku, a nie nieużywanego miejsca w partycjach, na tym właśnie zależy OP.
GDorn

8

Podczas gdy /dev/zerozajmowanie wolnego miejsca na dysku i używanie dd conv=sparse/ gz -cjest możliwe, na ogromnych dyskach z pustą przestrzenią działającą w 100 GB pamięci, /dev/zeroing jest boleśnie powolne - nie wspominając o tym, jak zauważono w innych odpowiedziach, /dev/zerozapisując SDD do EOF.

Oto, co zrobiłem, gdy wpadłem na taką sytuację:

  • Na Live CD lubuntu, używanym gparteddo „zmniejszania” dysku do minimalnego możliwego rozmiaru, pozostawiając nieprzydzielone miejsce

  • Służy
    dd bs=1M count=<size_in_MBs> if=/dev/sdX | gzip -c --fast| dd of=/path/to/image.gz do tworzenia szybko skompresowanego obrazu (nie trzeba dodawać, że możesz pominąć kompresję, jeśli masz wystarczająco dużo miejsca do przechowywania surowych danych (lub w inny sposób chcesz zmniejszyć obciążenie procesora)

  • Służy
    dd if=/path/to/image.gz | gunzip -c | dd bs=1M of=/dev/sdY do kopiowania danych z powrotem na inny dysk
  • Służy gpartedponownie do „rozszerzania” partycji

Nie próbowałem tego na wielu partycjach, ale uważam, że powyższy proces można dostosować do kopiowania „partycji”, jeśli najpierw utworzona zostanie tablica partycji na dysku docelowym i skopiowane zostaną tylko dane zawarte na partycji dd- odczyt / zapis przesunięć ( skip/ seekopcja ddodpowiednio) byłaby wymagana odpowiednio.


1
to jest prawdziwa odpowiedź, wystarczy użyć countparametru
Gordy

7

Nie możesz ddjest narzędziem bardzo niskiego poziomu i nie ma możliwości rozróżnienia plików od pustej przestrzeni.

Z drugiej strony pusta przestrzeń będzie się bardzo, bardzo ładnie kompresować, więc jeśli martwisz się tylko o przestrzeń dyskową, nie na przykład o czas zapisu, po prostu prześlij ją przez gzip.


7
Zakładając, że wolne miejsce nie było wcześniej używane. Możesz najpierw zerować wolne miejsce, aby zapewnić, że kompresja działa zgodnie z oczekiwaniami.
Sirex,

1
Prawdziwe. A to tylko komplikuje proces i sprawia, że ​​trwa to jeszcze dłużej.
c2h5oh 16.10.12

6

Zakładając, że reszta dysku jest pusta (wszystkie zera), możesz przesłać DD przez gzip, co powinno całkiem ładnie skompresować puste miejsce. Możesz użyć narzędzia takiego jak zeroofree, aby upewnić się, że puste miejsce jest rzeczywiście puste, więc ładnie się kompresuje.

Jeśli użyjesz narzędzia takiego jak partimage , clonezilla lub niektóre z innych narzędzi do klonowania linuxa, większość z nich zajmie się tobą automatycznie.


partimage i clonezilla są w rzeczywistości wystarczająco inteligentne, aby pominąć czytanie wolnego miejsca, zamiast polegać na tobie, aby zapisywać do niego zera, a następnie dd lub gzip upuszczają lub kompresują zera po ich odczytaniu.
psusi

2

Przyjęta odpowiedź jest nieprawidłowa. Zgadzam się z powyższym komentarzem. Używam dd z parametrem count do regularnego tworzenia kopii zapasowej dysku. Po prostu zamień BACKUP_FOLDER i literę urządzenia na „X”:

Zdefiniuj ostatnio używany blok dysku:

ct=$(fdisk -l | awk '$1 == "/dev/sdX" { print $3 }')

Następnie klonowanie dysku (z wyjątkiem pustej przestrzeni):

dd if=/dev/sdX bs=512 count=$ct | gzip > BACKUP_FOLDER/sdX_$(date +"%Y-%m-%d").img.gz >>"$LOG"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.