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.
4 Answers
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
-
1I think you want to flip
if
andof
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. Sep 13, 2017 at 19:18 -
1
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.
- Format the new sdcard
- Insert it Pi using card reader
- 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
If you have a big SD card 16 GB, 32 GB etc but you want to save space with backup you can use:
sudo apt-get install gnome-disk-utility
Open disk utility to check witch letter is your usb drive actually has:
gnome-disks
In my case a 32GB SD card with Raspberry image on it recognised as: /dev/sde
So I can run:
sudo dd bs=4M status=progress if=/dev/sde | gzip > \
/you-selected-full-path-here/raspberry-images/`date +%Y%m%d`_rpi_image_backup.gz
status=progress gives you progress bar indication
| gzip > compresses the 32 GB total size and not writing the empty space from the 32 GB
`date +%Y%m%d` writes today date in the filename
Output: 20190529_rpi_image_backup.gz
And the size is only 3.5GB. If you want to write this image to a new SD card use:
Also you can write this image made from 32 GB to a 16 GB or 8 GB disk, it is not complaining about that the image is too large anymore.
-
2
-
I wrote this answer for everybody not just for grather_columbia, who Google "SD card backup". This question is one of the first hits. I can't find this answer anywhere else, that's why I posted here.– jturiMay 31, 2019 at 11:51