chuggerguy

clonetodevice minus the source check

Jun 27th, 2025
31
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 8.71 KB | Software | 0 0
  1. #!/bin/bash
  2. # Caution, do not run unless you already have a backup you trust.
  3. # I run this on my machine and I trust it.
  4. # You should not trust a new backup plan unless you've not only
  5. # used it to backup, but also to do a successful restore.
  6. # This works for me, but it might not work for you.
  7. # I run Mint Mate with a standard two partition install. If you've done custom partitioning (separate home/swap/etc partitions)
  8. # it won't work for you. I made an attempt to assess whether it will work for you or not but, not guarantees)
  9. # Use at your own risk, I'm only an amateur, I mess up sometimes.
  10. # That said, it works for me. Feel free to try it. (maybe try cloning to USB first?)
  11. #
  12. # This is my original clonetodevice with "checksource" disabled.
  13. # Normally, checksource checks for the presence of only two specific partitions on the source but can work if
  14. # The drive has only one EFI partition and one Linux root partition.
  15. # For example, my laptop had extra partitions for Windows so when I forgot that and ran it, I ended up with a
  16. # bootable USB with two partitions, it ignored the Windows partitions. So... it worked fine.
  17. # Still, use at your own risk, try it on a USB. If the result is a bootable Linux USB that you're happy with
  18. # maybe clone the USB back to an internal device?
  19.  
  20. if [ "$(id -u)" != "0" ]; then
  21.   exec sudo "$0" "$@"
  22. fi
  23.  
  24. user="$SUDO_USER"
  25. hostname=$(hostname)
  26.  
  27. main () {
  28.     determinesource;
  29. #    checksource;
  30.     gettarget;
  31.     checktarget;
  32.     askifformatdesired;
  33.     if [[ $formatRequested == "y" ]]; then
  34.         doformat;
  35.     else
  36.         echo "skipping format";
  37.     fi
  38.     doclone;
  39.     fixgrub;
  40. }
  41.  
  42. #*************************determinesource******************************
  43. determinesource () {
  44.      slashmountedonpartition=$(mount | grep " / " | awk '{print $1}')
  45.  
  46.     if [[ $slashmountedonpartition == *"nvme"* ]]; then
  47.         sourcedevice=${slashmountedonpartition::-2}
  48.      else
  49.         sourcedevice=${slashmountedonpartition::-1}
  50.     fi
  51. }
  52. #***********************end determinesource****************************
  53.  
  54. #***********************checksource****************************
  55. checksource () {
  56. numpartitions=$(lsblk -nlpo NAME,TYPE $sourcedevice | awk '$2=="part"{print $1}' | wc -l)
  57.  
  58. if [ $numpartitions != 2 ]; then
  59.     echo "Sorry, this script only works with 2 specific partitions"
  60.     echo  "Partition #1 must be exactly \"EFI System\""
  61.     echo "Partition #2 must be exactly \"Linux filesystem\""
  62.     exit 1
  63. fi
  64.  
  65. if [[ $sourcedevice == *"nvme"* ]]; then
  66.     efipartition="$sourcedevice"p1
  67.     mainpartition="$sourcedevice"p2
  68. else
  69.     efipartition="$sourcedevice"1
  70.     mainpartition="$sourcedevice"2
  71. fi
  72.  
  73. efishort=$(echo $efipartition | awk -F'/' '{print $3}')
  74. mainshort=$(echo $mainpartition | awk -F'/' '{print $3}')
  75.  
  76.  
  77. #echo "efishort is: $efishort"
  78.  
  79. part1type=$(lsblk -o name,parttypename | grep $efishort | awk -F "$efishort" '{print $2}' | sed 's/^[[:space:]]*//')
  80.  
  81. part2type=$(lsblk -o name,parttypename | grep $mainshort | awk -F "$mainshort" '{print $2}' | sed 's/^[[:space:]]*//')
  82.  
  83. if [[ $part1type != "EFI System"  || $part2type != "Linux filesystem" ]]; then
  84.     echo "Sorry, partitions are wrong type"
  85.     echo "Partition #1 must be exactly \"EFI System\""
  86.     echo "Partition #2 must be exactly \"Linux filesystem\""
  87.     exit 2
  88. fi
  89.  
  90. }
  91. #***********************end checksource****************************
  92.  
  93. #*********************gettarget******************************
  94. gettarget () {
  95.     while [ "$response" != "y" ]; do
  96.         read -p "Enter the device to clone to [/dev/sdx]: " targetdevice
  97.         targetdevice=${targetdevice:-/dev/sdx}
  98.         read -p "Is $targetdevice correct [y/N]? " response
  99.         response=${response:-N}
  100.         response="${response:0:1}"
  101.         response="${response,,}"
  102.     done
  103. }
  104. #***********************end gettarget****************************
  105.  
  106. #************************checktarget*****************************
  107. checktarget () {
  108.     numtargetpartitions=$(lsblk -nlpo NAME,TYPE $targetdevice | awk '$2=="part"{print $1}' | wc -l)
  109.  
  110.     if [[ $targetdevice == *"nvme"* ]]; then
  111.         efipartition="$targetdevice"p1
  112.         mainpartition="$targetdevice"p2
  113.     else
  114.         efipartition="$targetdevice"1
  115.         mainpartition="$targetdevice"2
  116.     fi
  117.  
  118.     efishort=$(echo $efipartition | awk -F'/' '{print $3}')
  119.     mainshort=$(echo $mainpartition | awk -F'/' '{print $3}')
  120.  
  121.     part1type=$(lsblk -o name,parttypename | grep $efishort | awk -F "$efishort" '{print $2}' | sed 's/^[[:space:]]*//')
  122.  
  123.     part2type=$(lsblk -o name,parttypename | grep $mainshort | awk -F "$mainshort" '{print $2}' | sed 's/^[[:space:]]*//')
  124.  
  125.     if [[ $part1type != "EFI System"  || $part2type != "Linux filesystem" ]]; then
  126.         targetneedsformatted="true"
  127.     else
  128.         targetneedsformatted="false"
  129.     fi
  130. }
  131. #**********************end checktarget***************************
  132.  
  133. #*****************askifformatdesired*************************
  134. askifformatdesired () {
  135.  
  136.     if [[ $targetneedsformatted == "true" ]]; then
  137.         echo -e "\n"
  138.         read -p "Target device ($targetdevice) needs formatting, is that okay? [y/N]: " formatRequested
  139.         formatRequested=${formatRequested:-N}
  140.         formatRequested="${formatRequested:0:1}"
  141.         formatRequested="${formatRequested,,}"
  142.         if [[ $formatRequested != "y" ]]; then
  143.             echo "Format needed but refused, aborting."
  144.             exit;
  145.         fi
  146.     else #format not needed but still an option
  147.         echo -e "\nTarget has preexisting clone."
  148.         echo -e "Preexisting clone can either be refreshed or created anew. (default is to refresh the existing clone)"
  149.         read -p "Format and create a new clone? [y/N]: " formatRequested
  150.         formatRequested=${formatRequested:-N}
  151.         formatRequested="${formatRequested:0:1}"
  152.         formatRequested="${formatRequested,,}"
  153.     fi
  154. }
  155. #**************end askifformatdesired************************
  156.  
  157. #*******************doformat************************
  158. doformat () {
  159.     possiblelabel="$(hostname)usb"
  160.     echo
  161.     read -p "Enter a new label for the target device (e.g. [$possiblelabel]): " label
  162.     label=${label:-$possiblelabel}
  163.     echo "Label of target device will be: $label"
  164.     echo "This might take a few minutes, please be patient."
  165.     fdisk $targetdevice <<EOF
  166. g
  167. n
  168. 1
  169.  
  170. +512M
  171. t
  172. C12A7328-F81F-11D2-BA4B-00A0C93EC93B
  173. n
  174. 2
  175.  
  176.  
  177. w
  178. EOF
  179.  
  180.     echo "efi and ext4 partitions created successfully."
  181.     echo "The new partitions will now be formatted"
  182.     echo "This might take a few minutes, please be patient."
  183.     mkfs.fat -F32 -n EFI "$efipartition"
  184.     yes | mkfs.ext4 -L "$label" "$mainpartition"
  185.     sync
  186.  
  187. }
  188. #******************end doformat*********************
  189.  
  190. #*******************doclone************************
  191. doclone () {
  192. echo "making the clone"
  193.     label="target"
  194.     mount /boot/efi
  195.     mkdir -p /media/$user/EFI
  196.     mount "$efipartition" /media/$user/EFI
  197.     mkdir -p /media/$user/$label
  198.     mount "$mainpartition" /media/$user/$label
  199.  
  200.     sourceuuid=$(findmnt / -o UUID -n)
  201.     targetuuid=$(findmnt /media/$user/"$label" -o UUID -n)
  202.  
  203.     sourceefiuuid=$(grep /boot/efi /etc/fstab | awk '{print $1}' | grep UUID | sed -E 's/UUID=(.*)/\1/' )
  204.     targetefiuuid=$(findmnt /media/$user/EFI/ -o UUID -n)
  205.  
  206.     rsync -rv --delete /boot/efi/ /media/$user/EFI/
  207.    
  208. #trying to make it more distro independent... not well tested
  209.     find /media/$user/EFI/ -name "grub.cfg" -exec sed -i "s/$sourceuuid/$targetuuid/" "{}" \;
  210. #old way proven to work on my Mint Mate installation but wouldn't work if grub.cfg is inside a differently named folder
  211. #    sed -i "s/$sourceuuid/$targetuuid/" /media/$user/EFI/EFI/ubuntu/grub.cfg
  212.      
  213.     rsync -axAXHv --exclude='/dev/*' --exclude='/proc/*' --exclude='/sys/*' --exclude='/tmp/*' --exclude='/run/*' --exclude='/mnt/*' --exclude='/media/*' --exclude='/lost+found/' --delete  / /media/$user/"$label"/
  214.  
  215.     sed -i "s/$sourceuuid/$targetuuid/" /media/$user/$label/etc/fstab
  216.     sed -i "s/$sourceuuid/$targetuuid/" /media/$user/$label/boot/grub/grub.cfg
  217.     sed -i "s/$sourceefiuuid/$targetefiuuid/" /media/$user/$label/etc/fstab
  218.  
  219.     echo "Writing changes to target, do not remove!"
  220.  
  221.     sync
  222. }
  223.  
  224. #*******************doclone************************
  225.  
  226. #*******************fixgrub************************
  227. fixgrub () {
  228.  
  229. for i in /sys /run /dev /proc; do mount --bind "$i" "/media/$user/target$i"; done
  230.  
  231. chroot /media/$user/target/ /bin/bash -- << EOT
  232.     update-grub
  233. EOT
  234.  
  235. for i in /proc /dev /run /sys; do umount "/media/$user/target$i"; done
  236.  
  237. umount /media/$user/EFI
  238. umount /media/$user/target
  239.  
  240. rmdir /media/$user/target
  241. rmdir /media/$user/EFI
  242.  
  243. echo "It is now okay to remove the target drive."
  244. }
  245.  
  246. #*****************end fixgrub**********************
  247.  
  248. main
Advertisement
Add Comment
Please, Sign In to add comment