I am using a Win7 machine and a bunch of Pis. Some of them took weeks to configure. I would like to backup their SD cards in case they break. It should be backed up so that if it breaks I could simply buy a new card and reload the backup onto it and plug into the Pi. When I put the cards in my SD card reader on the Windows machine, it does not recognize it as containing files.

  • Sorry if this sounds blunt but I really wonder if none of the existing questions addresses this issue. – Ghanima Sep 13 '17 at 20:38
up vote 0 down vote accepted

A disk imager should be able to make a full image of your card, even if the underlying OS can't read the partitions on that card. Win32DiskImager is popular on Windows. The image will be the size of the full card, whether or not you actually use all of the space, so a 32 GB card will yield a 32 GB image file. You do have to ensure that the target disk is larger than the source image.

Yes it can be done. There is an easy and a complicated solution. I'm only able to describe it on a unix system e.g. a mac or linux. But you can use any VM to emulate e.g. linux on windows.

Easy

sudo dd bs=1m if=path_of_your_image.img of=/dev/<disknumber>
e.g. disknumber = disk4
    ctr + T
        shows status

if is the input => the path to your raspberry sd card of is the output file e.g. myBackup.img

If you want to roll back the backup you can then change if and of. The image size is the size of the SD card.

Complicated

but better (because it shrinks the image to the space which is really used). This only works on a linux machine. I run ubuntu with parallels.

Copy this script to any_filename.sh and execute it:

#!/bin/bash

device=$1
outfile=$2
optionZip=$3

# sanity checks on the command line parameters
if [ "${device}" == "" ]; then
    echo "Please specify device, e.g. $0 /dev/sda <filename>" 1>&2;
    exit 1;
fi;

if [ "${outfile}" == "" ]; then
    echo "Please specify filename, e.g. $0 <device> zymbit.img.zip" 2>&1;
    exit 1;
fi;

# sanity checks on the partition layout
fdisk -l "${device}" | grep -q "${device}1.*W95 FAT32"
if [ "$?" != "0" ]; then
    echo 'The first partition is expected to be FAT32' 1>&1;
    exit 1;
fi;

fdisk -l "${device}" | grep -q "${device}2.*Linux"
if [ "$?" != "0" ]; then
    echo 'The second partition is expected to be Linux' 1>&1;
    exit 1;
fi;

# converts and pads given bytes into MB
# Takes the given number in bytes and (by nature of integer division) rounds
# the number of bytes down to the nearest hundred bytes.  That value is then
# padded by 200MB.  The padding was determined by trial and error when
# attempting to image a 1.6GB linux partition.
# TODO: determine a better way to calculate the padding.
function convert_bytes()
{
    local bytes=$1
    local rounded=0

    let rounded="((${bytes}/100000000)+2)*100"

    echo ${rounded}
}

# start the dangerous stuff
linux_partition="${device}2"
umount "${device}2"

# do not continue of there are errors
set -e

e2fsck -f "${linux_partition}"

# call resize2fs to shrink the partition down to the minimum size it needs to be.
# parse the output to know how big the partition is in bytes
let bytes=$(resize2fs -M "${linux_partition}" 2>&1 | grep -i -e "The filesystem .*is .*blocks long" | sed -e 's/.*is [^ ]* \([0-9]*\) (4k) blocks.*/\1*4096/')
echo "resized partition"

# convert the value in bytes returned by resize2fs to MB
let megs_rounded=$(convert_bytes ${bytes})

# use parted to shrink the partition down.
# when shrinking the partition down parted will prompt for confirmation.  the
# following post notes to append yes to the operation:
# https://bugs.launchpad.net/ubuntu/+source/parted/+bug/1270203/comments/2
parted --align optimal "${device}" unit MB resizepart 2 "${megs_rounded}" yes
echo "resized 2"

# use last value in the `End` column to know how much to image
let total_bytes=$(parted "${device}" unit B print | grep -v '^$' | awk '{print $3}' | tail -n 1 | sed -e 's/B//');
let total_megs_rounded=$(convert_bytes ${total_bytes})

if [ "${optionZip}" == "true" ]; then
    # generate a zip file on the fly
    #time dd bs=1M if=${device} count=${total_megs_rounded} | gzip -9 > ${outfile}
    imgfile=$(echo "${outfile}" | sed -e 's/.zip$//')
    if [ "${imgfile}" == "${outfile}" ]; then
        imgfile=sdcard.img
    fi;

    # drop the .img to disk and then zip so that Macs can read the file
    dd bs=1M if="${device}" of="${imgfile}" count="${total_megs_rounded}"
    echo "copied"

    zip "${outfile}" "${imgfile}"
    echo "zipped"
    rm "${imgfile}"
else
    dd bs=1M if="${device}" of="${outfile}" count="${total_megs_rounded}"
    echo "copied"
fi;

# expand the filesystem back
full_size=$(parted "${device}" print | grep "Disk ${device}" | awk '{print $3}')
parted "${device}" resizepart 2 "${full_size}"
echo "expanded"
# wait up to 10 seconds for the linux partition to show up
for i in {0..9}; do
    [ -e "${linux_partition}" ] && break
    sleep 1
done;

# if the linux partition didn't show up, this will fail
resize2fs "${linux_partition}"
sudo eject "${device}"
echo "done"
exit 0;

I copied this code from zymbit and modified it a bit.

To install the image again I use etcher.io. You have to expand the file system after flashing the image.

Either with raspi-config or by executing this script:

#!/bin/sh
get_init_sys() {
  if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
    SYSTEMD=1
  elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
    SYSTEMD=0
  else
    echo "Unrecognised init system"
    return 1
  fi
}

do_expand_rootfs() {
  get_init_sys
  if [ $SYSTEMD -eq 1 ]; then
    ROOT_PART=$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p')
  else
    if ! [ -h /dev/root ]; then
      whiptail --msgbox "/dev/root does not exist or is not a symlink. Don't know how to expand" 20 60 2
      return 0
    fi
    ROOT_PART=$(readlink /dev/root)
  fi

  PART_NUM=${ROOT_PART#mmcblk0p}
  if [ "$PART_NUM" = "$ROOT_PART" ]; then
    whiptail --msgbox "$ROOT_PART is not an SD card. Don't know how to expand" 20 60 2
    return 0
  fi

  # NOTE: the NOOBS partition layout confuses parted. For now, let's only
  # agree to work with a sufficiently simple partition layout
  if [ "$PART_NUM" -ne 2 ]; then
    whiptail --msgbox "Your partition layout is not currently supported by this tool. You are probably using NOOBS, in which case your root filesystem is already expanded anyway." 20 60 2
    return 0
  fi

  LAST_PART_NUM=$(parted /dev/mmcblk0 -ms unit s p | tail -n 1 | cut -f 1 -d:)
  if [ $LAST_PART_NUM -ne $PART_NUM ]; then
    whiptail --msgbox "$ROOT_PART is not the last partition. Don't know how to expand" 20 60 2
    return 0
  fi

  # Get the starting offset of the root partition
  PART_START=$(parted /dev/mmcblk0 -ms unit s p | grep "^${PART_NUM}" | cut -f 2 -d: | sed 's/[^0-9]//g')
  [ "$PART_START" ] || return 1
  # Return value will likely be error for fdisk as it fails to reload the
  # partition table because the root fs is mounted
  fdisk /dev/mmcblk0 <<EOF
p
d
$PART_NUM
n
p
$PART_NUM
$PART_START

p
w
EOF
  ASK_TO_REBOOT=1

  # now set up an init.d script
cat <<EOF > /etc/init.d/resize2fs_once &&
#!/bin/sh
### BEGIN INIT INFO
# Provides:          resize2fs_once
# Required-Start:
# Required-Stop:
# Default-Start: 3
# Default-Stop:
# Short-Description: Resize the root filesystem to fill partition
# Description:
### END INIT INFO

. /lib/lsb/init-functions

case "\$1" in
  start)
    log_daemon_msg "Starting resize2fs_once" &&
    resize2fs /dev/$ROOT_PART &&
    update-rc.d resize2fs_once remove &&
    rm /etc/init.d/resize2fs_once &&
    log_end_msg \$?
    ;;
  *)
    echo "Usage: \$0 start" >&2
    exit 3
    ;;
esac
EOF
  chmod +x /etc/init.d/resize2fs_once &&
  update-rc.d resize2fs_once defaults &&
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "Root partition has been resized.\nThe filesystem will be enlarged upon the next reboot" 20 60 2
  fi
}

do_expand_rootfs
  • I think you want to flip if and of in your easy section (which uses dd). Currently you have it set up to take an img file as and write it to a device node (e.g. a physical device. The OP asked how to take the data off of the SD card an back it up. Hence, we want to create an img file as output, not accept it as input. – airfishey Sep 13 '17 at 19:18
  • Hardly relevant to the OP who is using Windows. – Milliways Sep 13 '17 at 23:47

You can save your OS by using SDcard copier application in the raspbian.

For that you just need an extra empty SDcard.

You can do it by.

  1. Format the new sdcard
  2. Insert it Pi using card reader
  3. Open menu->accessories->sd card copier 4.Select the proper device for copy from device(sdcard running in Pi) and copy to device(inserted sdcard)

It takes about 5-10 minutes to complete. After that boot the pi using this new sdcard. And enjoy the same OS which you have it on the old sdcard

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.