chuggerguy

clonetodevice

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