Skip to content

Instantly share code, notes, and snippets.

@ClarenceYk
Last active August 26, 2020 08:09
Show Gist options
  • Save ClarenceYk/d79d486097350a48ff653ccd028064c8 to your computer and use it in GitHub Desktop.
Save ClarenceYk/d79d486097350a48ff653ccd028064c8 to your computer and use it in GitHub Desktop.
An example for using rsync to clone a linux system.
#!/bin/bash
### Colors
RED='\e[31m'
RED_B='\e[1;37;41m'
GREEN='\e[32m'
GREEN_B='\e[1;37;42m'
YELLOW_B='\e[1;43m'
NC='\e[0m'
### Tools
blkid=/sbin/blkid
sfdisk=/sbin/sfdisk
### Function for Triming Characters
trim_spaces() {
echo -n $1 | sed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//"
}
trim_tailing_slashes() {
echo -n $1 | sed -e "s/[\/]*$//"
}
### Functions for result checking
check() {
if [ $1 -eq 0 ]; then
echo -e "${GREEN}Success${NC}"
else
echo -e "${RED}Failed${NC}"; exit 1
fi
}
check_without_exit() {
if [ $1 -eq 0 ]; then
echo -e "${GREEN}Success${NC}"
else
echo -e "${RED}Failed${NC}"
fi
}
check_empty() {
if [ -z $2 ]; then
echo -e "${RED_B}Error:${NC} $1 must not be empty"; exit 1
fi
}
check_ip() {
local ip=$1
local stat=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
if [ $stat -ne 0 ]; then
echo -e "${RED_B}Error:${NC} $ip is not a volid ip address"; exit 1
fi
}
### Get partition's UUID
get_blkid() {
$blkid $1 | cut -f 2 -d " " | cut -f 2 -d "=" | sed -e 's/^"*//' -e 's/"*$//'
}
### Get block device from user
read -p 'Disk you want to use: ' Disk
Disk=$( trim_spaces $Disk )
check_empty 'block device' $Disk
if [ ! -b $Disk ]; then
echo -e "${RED_B}Error:${NC} $Disk is not a block device."; exit 1
fi
echo -en "Use ${GREEN_B}${Disk}${NC} as the target device!"
read -p ' Continue? (Y/n): ' Confirm
if [ "$Confirm" != 'Y' ]; then
echo "Canceled by user!"; exit 0
fi
### Partition the disk
echo -e "${YELLOW_B} ${NC}"
echo -e "${YELLOW_B} -> Partition <- ${NC}"
echo -e "${YELLOW_B} ${NC}"
echo -n 'Destroy old partition table... '
dd if=/dev/zero of=$Disk bs=1024 count=1 &> /dev/null
check $?
echo -n 'Create new partition table... '
$sfdisk --force $Disk &> /dev/null << EOF
1M,4G,S,
,,L,*
EOF
check $?
echo -en "Format new partition ${GREEN_B}${Disk}1${NC} to swap... "
mkswap ${Disk}1 &> /dev/null
check $?
echo -en "Format new partition ${GREEN_B}${Disk}2${NC} to ext4... "
mkfs.ext4 ${Disk}2 &> /dev/null
check $?
### Sync system files from source
echo -e "${YELLOW_B} ${NC}"
echo -e "${YELLOW_B} -> Synchronization <- ${NC}"
echo -e "${YELLOW_B} ${NC}"
read -p 'Source host IP: ' rsync_ip
rsync_ip=$( trim_spaces $rsync_ip )
check_ip $rsync_ip
read -p "Which section to use in source host(default 'all'): " rsync_section
rsync_section=$( trim_spaces $rsync_section )
if [ -z $rsync_section ]; then
rsync_section='all'
fi
read -p "Which dir to sync in source host(default '/mnt/debian_10'): " rsync_dir
rsync_dir=$( trim_spaces $rsync_dir )
if [ -z $rsync_dir ]; then
rsync_dir='/mnt/debian_10/'
else
if [ $rsync_dir != "/" ]; then
rsync_dir=$( trim_tailing_slashes $rsync_dir )
rsync_dir=${rsync_dir}/
fi
fi
echo -n 'Check connectivity... '
ping -c 1 $rsync_ip &> /dev/null
check $?
rsync_mount='/mnt/rsync_tmp'
echo -n "Mount ${Disk}2 to ${rsync_mount}... "
mkdir -p $rsync_mount &> /dev/null
mount ${Disk}2 $rsync_mount &> /dev/null
check $?
echo -n "Sync from ${rsync_ip}:${rsync_section}:${rsync_dir} ... "
rsync -avHX ${rsync_ip}::${rsync_section}${rsync_dir} ${rsync_mount}/ \
--exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/mnt/*,/media/*,/lost+found} \
&> /dev/null
check $?
### Create /etc/fstab
echo -e "${YELLOW_B} ${NC}"
echo -e "${YELLOW_B} -> Rebuild GRUB <- ${NC}"
echo -e "${YELLOW_B} ${NC}"
echo -n 'Generate /etc/fstab... '
cat << EOF > /tmp/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=$( get_blkid ${Disk}2 ) / ext4 errors=remount-ro 0 1
UUID=$( get_blkid ${Disk}1 ) none swap sw 0 0
EOF
check $?
cp -v /tmp/fstab ${rsync_mount}/etc/fstab
### Create shell script for updating grub
echo -n 'Generate update_grub.sh... '
cat << EOF > /tmp/update_grub.sh
#!/bin/bash
grub-install ${Disk}
update-grub
EOF
chmod +x /tmp/update_grub.sh
check $?
cp -v /tmp/update_grub.sh ${rsync_mount}/tmp/update_grub.sh
### Reinstall GRUB
echo -n 'Reinstall GRUB... '
mount --bind /proc ${rsync_mount}/proc
mount --bind /sys ${rsync_mount}/sys
mount --bind /dev ${rsync_mount}/dev
mount --bind /run ${rsync_mount}/run
chroot ${rsync_mount} /tmp/update_grub.sh &> /dev/null
check $?
echo -e "${GREEN_B} ${NC}"
echo -e "${GREEN_B} -> Install Success! <- ${NC}"
echo -e "${GREEN_B} ${NC}"
### Script end
read -p ' Reboot Now? (Y/n): ' reboot
if [ "$reboot" = 'Y' ]; then
reboot
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment