Jak zmienić rozmiar pliku IMG utworzonego za pomocą DD?

19

Mam obraz DD z karty SD o pojemności 4 GB, która ma dwie partycje, te dwie partycje zużywają tylko około 800 MB i dlatego chcę zmniejszyć rozmiar obrazu.

Czy ktoś zna sposób na usunięcie „wolnego miejsca” z pliku img?

A_Porcupine
źródło
możesz dodać pożądany wynik. tj .: obraz z powrotem na kartę, aby zapisać na płycie CD.
Wayne

Odpowiedzi:

8

Najpierw upewnij się, że wolne miejsce jest faktycznie puste i nie zawiera resztek usuniętych plików. Najłatwiejszym sposobem na osiągnięcie tego jest utworzenie na dysku ogromnego pliku zawierającego tylko bajty zerowe, a następnie usunięcie go.

# losetup --find --partscan foo.img
# lsblk
NAME      MAJ:MIN RM    SIZE RO TYPE MOUNTPOINT
loop0       7:0    0   4096M  0 loop 
├─loop0p1 259:0    0   2048M  0 loop 
└─loop0p2 259:1    0   2048M  0 loop 
# for part in /dev/loop0p*; do
    mount $part /mnt
    dd if=/dev/zero of=/mnt/filler conv=fsync bs=1M
    rm /mnt/filler
    umount /mnt
  done
dd: error writing ‘/mnt/filler’: No space left on device
dd: error writing ‘/mnt/filler’: No space left on device
# losetup --detach /dev/loop0

Następnie skompresuj go za pomocą narzędzia takiego jak gziplub xz. Nawet przy najniższych poziomach kompresji długa seria zer dobrze kompresuje:

# ls -s
4096M foo.img
# gzip foo.img
# ls -s
11M foo.img.gz

Pamiętaj, że musisz rozpakować obraz podczas zapisywania go z powrotem na dysk. Spowoduje to rozpakowanie go „na żywo”:

# cat foo.img.gz | gunzip | dd of=/dev/sda

Należy pamiętać, że urządzenie wyjściowe (sda) musi mieć wystarczający rozmiar, aby pasował do oryginalnego obrazu, w przeciwnym razie dane zostaną utracone lub uszkodzone.


Alternatywną metodą, jeśli chcesz nadal używać obrazu - np. Na maszynie wirtualnej - jest konwersja surowego obrazu na jeden z formatów obrazów używanych przez oprogramowanie do wirtualizacji; np. qcow2 dla Qemu, VDI dla VirtualBox lub VMDK dla VMware.

Pamiętaj, że nadal wymaga to przygotowania obrazu poprzez wyczyszczenie wolnego miejsca za pomocą powyższej metody.

# qemu-img convert -f raw -O qcow2 foo.img foo.qcow

# qemu-img convert -f raw -O vmdk foo.img foo.vmdk

Ale jeśli będzie on ponownie zapisany na prawdziwym dysku, musisz przekonwertować go z powrotem na surowy obraz.

użytkownik1686
źródło
1
skąd możesz mieć pewność, że wszystkie pliki, które są obecnie przechowywane na partycjach, nie są fizycznie rozproszone na dysku?
Valerio Santinelli
ponieważ podejrzewam, że pliki nie są zapisywane sekwencyjnie na dysku, a jeśli plik znajduje się na końcu magazynu, po zmniejszeniu rozmiaru stracę zawartość tego pliku.
Valerio Santinelli,
Ponieważ OP pyta, jak zmniejszyć obraz dysku bez utraty danych. Jeśli obetniesz obraz o określonym rozmiarze, nie możesz być pewien, że dane zostaną zachowane.
Valerio Santinelli,
@ValerioSantinelli: Gdzie dokładnie sugeruję obcięcie obrazu?
user1686
1
@ValerioSantinelli: Używając odpowiedniego narzędzia zmiany rozmiaru systemu plików dla twojego systemu plików, np. resize2fsLub ntfsresize(Linux nie ma narzędzia do FAT), przed zapisaniem go na mniejszym urządzeniu lub przez utworzenie nowego systemu plików i skopiowanie tylko plików.
user1686,
22

Korzystanie resize2fsjest znacznie łatwiejsze

resize2fs -M xxx.img

najpierw zostaniesz poproszony o e2fsck - więc:

e2fsck -f -y xxx.img

(obraz NIE MOŻE być montowany!)

Uwaga: zadziała to tylko wtedy, gdy obraz składa się z jednej partycji, jeśli jest to całe urządzenie blokowe z wieloma partycjami patrz powyższa odpowiedź ...

Serge Wagner
źródło
Tylko uwaga: w przypadku wielu partycji użyj, losetup --find --partscan xxx.imgaby ustawić plik obrazu jako urządzenie pętli. następnie uruchom, lsblkaby znaleźć partycje urządzenia pętli.
Yihui Xiong
Wygląda na to, że nie działa w przypadku obrazu ISO zawierającego system operacyjny. Po zmianie rozmiaru system nie uruchamia się.
SR
System operacyjny Linux @SR?
Rolf
1
To bardzo miła odpowiedź, ale resize2fsdotyczy tylko extNpartycji typu. Inne typy partycji będą wymagały innych narzędzi.
Rolf
2

Próbowałem też z qemu-img i działało to jak urok:

qemu-img resize test.img 2G

Zmieniamy rozmiar, test.imgaby uczynić go 2G (2 GB).

Działa dla mnie bezbłędnie.

Phil Roggenbuck
źródło
1
Niesamowite, działało również dla mnie bezbłędnie, kompresując obraz Raspbian. W pełni funkcjonujący!
fleandro
Cóż, wszystko działa, jednak po uruchomieniu, uruchamianie df -hpokazuje oryginalny rozmiar. Jak to jest możliwe?
fleandro
Najwyraźniej qemu-img nie ma tablicy partycji, więc w jaki sposób kompresuje .img?
ffleandro
Mogę zmienić rozmiar dysku .img na 1M, co zdecydowanie psuje obraz dysku. Masz pomysł, aby zmiana rozmiaru była bezpieczniejsza?
lesca
1

W moim komputerze Ubuntu 16.10 zastosowałem podejście gparted:

1) Zamapuj plik img na następnej dostępnej partycji pętli losetup, jak opisano w poprzednich postach, jak powyżej

2) Sprawdź, na lsblkktórym napędzie pętli jest mapowany plik obrazu, np/dev/loop0

3) Wykonaj sudo gparted /dev/loop0

4) Zmniejsz partycje pętli, jeśli uzna to za stosowne; upewnij się, że te partycje są odmontowane.

5) Wykonaj fdisk /dev/loop0, a następnie wprowadź p, to pokaże rozmiar bloku i końcowy numer bloku różnych partycji.

6) wykonywanie dd if=/dev/loop0 of=shrunk_image_file.img, stosuje się do tego polecenia opcje bs=[BlockSize]i count=[EndBlockNumberOfLastLoopPartition+1]i trzeba będzie skurczył i Rightsizing plik obrazu.

VeryNoob
źródło