Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- # Caution, do not run unless you already have a backup you trust.
- # I run this on my machine and I trust it.
- # But you should not trust a new backup plan unless you've not only
- # used it to backup, but also to do a successful restore.
- # This works for me, but it might not work for you.
- # Use at your own risk, I'm only an amateur, I miss up sometimes.
- # That said, it seems to work for me.
- #
- if [ "$(id -u)" != "0" ]; then
- exec sudo "$0" "$@"
- fi
- user="$SUDO_USER"
- hostname=$(hostname)
- main () {
- determinesource;
- checksource;
- gettarget;
- checktarget;
- askifformatdesired;
- if [[ $formatRequested == "y" ]]; then
- doformat;
- else
- echo "skipping format";
- fi
- doclone;
- fixgrub;
- }
- #*************************determinesource******************************
- determinesource () {
- slashmountedonpartition=$(mount | grep " / " | awk '{print $1}')
- if [[ $slashmountedonpartition == *"nvme"* ]]; then
- sourcedevice=${slashmountedonpartition::-2}
- else
- sourcedevice=${slashmountedonpartition::-1}
- fi
- }
- #***********************end determinesource****************************
- #***********************checksource****************************
- checksource () {
- numpartitions=$(lsblk -nlpo NAME,TYPE $sourcedevice | awk '$2=="part"{print $1}' | wc -l)
- if [ $numpartitions != 2 ]; then
- echo "Sorry, this script only works with 2 specific partitions"
- echo "Partition #1 must be exactly \"EFI System\""
- echo "Partition #2 must be exactly \"Linux filesystem\""
- exit 1
- fi
- if [[ $sourcedevice == *"nvme"* ]]; then
- efipartition="$sourcedevice"p1
- mainpartition="$sourcedevice"p2
- else
- efipartition="$sourcedevice"1
- mainpartition="$sourcedevice"2
- fi
- efishort=$(echo $efipartition | awk -F'/' '{print $3}')
- mainshort=$(echo $mainpartition | awk -F'/' '{print $3}')
- #echo "efishort is: $efishort"
- part1type=$(lsblk -o name,parttypename | grep $efishort | awk -F "$efishort" '{print $2}' | sed 's/^[[:space:]]*//')
- part2type=$(lsblk -o name,parttypename | grep $mainshort | awk -F "$mainshort" '{print $2}' | sed 's/^[[:space:]]*//')
- if [[ $part1type != "EFI System" || $part2type != "Linux filesystem" ]]; then
- echo "Sorry, partitions are wrong type"
- echo "Partition #1 must be exactly \"EFI System\""
- echo "Partition #2 must be exactly \"Linux filesystem\""
- exit 2
- fi
- }
- #***********************end checksource****************************
- #*********************gettarget******************************
- gettarget () {
- while [ "$response" != "y" ]; do
- read -p "Enter the device to clone to [/dev/sdx]: " targetdevice
- targetdevice=${targetdevice:-/dev/sdx}
- read -p "Is $targetdevice correct [y/N]? " response
- response=${response:-N}
- response="${response:0:1}"
- response="${response,,}"
- done
- }
- #***********************end gettarget****************************
- #************************checktarget*****************************
- checktarget () {
- numtargetpartitions=$(lsblk -nlpo NAME,TYPE $targetdevice | awk '$2=="part"{print $1}' | wc -l)
- if [[ $targetdevice == *"nvme"* ]]; then
- efipartition="$targetdevice"p1
- mainpartition="$targetdevice"p2
- else
- efipartition="$targetdevice"1
- mainpartition="$targetdevice"2
- fi
- efishort=$(echo $efipartition | awk -F'/' '{print $3}')
- mainshort=$(echo $mainpartition | awk -F'/' '{print $3}')
- part1type=$(lsblk -o name,parttypename | grep $efishort | awk -F "$efishort" '{print $2}' | sed 's/^[[:space:]]*//')
- part2type=$(lsblk -o name,parttypename | grep $mainshort | awk -F "$mainshort" '{print $2}' | sed 's/^[[:space:]]*//')
- if [[ $part1type != "EFI System" || $part2type != "Linux filesystem" ]]; then
- targetneedsformatted="true"
- else
- targetneedsformatted="false"
- fi
- }
- #**********************end checktarget***************************
- #*****************askifformatdesired*************************
- askifformatdesired () {
- if [[ $targetneedsformatted == "true" ]]; then
- echo -e "\n"
- read -p "Target device ($targetdevice) needs formatting, is that okay? [y/N]: " formatRequested
- formatRequested=${formatRequested:-N}
- formatRequested="${formatRequested:0:1}"
- formatRequested="${formatRequested,,}"
- if [[ $formatRequested != "y" ]]; then
- echo "Format needed but refused, aborting."
- exit;
- fi
- else #format not needed but still an option
- echo -e "\nTarget has preexisting clone."
- echo -e "Preexisting clone can either be refreshed or created anew. (default is to refresh the existing clone)"
- read -p "Format and create a new clone? [y/N]: " formatRequested
- formatRequested=${formatRequested:-N}
- formatRequested="${formatRequested:0:1}"
- formatRequested="${formatRequested,,}"
- fi
- }
- #**************end askifformatdesired************************
- #*******************doformat************************
- doformat () {
- possiblelabel="$(hostname)usb"
- echo
- read -p "Enter a new label for the target device (e.g. [$possiblelabel]): " label
- label=${label:-$possiblelabel}
- echo "Label of target device will be: $label"
- echo "This might take a few minutes, please be patient."
- fdisk $targetdevice <<EOF
- g
- n
- 1
- +512M
- t
- C12A7328-F81F-11D2-BA4B-00A0C93EC93B
- n
- 2
- w
- EOF
- echo "efi and ext4 partitions created successfully."
- echo "The new partitions will now be formatted"
- echo "This might take a few minutes, please be patient."
- mkfs.fat -F32 -n EFI "$efipartition"
- yes | mkfs.ext4 -L "$label" "$mainpartition"
- sync
- }
- #******************end doformat*********************
- #*******************doclone************************
- doclone () {
- echo "making the clone"
- label="target"
- mount /boot/efi
- mkdir -p /media/$user/EFI
- mount "$efipartition" /media/$user/EFI
- mkdir -p /media/$user/$label
- mount "$mainpartition" /media/$user/$label
- sourceuuid=$(findmnt / -o UUID -n)
- targetuuid=$(findmnt /media/$user/"$label" -o UUID -n)
- sourceefiuuid=$(grep /boot/efi /etc/fstab | awk '{print $1}' | grep UUID | sed -E 's/UUID=(.*)/\1/' )
- targetefiuuid=$(findmnt /media/$user/EFI/ -o UUID -n)
- rsync -rv --delete /boot/efi/ /media/$user/EFI/
- #trying to make it more distro independent... not well tested
- find /media/$user/EFI/ -name "grub.cfg" -exec sed -i "s/$sourceuuid/$targetuuid/" "{}" \;
- #old way proven to work on my Mint Mate installation but wouldn't work if grub.cfg is inside a differently named folder
- # sed -i "s/$sourceuuid/$targetuuid/" /media/$user/EFI/EFI/ubuntu/grub.cfg
- rsync -axAXHv --exclude='/dev/*' --exclude='/proc/*' --exclude='/sys/*' --exclude='/tmp/*' --exclude='/run/*' --exclude='/mnt/*' --exclude='/media/*' --exclude='/lost+found/' --delete / /media/$user/"$label"/
- sed -i "s/$sourceuuid/$targetuuid/" /media/$user/$label/etc/fstab
- sed -i "s/$sourceuuid/$targetuuid/" /media/$user/$label/boot/grub/grub.cfg
- sed -i "s/$sourceefiuuid/$targetefiuuid/" /media/$user/$label/etc/fstab
- echo "Writing changes to target, do not remove!"
- sync
- }
- #*******************doclone************************
- #*******************fixgrub************************
- fixgrub () {
- for i in /sys /run /dev /proc; do mount --bind "$i" "/media/$user/target$i"; done
- chroot /media/$user/target/ /bin/bash -- << EOT
- update-grub
- EOT
- for i in /proc /dev /run /sys; do umount "/media/$user/target$i"; done
- umount /media/$user/EFI
- umount /media/$user/target
- rmdir /media/$user/target
- rmdir /media/$user/EFI
- echo "It is now okay to remove the target drive."
- }
- #*****************end fixgrub**********************
- main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement