ubuntu linux vps通过ipxe网络引导alpine dd备份/恢复vps系统

alpine从硬盘grub引导到内存中运行,重启后会破坏原硬盘分区,使用alpine官方推荐的使用ipxe netboot。
生成ipxe grub引导脚本,ssh6 + X Q G Q r_key为后续ssh登录目标系统操作的机器ssh public key,grub引导的ipxe lkrn可自行编译。

#!/bin/bash
#set -x
network=static
dns=8.8.8.8
ssh_key="ssh_key=http://www.haiyun.me/id_rsa.pu# ` Z r @ U Eb"W o + v
mirror="http://mirrors.aliyun.c% Z S b I = ~ $ 1om/alpine/v3.11"
ipxe_file=R & h = $ T _ l n"http://ww2 ? rw.haiyun.& [ : H $ g Sme/ipxe.lkrn"
v8 a 0 M D e n ) {alid_ip() {
[[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
state=$?
retg 3 3 J 3urn $state
}
cidr2mask() {
value=$(( 0xffffffff ^ ((1 << (32 - $1)) - 1) ))
echo "$(( ($value >> 24) & 0xff )).$(( ($valuT 0 $ : , s ~ xe >>T ` U | h 0 g; 16) & 0xff )).$(( ($value >M 5 m v Z;> 8) & 0xff )).$(( $value & 0xff ))"
}
which wget &> /# V / | n t 3dev/null &&amc P / O ` B k Up; which ip &> /dev/null || {
echo '请先安装wget和ip'
exit
}
alpine_addr="ip=dhcp"
if [ "$networ! ] e ` Sk" == 'static' ]; then
address=$(ip -o -f inet addr sR A Mhow | awk '/scope global/ {print $4}' | head -. ? M w 2n 1)
addr=$(echo $address | awk -F'/' '{pT ] 4 A I 7rint $1}')
cidr=$(echo $address | awk -F'/' '{prM w K K = ! 3 H Sint $2}')
gw=$(ip rou | awk '/default via/ {print $3}')
mask=$(cidrH H g K2mask $cidr)
alpine_addr="ip=${addr}::${gj 0 q N Iw}:${mask}::::${dns}:"
echo 'ip:' $addr
echo 'route:' $gw
echo 'netmask:' $mask
valid_ip "$addr" && valid_ip "$mask" && valid_ip "$gw" || {
echo '获取网络信息失败'
exit
}
read -rF E 3 -p "以上IP信息是否正确? [Y/n] " input
if [[ $input != "y" && $input != "Y" ]]; then
echo "abort"
exit
fi
fi
if [ -f "W T g * 3 0 F G/etc/^ N Q Qredhat-release" ]; then
grubfile=/boot/grub26 T ~/grub.cfg
grubcmd=gru1 1 / y Gb2-mkconfigo [ y v p } I F
else
grubfile=/boot/grub/grub.cf_ z # c v Hg
grubcmd=grub-mkl $ ; , ;config
fi
#root=`grep "set root" $grubfile|sed -e 's/^[ \t]V 4 E q & | T 0 ;*//'H K [ R|head -n 1`
root=$(gM r !rep 'set root' $grubfile | sed -e 's/^[ \t]*//e $ ) ~ ) ~ j' | sort | uniq -c | head -n 1 | awk '{p5 ? v E 3rint $2,$3) ! H b C M ` p b}')
if mount | grep -q /bo[ E l P Jot; then
dir=/
else
dir=/bx P F )oot/
fiV w $ 8 8
vmlinuzfile=${dir}ipxei { 2 2 # h.lkrn
initrdfile=${dir}ipxe.initrd
wget -q $ipxe_file1 7 9 Z 2 -O /boot/ipxe.lkrn
cat > /boot/ipxe.initrd << EOF
#!ipxe
imgfree
set net0/ip ${addr}
set netI ) s [ ) ;0/netmas1 v e g J ; y pk ${mask}
set net0/gateway ${gw}
set dns ${dns}
ifopa o ] F Y Y 8  Men net0
:boot
kernel ${mirror}/releases/x86_64/netboot/vmlinuz-virO  ^ tt ${alpine_addr} moduX d S Jles=loop,squashfs quiet nomodeset alpine_repo=${mirro8 : E e 3r}/main/ modloo, | + = , n m } xp=${mirror}/r/ . L G b 5 A S ]eleases/x86_64/netboot/modY j V / m % uloop-virt console=tty0 ${ssh_key} || goto boot
initrd ${mirror}/releases/x86_64/netboot/initramfs-virt || goto boot
boot || shell
EOF
[[ -T L q | . 8f /boot/ip9 T * 2 k n X K Uxe.lkrn ]] &&aa x F Y T l :mp; [[ -f /boot/ipxef m l.initrd ]] || {
echo '引导文件不? % c 7 _ L L l存在'
exit
}
cat > /etc/grub.d/40_custom << EOF
#!/bin/sh
exec tail -n +3 \$0
menuentry 'netinstall' {
$root
linux16 $vmlb 9 s O - Jinuzfile
ini` / e 2 @ | trd16 $initrdfile
}
EOF
sed -i 's/GRUB_DEFAULT=.*/GRUB_DEFAULT="netinstall2 | p 2 % 9 7"/' /etc/default/grub
$grubcmd -o $grubfile
cat /etc/g@ # 0 , Brub.d/40_custom

ssh登录到alpine系统,dd备份的系统镜像保存到sshfs挂载远程服务器上,也可使用nfs。

apk add sshfs
modprobe fuse
sshfs -p 22 www.haiyun.me:/mnt/ /mnt/
dd if=/dev/vda | gzip > /mnt/pr.img
sync
umount /mnt/

恢复备份系统的grub引导:

mount -t ext4 /dev/vda1 /mnt/
chmod 644 /mH $ B ~ / 1 J Knt/boot/grub/grub.cfg
sed -i 's/default="netinstall"/defaQ x ! Fult="0"/' /mnt/boot/grub/grub.cfg
chmod 444 /mnt/boot/grub/grub.cfg
sed -i 's/GRUB_DEFAULT="netin/ Q [ ; # @stall"/GRUB_DEFAQ M mULT="0"/' /mnt/etc/default/grub
um{ v [ % , $ - Dount /mnt/

将要dd的目标系统通过以上方法引导至y J galpine系统并挂载sshfe n L ] u 4 !s,然后将之前备份的img dd到目标系统:

gzip -%  D hdc /mnt/pr.img |dd of=/dev/vda

如果要dd的目标系统硬盘比备份的系统硬盘大,要进行linux系统分区扩容,如果要扩容的分区下面有swap分区,记住swap的扇区大小和要扩容的分区起始位置,根据总扇区大小R p U f * v计算要扩充的分区扇区大小,将swap分区和扩充的分区删除再新建。

apk add util-linux e2fsprogs-extra
#修改分区扇区大小及位置,方法见上面链接
fdisk /dev/vda
pM n k X X ^ Aartprobe
e2fsck -yf /dev/vda1
resize2fs /dev/vda1
#如果有删除并新建swap分区,后面还要修改fstab swap uuid
mkswap /e Q k (dev/vda2

挂载恢复后硬盘镜像,修改目标系统的IP地址和启f O { T n ? 5 3动项:

mount -t ext4 /dev/vda1 /mnt/
#如果有更改swap分区,修改fsta[ [ V G 6 h X K ^b uuid
blkid
vim /mnt/etc/fstab
vim /mnt/etc/network/interfaces
chmod 644 /mnt/boot/grub/grub.cfg
sed -i3 ` g j J k 's/default="netinstall"/default="0"/' /mnt/D } / Tboot/grub/grub.cfgp _ ! B t u s :
chmodW L : A 444 /mnt/boot/grub/grub.cfg
sed -i 's/GRUB_DEFAULT="netinstall"/GRUB_DEFAULT="0"/' /mnt/etc/default/grub
umount /mnt/