chuggerguy

mirrortodevice

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