Skopiuj istniejącą instalację Raspbian na mniejszą kartę SD

25

Czy można skopiować istniejącą i skonfigurowaną instalację Raspbian na mniejszą kartę SD?

Kiedy po raz pierwszy zainstalowałem Raspbian, miałem pod ręką tylko kartę 32 GB, która oczywiście jest większa niż potrzeba.

mwld
źródło
System będzie działał lepiej, a karta będzie działać dłużej z większą ilością wolnego miejsca na partycji podstawowej, więc nie zmniejszaj go zbytnio - utrzymaj przynajmniej dwukrotnie więcej zużycia (np. Jeśli twój system ma 2-3 GB użyj 8 GB i powiększ partycję, aby wypełnić całą dostępną przestrzeń). Pamiętaj, że jeśli nie zwiększysz partycji na początek, nie będzie ona 32 GB, więc nie musisz jej zmniejszać.
złotowłosy
Dzięki za zwrócenie na to uwagi, ale moja Raspberry używa obecnie tylko 1,8 GB, ponieważ jest to naprawdę podstawowa instalacja. Myślę, że 4 GB powinno wystarczyć.
mwld
Wydaje mi się, że dorastałem do pełnego rozmiaru, kiedy pierwszy raz zainstalowałem Debian Wheezy. Teraz zmniejszyłem go do 2,5 GB, ale nadal nie mam sukcesu. Zobacz moje komentarze poniżej.
mwld
Prawie duplikat: raspberrypi.stackexchange.com/q/29947/5538
goldilocks
1
Jeśli jedna z poniższych odpowiedzi spełnia twoje pytanie, sprawdź odpowiedź.
Wes Modes

Odpowiedzi:

12

W tej odpowiedzi pokazuję, co robić krok po kroku, aby ludzie mogli zrozumieć logikę rozwiązania i móc zastosować kroki w innych problemach.

Ale po pierwsze, należy stwierdzić, że migracja systemów plików z karty SD na mniejszą (ale wystarczająco dużą dla danych) kartę SD jest ogólnym (nie specyficznym dla raspi) problemem.

Wymagania

Laptop z czytnikiem kart micro SD i działającym na nim Linuksem (wolę Ubuntu).

Skróty

PIBOX      : Raspberry Pi which is used
SD_CARD_A  : 8GB micro SD card which is used on PIBOX and on which Raspbian-lite (the OS) is installed
SD_CARD_B  : 2GB micro SD card which will be used on PIBOX and on which Raspbian-lite (the OS) will be installed

Partycje SD_CARD_A

Gdy PIBOX jest uruchomiony, wyświetlamy listę partycji (niepotrzebne partycje systemowe nie są tutaj wyświetlane).

root@pibox:~# df -Th
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/root      ext4      7.3G  1.1G  5.9G  16% /
/dev/mmcblk0p1 vfat       63M   21M   43M  33% /boot

Istnieją 2 partycje na karcie SD_CARD_A jako /i /boot. Nawet 2 GB nie jest w całości wykorzystywane.

Kopia zapasowa SD_CARD_A

Po wyłączeniu i zatrzymaniu PIBOX, wyjmujemy SD_CARD_A z płyty PIBOX i wkładamy do czytnika kart naszego laptopa.

Partycje SD_CARD_A są automatycznie montowane w naszym systemie jako /dev/sdc1i /dev/sdc2.

root@mylaptop:~# df -Th
Filesystem                    Type      Size  Used Avail Use% Mounted on
/dev/sdb2                     ext4       22G   13G  7.9G  63% /
/dev/sdb1                     vfat      197M  2.6M  195M   2% /boot/efi
/dev/sda8                     ext4       66G   11G   52G  17% /home
/dev/sdc1                     vfat       63M   21M   43M  33% /media/some_user_name/boot
/dev/sdc2                     ext4      7.3G  1.1G  5.9G  16% /media/some_user_name/some_uuid_serial

Odmontujemy te partycje z naszego systemu, aby działały na nich skutecznie.

root@mylaptop:~# umount /dev/sdc1
root@mylaptop:~# umount /dev/sdc2

Wyświetlamy informacje o urządzeniu SD_CARD_A w szczegółach w celu potwierdzenia w kolejnych krokach.

root@mylaptop:~# fdisk -l /dev/sdc
Disk /dev/sdc: 7969 MB, 7969177600 bytes
246 heads, 62 sectors/track, 1020 cylinders, total 15564800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x2019f6d8

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1            8192      137215       64512    c  W95 FAT32 (LBA)
/dev/sdc2          137216    15564799     7713792   83  Linux

Powyżej widać, że SD_CARD_A ma pojemność 8 GB.

Klonujemy SD_CARD_A do pliku pibox.img.

root@mylaptop:~# dd bs=4MB if=/dev/sdc of=pibox.img
1992+1 records in
1992+1 records out
7969177600 bytes (8.0 GB) copied, 416.582 s, 19.1 MB/s

Sprawdź rozmiar skopiowanych bajtów, jest on równy wartości otrzymanej przez fdisk -l /dev/sdcpolecenie.

Linuxowy moduł sprzężenia zwrotnego

Linux ma moduł o nazwie loopback, który zapewnia nam obsługę pliku jako urządzenia blokowego.

Ładujemy moduł sprzężenia zwrotnego.

root@mylaptop:~# modprobe loop

Znajdujemy nieużywaną ścieżkę urządzenia pętli zwrotnej.

root@mylaptop:~# losetup -f /dev/loop0

Teraz tworzymy urządzenie loopback dla pliku pibox.img.

root@mylaptop:~# losetup /dev/loop0 pibox.img

Wywołujemy jądro o zmianach partycji.

root@mylaptop:~# partprobe /dev/loop0

Potwierdzamy, czy poprzednie operacje zakończyły się powodzeniem.

root@mylaptop:~# losetup /dev/loop0
/dev/loop0: [0806]:69 (/root/pibox.img)

Wyświetlamy szczegółowe informacje o urządzeniu pętli zwrotnej, aby porównać je z SD_CARD_A.

root@mylaptop:~# fdisk -l /dev/loop0
Disk /dev/loop0: 7969 MB, 7969177600 bytes
255 heads, 63 sectors/track, 968 cylinders, total 15564800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x2019f6d8

      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1            8192      137215       64512    c  W95 FAT32 (LBA)
/dev/loop0p2          137216    15564799     7713792   83  Linux

Powyżej widać, że rozmiar urządzenia sprzężenia zwrotnego (= 7969177600 bajtów) i partycje są takie same jak SD_CARD_A.

Podstawowa matematyka

Odtąd skupimy się na partycji /dev/loop0p2. Nazwijmy to THE_PARTITION .

Rozmiar bloku wynosi 512 bajtów (jak wydrukowano w wierszu rozpoczynającym się od Units = sektory .....)

THE_PARTITION zaczyna się od bloku 137216 i kończy na bloku 15564799, co oznacza, że ​​ma rozmiar 15427584 blocks(= 15564799 - 137216 + 1).

Tak więc rozmiar THE_PARTITION w bajtach wynosi 7898923008 bytes(= 512 * 15427584).

Aby zmieścić THE_PARTITION w SD_CARD_B, chcemy, aby miał nowy rozmiar 3710940 blocks lub innymi słowy 1900001280 bytes(= 512 * 3710940).

Tak więc nowy numer bloku końcowego jest 3848155obliczany przez start block number(= 137216) + size in blocks(= 3710940) - 1.

System plików a partycja

Istnieją 2 operacje, których nie należy mylić.

  • Zmiana rozmiaru systemu plików. Zmniejszymy system plików w THE_PARTITION, ustawiając jego rozmiar na 3710940 blocks.
  • Zmiana rozmiaru partycji. Zmniejszymy THE_PARTITION, ustawiając jego numer bloku końcowego na 3848155.

Zmniejszający się system plików

Przed zmniejszeniem systemu plików należy go oznaczyć jako czysty e2fsck.

root@mylaptop:~# e2fsck -f /dev/loop0p2
e2fsck 1.42.9 (4-Feb-2014)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/loop0p2: 41175/475776 files (0.2% non-contiguous), 309183/1928448 blocks

Zmniejszamy system plików resize2fs.

root@mylaptop:~# resize2fs /dev/loop0p2 3710940s
resize2fs 1.42.9 (4-Feb-2014)
Resizing the filesystem on /dev/loop0p2 to 463867 (4k) blocks.
The filesystem on /dev/loop0p2 is now 463867 blocks long.

Ścianka działowa

Dowiadujemy się, z czym jest numer THE_PARTITION parted.

root@mylaptop:~# parted /dev/loop0
GNU Parted 2.3
Using /dev/loop0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print                                                            
Model: Loopback device (loop)
Disk /dev/loop0: 7969MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End     Size    Type     File system  Flags
 1      4194kB  70.3MB  66.1MB  primary  fat16        lba
 2      70.3MB  7969MB  7899MB  primary  ext4

(parted) quit

Zmniejszamy THE_PARTITION za pomocą parted.

root@mylaptop:~# parted /dev/loop0 unit s resizepart 2 3848155
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? Yes  

Skończyliśmy z urządzeniem loopback. Odłączamy to.

root@mylaptop:~# losetup -d /dev/loop0

Obcinanie pliku obrazu

Sprawdzamy nową tablicę partycji.

root@mylaptop:~# fdisk -l pibox.img 

Disk pibox.img: 7969 MB, 7969177600 bytes
255 heads, 63 sectors/track, 968 cylinders, total 15564800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x2019f6d8

    Device Boot      Start         End      Blocks   Id  System
pibox.img1            8192      137215       64512    c  W95 FAT32 (LBA)
pibox.img2          137216     3848155     1855470   83  Linux

Na wyjściu wyraźnie widać, że końcowy numer bloku THE_PARTITION jest zmniejszony from 15564799 to 3848155.

Ostatni używany przez nas blok 3848155. Numeracja bloków zaczyna się od 0. Mamy więc łącznie 3848155 + 1 bloków i nowy rozmiar pliku pibox.img powinien wynosić 1970255872 bytes (= (3848155 + 1) * 512).

Obcinamy plik pibox.img.

root@mylaptop:~# truncate --size=1970255872 pibox.img

Sprawdzamy nowy rozmiar pliku pibox.img.

root@mylaptop:~# ls -l pibox.img 
-rw-r--r-- 1 root root 1970255872 Oct 13 21:53 pibox.img

Tworzenie SD_CARD_B

Umieszczamy SD_CARD_B w czytniku kart naszego laptopa. Partycje SD_CARD_B są automatycznie montowane w naszym systemie jako /dev/sdc1i /dev/sdc2.

root@mylaptop:~# df -Th
Filesystem                    Type      Size  Used Avail Use% Mounted on
/dev/sdb2                     ext4       22G   13G  7.9G  63% /
/dev/sdb1                     vfat      197M  2.6M  195M   2% /boot/efi
/dev/sda8                     ext4       66G   11G   52G  17% /home
/dev/sdc1                     vfat       63M   21M   43M  33% /media/some_user_name/boot
/dev/sdc2                     ext4      1.8G  1.6G   59M  97% /media/some_user_name/some_uuid_serial

Powyżej widać, że SD_CARD_B ma pojemność 2 GB.

Odmontujemy te partycje z naszego systemu, aby pomyślnie działały na karcie SD_CARD_B.

root@mylaptop:~# umount /dev/sdc1
root@mylaptop:~# umount /dev/sdc2

Klonujemy plik pibox.img do SD_CARD_B.

root@mylaptop:~# dd bs=4MB if=pibox.img of=/dev/sdc
492+1 records in
492+1 records out
1970255872 bytes (2.0 GB) copied, 646.967 s, 3.0 MB/s

Sprawdź rozmiar skopiowanych bajtów, jest on równy wartości otrzymanej przez ls -l pibox.imgpolecenie.

Uruchamianie PIBOX

Po wyjęciu SD_CARD_B z naszego laptopa i włożeniu go do płyty PIBOX, uruchamiamy system i logujemy się do konsoli PIBOX.

Podajemy listę partycji (niektóre inne niepotrzebne partycje systemowe nie są tutaj wyświetlane).

root@pibox:~# df -Th
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/root      ext4      1.8G  1.1G  601M  64% /
/dev/mmcblk0p1 vfat       63M   21M   43M  33% /boot
vaha
źródło
Dobry. Myślę, że niektóre z twoich rzeczy związanych z konfigurowaniem pętli zwrotnej mogą być długie i niepotrzebne, możesz to sprawdzić. Coś bardzo podobnego z bardzo podobnego pytania: raspberrypi.stackexchange.com/a/29952/5538
goldilocks
@Goldilocks, nie testowałem, ale myślę, że konieczne jest użycie sprzężenia zwrotnego. O ile wiem, że parted nie może bezpośrednio pracować na pliku obrazu, potrzebuje interfejsu urządzenia do swoich operacji.
vaha
Tak, ale myślę, że przekonasz się, że nie musisz się tym przejmować losetupani nawet -o loop=whatever. Podobnie jak w innym poście, którego używam, mount -o offset=123 /imagefilepath /mntpointa użycie sprzężenia zwrotnego jest niejawne. Domyślam się, że jest to ogólnie prawda na Linuksie - spróbuj i zobacz. Następnie możesz sprowadzić to do stwierdzenia, że ​​partycje są montowane za pomocą wirtualnego „urządzenia sprzężenia zwrotnego”.
goldilocks
5

Gdy użyjesz dd if=/dev/sdx of=/path/to/image bs=1M, /dev/sdxodnosi się do całego „dysku”, więc obraz zawsze będzie miał rozmiar całej karty.

Zamiast tego musisz użyć dd if=/dev/sdxn ...gdzie njest numer partycji.

Prawdopodobnie będziesz musiał to zrobić dwa razy - raz dla /bootpartycji i raz dla /partycji.

Następnie musisz utworzyć partycje na nowej karcie, które są co najmniej tak duże jak te dwie oryginalne, aby dodać zawartość z powrotem.

John La Rooy
źródło
3

Użyj czegoś w rodzaju parted (edytor partycji), aby zmniejszyć partycję podstawową do mniejszego rozmiaru, a następnie użyj narzędzia takiego jak Clonezilla, aby skopiować z mniejszej partycji na nową kartę. Prawdopodobnie będziesz musiał to zrobić na innym komputerze.

Jerry Gagnon
źródło
Niestety to nie zadziałało. Za pomocą GParted zmniejszyłem partycję do 2,5 GB. Ale kiedy próbowałem utworzyć z niego obraz na pamięć USB, stał się on znacznie większy (4,3 GB - ale myślę, że chciał skopiować całe 32 GB i po prostu zatrzymał się na 4,3 GB z powodu ograniczenia rozmiaru pliku FAT).
mwld
2
Użyłem polecenia dd if=/dev/sdx of=/path/to/image bs=1Mz tego wątku: raspberrypi.stackexchange.com/questions/311/…
mwld
Czy masz jakieś pomysły, w jaki sposób mogę po prostu skopiować partycję podstawową z 2,5 GB do obrazu i nadal tworzyć z niej kartę SD z bootowalnym Raspbianem?
mwld
Przepraszam za późną odpowiedź. Zacząłem od karty SD 4 GB, utworzyłem obraz, a następnie zapisałem ten obraz na kartach 8 GB i większych. Nie musiałem używać większej partycji do niczego, nad czym pracowałem. Nie znam narzędzia, które pozwoli ci stworzyć obraz pojedynczej partycji na karcie SD.
Jerry Gagnon
3
  1. Utwórz obraz karty przy użyciu jednej z wyżej wymienionych metod - Jak wykonać kopię zapasową mojego Raspberry Pi?

  2. Użyj skryptu na stronie http://sirlagz.net/2013/03/10/script-automatic-rpi-image-downsizer/, aby zmniejszyć rozmiar obrazu

  3. Przywróć zmniejszony obraz na nowej, mniejszej karcie

Mihir
źródło
Wpadłem na tę stronę, gdy próbuję osiągnąć ten sam cel, aby wykonać kopię zapasową mojego obrazu raspbian, ale nie chcę, aby cała karta TYLKO istotne dane na karcie. Zgodnie z powyższą sugestią szukałem skryptu tutaj sirlagz.net/2013/03/10/script-automatic-rpi-image-downsizer, ale nie mogłem go znaleźć. czy ktoś może zaktualizować ten link, jeśli jest on dostępny?
shallyverma
Nadal mogę uzyskać dostęp do linku, a sam post jest skryptem. Skopiuj skrypt do pliku i nazwij go script.sh, Spraw, aby plik był wykonywalny przy użyciu chmodi uruchom go.
Mihir,
1

Od jakiegoś czasu używam rsyncdo kopiowania systemów plików z jednego dysku na drugi, bez żadnych problemów. Zaletą używania rsync jest to, że kopiuje on zawartość systemu plików, zamiast robić kopię urządzenia na poziomie bloku; w rezultacie tak naprawdę nie ma znaczenia, jaki jest rozmiar dysku docelowego i źródłowego, o ile dysk docelowy ma wystarczająco dużo miejsca do przechowywania danych.

Oto jak bym to zrobił:

  1. Utwórz nową instalację Raspbian na wybranej, mniejszej karcie SD.
  2. Uruchom nową instalację i rozwiń system plików, aby wypełnić cały dysk. Zamknij pi.
  3. Teraz zamontuj nowe i stare karty i użyj rsync -avx oldFilesystem newFilesystemdo skopiowania / zastąpienia systemu plików na nowej karcie systemem plików ze starej karty.
  4. Na koniec uruchom nowy system i uruchom, rpi-updateaby upewnić się, że oprogramowanie układowe jest spójne i aktualne.

Następnie na nowej karcie powinien być zainstalowany doskonale funkcjonalny system Raspbian.

sdenton4
źródło
Więc do tej metody (krok 3) potrzebuję 2 czytników kart SD?
Victor Van Hee
Albo dwa czytniki kart SD, albo urządzenie pośrednie. Możesz zsynchronizować stary system plików z folderem na dysku twardym, a następnie zsynchronizować ten folder z drugą kartą SD, jeśli nie chcesz wybierać czytnika.
sdenton4
1

Stworzyłem skrypt powłoki, aby wykonać kopię zapasową i przywrócić wszystkie dane na karcie SD. Najpierw usuwa niektóre dane (odpowiadające mojemu projektowi) i zmniejsza partycję do minimalnego rozmiaru, aby obraz był tak duży, jak dane na karcie SD. Dodatkowo skrypt tworzy plik * .zip obrazu. Po przywróceniu utworzonego obrazu na innej karcie SD partycja zostanie powiększona do maksymalnego rozmiaru. Skrypt korzysta z poleceń wymienionych w innych odpowiedziach. Ponieważ jest to mój skrypt powłoki pięści o takim rozmiarze, jego utworzenie zajęło mi wiele godzin i nie jest to idealny jet. Szczególnie nie wiem, jak obsługiwać zwracane wartości resize2fs i fdisk, więc użytkownik musi wpisać wartości, których potrzebuję. Czy są jakieś pomysły, aby to naprawić? Mam nadzieję, że ten skrypt pomaga komuś innemu. Możesz go edytować i ulepszać.

"Usage:
    <skriptname> -b <path>                  create backup of SC Card (dev/mmcblk0) to file <path>/JJJJ-MM-DD_HHMM.img
    <skriptname> -r <path>/FILENAME.img     restore an exitsting image (<path>/FILENAME.img) to the SD Card (dev/mmcblk0) 
    <skriptname> -r <path>/FILENAME.zip     unzip and restore an exitsting image (<path>/FILENAME.zip) to the SD Card (dev/mmcblk0)
    <skriptname> -h                         show this hlep

tutaj jest:

#!/bin/bash 

# check if the user is root
if (( $EUID != 0 )); then
  echo "This script requires root privileges please run as root"
  exit
fi


while getopts ":b:r:h" opt; do
  case $opt in
    b)
      mode="backup"
      OUTPATH=$OPTARG
      ;;
    r)
      mode="restore"
      DIRFILENAME=$OPTARG
      ;;
    h)
      mode="help"
      ;;
    \?)
      echo "Invalid option: -$OPTARG. Use -h for help" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument. Use -h for help" >&2
      exit 1
      ;;
  esac
done
# no option
if [ $OPTIND == 1 ]
then
  echo "$(basename "$0") needs an option! Use -h for help"
  exit 1
fi


myMount(){
  # create mountpoint if not existing
  if [ ! -d /tmp/sd2/ ] ; then
    mkdir /tmp/sd2
  fi

  # mount partition
  mount -v -t ext4 /dev/mmcblk0p2 /tmp/sd2
  err=$?
  if [ $err != 0 ]; then
    echo "mount failed error: $err"
    exit 1
  fi
}

myUmount(){
  cd /home/ # otherwise umount will fail
  # fuser -vm /tmp/sd2/

  # umount partition
  umount -v /tmp/sd2
  err=$?
  if [ $err != 0 ]; then
    echo "umount failed error: $err"
    exit 1
  fi
}

myEnlarge(){
  echo "enlarge partition..."
  # enlarge partition is not posible with fdisk -> delete and recreate it
  (
  echo d # delete partition
  echo 2 # patition number
  echo n # add a new partition
  echo p # primary partition
  echo 2 # partition number
  echo   # first sector (accept default: varies)
  echo   # last sector (accept default: varies)
  echo w # write changes
  ) | fdisk /dev/mmcblk0

  echo "\n check filesystem... "
  e2fsck -f -v -C 0 /dev/mmcblk0p2

  # enlarge filesystem to maxsize
  resize2fs -p /dev/mmcblk0p2
}

case "$mode" in
"help")
  echo "Usage:
    $(basename "$0") -b <path>                  create backup of SC Card (dev/mmcblk0) to file <path>/JJJJ-MM-DD_HHMM.img
    $(basename "$0") -r <path>/FILENAME.img     restore an exitsting image (<path>/FILENAME.img) to the SD Card (dev/mmcblk0) 
    $(basename "$0") -r <path>/FILENAME.zip     unzip and restore an exitsting image (<path>/FILENAME.zip) to the SD Card (dev/mmcblk0)
    $(basename "$0") -h                         show this hlep
--------------------------------
Adrian Zeitler, Germany 2017"
  ;;
"backup")  ####################################### backup ####################################### 
  echo "an image of the SD Card (/dev/mmcblk0) whitch is as smal as possible will be created to $OUTPATH."
  # ------------------  delete some data --------------------

  echo "Do you want to delete tempfiles? [y/n]" 
  read delfiles

  if [ "$delfiles" = "y" ]
    then
      echo "Delete tempfiles..."

      myMount

      # remove some data
      cd /tmp/sd2/home/alarm/
      rm -v -f hagelbeere.db
      rm -v -f HAILcam.log
      rm -v -f HAILcam.log.1
      rm -v -f test.jpg

      myUmount

    elif [ "$delfiles" = "n" ]
      then
    echo "I don't delete anything."
    else
    echo "Sorry, I didn't understand."
    exit 1
  fi


  # --------------------------------------------------------------
  # shrink partition 2 to minimum size

  echo "check file system... "
  e2fsck -f -v -C 0 /dev/mmcblk0p2
  err=$?
  if [ $err != 0 ]; then
    echo "file system check failed, error: $err"
    exit 1
  fi

  echo "shrink filesystem of partition 2 to minimum size..."
  resize2fs -p -M /dev/mmcblk0p2
  err=$?
  if [ $err != 0 ]; then
    echo "resize2fs failed, error: $err"
    exit 1
  fi
  # --> Das Dateisystem auf /dev/mmcblk0p2 ist nun 692365 Blöcke groß.

  echo "Please tell me the new filesystem size displayed above:"
  read size
  # from resize2fs blocksize, fdisk wants sector: sector = block * 8
  size=$(( $size*8 ))

  # shrink partition is not posible with fdisk -> delete and recreate it
  (
  echo d # delete partition
  echo 2 # patition number
  echo n # add a new partition
  echo p # primary partition
  echo 2 # partition number
  echo   # first sector (accept default: varies)
  echo +$size  # last sector
  echo w # write changes
  ) | fdisk /dev/mmcblk0
  err=$?
  if [ $err != 0 ]; then
    echo "fdisk failed, error: $err"
    exit 1
  fi


  # --------------------------------------------------------------

  # fill unused space with zeros
  echo "Do you want to fill unused space with zeros? [y/n]" 
  read fillzeros


  if [ "$fillzeros" = "y" ]
    then
      echo "Copy zeros. This will end up with an error. But this is ok."

      myMount    

      dd if=/dev/zero | pv | dd of=/tmp/sd2/nullen.datei conv=noerror,notrunc,sync bs=10240
      # exits with error -> this is normal

      # dlelete zeros
      rm -v -f /tmp/sd2/nullen.datei
      sync

      myUmount

    elif [ "$fillzeros" = "n" ]
      then
    echo "I don't delete anything."
    else
    echo "Sorry, I didn't understand."
    exit 1
  fi

  # --------------------------------------------------------------

  # find out end of partition
  fdisk -l /dev/mmcblk0
  echo "Please tell me the end of mmcblk0p2 displayed above."
  read count



  DATE=$(date +"%Y-%m-%d_%H%M")
  IMGFILENAME=$DATE.img 
  echo "Do you want to create image with filename $OUTPATH$IMGFILENAME? [y/n]"
  read answer
  if [ "$answer" = "y" ]
  then
    echo "Do you want to create a *.zip file of the created image? [y/n]"
    read zip
    echo "Do you want to enlarge partition 2 to maxsize after image creation? [y/n]"
    read enlarge

    echo "create image..."
    cd $OUTPATH
    # create image with dd, stop at and of partition
    # count=N   copy only N input blocks
    # bs=BYTES  read and write up to BYTES bytes at a time = block size
    # pv    show status
    dd if=/dev/mmcblk0 | pv -s $(( $count*512 )) | dd of=$IMGFILENAME bs=512 count=$count
    err=$?
    if [ $err != 0 ]; then
      echo "dd failed error: $err"
      exit 1
    fi

    # --------------------------------------------------------------
    # create zip file
    # or like this:
    # sudo dd if=/dev/sdX | pv |gzip > /pfad/zur/datei.img.gz
    if [ "$zip" = "y" ]
    then
      echo "create zip file..."
      zip $DATE.zip $IMGFILENAME
    fi
    # --------------------------------------------------------------
  fi

  # --------------------------------------------------------------
  # enlarge partition 2

  if [ "$enlarge" = "y" ]
  then
    myEnlarge
  fi

  ;; #end case mode backup
"restore")  ####################################### restore ####################################### 
  #chek if image exists
  if [[ -s "$DIRFILENAME" ]]
  then
    # check if file is an image or zip file
    if [[ $DIRFILENAME =~ \.img$ ]]
    then
      IMGFILENAME=$(basename "$DIRFILENAME")
    elif [[ $DIRFILENAME =~ \.zip$ ]]
    then
      ZIPFILENAME=$(basename "$DIRFILENAME")
    else
      echo "Not the right file format. I accept *.img and *.zip"
      exit 1
    fi
  else
    echo "Image file does not exist."
    exit 1
  fi
  echo "the file $DIRFILENAME will be restored to the SD Card /dev/mmcblk0"

  #change to the path of the imagefile
  SOURCEPATH=$(dirname "$DIRFILENAME")
  cd $SOURCEPATH


  if [ "$ZIPFILENAME" != "" ]
  then
    echo "unzip file"
    # change file extention form zip zu img
    l=$(( ${#ZIPFILENAME}-3 ))
    IMGFILENAME="${ZIPFILENAME:0:l}img"
    unzip $ZIPFILENAME
  fi

  echo "Do you realy want to restore $SOURCEPATH/$IMGFILENAME to the SD card /dev/mmcblk0? 
  Warning: all data on the device /dev/mmcblk0 will be lost! [y/n]"
  read answer
  if [ "$answer" = "y" ]
  then
    echo "Do you want to enlarge partition 2 to maxsize after restoring? [y/n]"
    read enlarge
    echo "restore image..."
    filesize=$(wc -c <"$IMGFILENAME")
    echo "Filesize = $filesize Byte"
    dd if=$IMGFILENAME | pv -s $filesize | dd of=/dev/mmcblk0 bs=512
    err=$?
    if [ $err != 0 ]; then
      echo "dd failed error: $err"
      exit 1
    fi
  fi

  # --------------------------------------------------------------
  # enlarge partition 2
  if [ "$enlarge" = "y" ]
  then
    myEnlarge
  fi

  ;; #end case mode restore
esac
Adrian
źródło
0

Najłatwiejszym rozwiązaniem, jakie znalazłem, było wykonanie kopii zapasowej oryginalnej większej karty za pomocą komend dd opisanych powyżej, a następnie przywrócenie obrazu na mniejszej karcie za pomocą czegoś takiego jak piwriter. dd może również działać ... nie jestem pewien. PiWriter zwrócił błąd, ponieważ zabrakło mu miejsca, ale ponieważ obraz nie zawierał żadnych rzeczywistych danych przekraczających rozmiar mniejszej karty, po prostu obcinał puste sektory. Nie jestem pewien, jakie są tego konsekwencje ... partycja może wymagać sprawdzenia lub naprawy, ale mogę sprawdzić, czy zadziałała, gdy wstawiłem ją do Pi.

Pies
źródło
1
jest to bardzo niebezpieczna rada, nigdy nie dowiesz się, czy rzeczywiście istnieją jakiekolwiek dane przekraczające rozmiar. szukamy bardziej niezawodnych i sprawdzonych rozwiązań.
lenik
Żyję niebezpiecznie, co mogę powiedzieć;) Z całą powagą, chociaż nie mam dużego doświadczenia w pracy z mapami dd lub partycjonowania, więc jestem tutaj na nieznanym terytorium. Prawdopodobnie miałem szczęście, ponieważ miałem tylko około 800 MB danych przechodzących z karty 16 GB na kartę 8 GB. Jednak z ciekawości, czy jest jakiś sposób, aby najpierw zdefragmentować dane, aby upewnić się, że wszystkie są zgrupowane na początku partycji? Wygląda na hackerskiego, ale może?
Pooch
nie wiem o defragmentacji, ale zdecydowanie możesz zmienić rozmiar partycji i przenieść je na początek karty SD, aby zajmowały tylko początek. zajmuje trochę dłużej niż zwykłe dd, ale wyniki są znacznie bardziej wiarygodne.
lenik
0

Używam starej wersji win32diskimager-RELEASE-0.1-r15-win32do odczytu obrazu, tworzy obraz 4 GB nawet z karty SD 8 GB, a następnie zapisuje obraz w najnowszej wersji programu win32diskimager.

Używam starszej wersji, ponieważ stara pominie każdy błąd.

Double-G
źródło
Czy w nowej wersji 0.95 nie ma opcji, która pozwala robić to samo, tzn. Pomijać każdy błąd? Niestety strona sourceforge nie wyświetla żadnej z dostępnych opcji. Wydaje się, że korzystanie z oprogramowania w wersji beta jest nieco ryzykowne
Greenonline
Nie dostaję żadnych problemów z używaniem programu, który pominie każdy błąd.
RufusVS