海运的博客

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

发布时间:February 8, 2020 // 分类: // No Comments

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

#!/bin/bash
#set -x
network=static
dns=8.8.8.8
ssh_key="ssh_key=https://www.haiyun.me/id_rsa.pub"
mirror="http://mirrors.aliyun.com/alpine/v3.11"
ipxe_file="https://www.haiyun.me/ipxe.lkrn"

valid_ip() {
  [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
  state=$?
  return $state 
}
cidr2mask() {
    value=$(( 0xffffffff ^ ((1 << (32 - $1)) - 1) ))
    echo "$(( ($value >> 24) & 0xff )).$(( ($value >> 16) & 0xff )).$(( ($value >> 8) & 0xff )).$(( $value & 0xff ))"
}
which wget &> /dev/null && which ip &> /dev/null || {
  echo '请先安装wget和ip'
  exit
}
alpine_addr="ip=dhcp"
if [ "$network" == 'static' ]; then
  address=$(ip -o -f inet addr show | awk '/scope global/ {print $4}' | head -n 1)
  addr=$(echo $address | awk -F'/' '{print $1}')
  cidr=$(echo $address | awk -F'/' '{print $2}')
  gw=$(ip rou | awk '/default via/ {print $3}')
  mask=$(cidr2mask $cidr)
  alpine_addr="ip=${addr}::${gw}:${mask}::::${dns}:"
  echo 'ip:' $addr
  echo 'route:' $gw
  echo 'netmask:' $mask
  valid_ip "$addr" && valid_ip "$mask" && valid_ip "$gw" || {
    echo '获取网络信息失败'
    exit
  }
  read -r -p "以上IP信息是否正确? [Y/n] " input
  if [[ $input != "y" && $input != "Y" ]]; then
    echo "abort"
    exit
  fi
fi

if [ -f "/etc/redhat-release" ]; then
  grubfile=/boot/grub2/grub.cfg
  grubcmd=grub2-mkconfig
else
  grubfile=/boot/grub/grub.cfg
  grubcmd=grub-mkconfig
fi
#root=`grep "set root" $grubfile|sed -e 's/^[ \t]*//'|head -n 1`
root=$(grep 'set root' $grubfile | sed -e 's/^[ \t]*//' | sort | uniq -c | head -n 1 | awk '{print $2,$3}')
if mount | grep -q /boot; then
  dir=/
else
  dir=/boot/
fi
vmlinuzfile=${dir}ipxe.lkrn
initrdfile=${dir}ipxe.initrd
wget -q $ipxe_file -O /boot/ipxe.lkrn
cat > /boot/ipxe.initrd << EOF
#!ipxe
imgfree
set net0/ip ${addr}
set net0/netmask ${mask}
set net0/gateway ${gw}
set dns ${dns}
ifopen net0

:boot
kernel ${mirror}/releases/x86_64/netboot/vmlinuz-virt ${alpine_addr} modules=loop,squashfs quiet nomodeset alpine_repo=${mirror}/main/ modloop=${mirror}/releases/x86_64/netboot/modloop-virt console=tty0 ${ssh_key} || goto boot
initrd ${mirror}/releases/x86_64/netboot/initramfs-virt || goto boot

boot || shell
EOF

[[ -f /boot/ipxe.lkrn ]] && [[ -f /boot/ipxe.initrd ]] || {
  echo '引导文件不存在'
  exit
}

cat > /etc/grub.d/40_custom << EOF
#!/bin/sh
exec tail -n +3 \$0
menuentry 'netinstall' {
$root
linux16 $vmlinuzfile
initrd16 $initrdfile
}
EOF
sed -i 's/GRUB_DEFAULT=.*/GRUB_DEFAULT="netinstall"/' /etc/default/grub
$grubcmd -o $grubfile
cat /etc/grub.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 /mnt/boot/grub/grub.cfg
sed -i 's/default="netinstall"/default="0"/' /mnt/boot/grub/grub.cfg
chmod 444 /mnt/boot/grub/grub.cfg
sed -i 's/GRUB_DEFAULT="netinstall"/GRUB_DEFAULT="0"/' /mnt/etc/default/grub
umount /mnt/

将要dd的目标系统通过以上方法引导至alpine系统并挂载sshfs,然后将之前备份的img dd到目标系统:

gzip -dc /mnt/pr.img |dd of=/dev/vda

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

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

挂载恢复后硬盘镜像,修改目标系统的IP地址和启动项:

mount -t ext4 /dev/vda1 /mnt/
#如果有更改swap分区,修改fstab uuid
blkid
vim /mnt/etc/fstab 
vim /mnt/etc/network/interfaces
chmod 644 /mnt/boot/grub/grub.cfg
sed -i 's/default="netinstall"/default="0"/' /mnt/boot/grub/grub.cfg
chmod 444 /mnt/boot/grub/grub.cfg
sed -i 's/GRUB_DEFAULT="netinstall"/GRUB_DEFAULT="0"/' /mnt/etc/default/grub
umount /mnt/

标签:none

评论已关闭

分类
最新文章
最近回复
  • 海运: 恩山有很多。
  • swsend: 大佬可以分享一下固件吗,谢谢。
  • Jimmy: 方法一 nghtp3步骤需要改成如下才能编译成功: git clone https://git...
  • 海运: 地址格式和udpxy一样,udpxy和msd_lite能用这个就能用。
  • 1: 怎么用 编译后的程序在家里路由器内任意一台设备上运行就可以吗?比如笔记本电脑 m参数是笔记本的...
  • 孤狼: ups_status_set: seems that UPS [BK650M2-CH] is ...
  • 孤狼: 擦。。。。apcupsd会失联 nut在冲到到100的时候会ONBATT进入关机状态,我想想办...
  • 海运: 网络,找到相应的url编辑重发请求,firefox有此功能,其它未知。
  • knetxp: 用浏览器F12网络拦截或监听后编辑重发请求,修改url中的set为set_super,将POS...
  • Albert: 啊啊啊啊啊啊啊啊啊 我太激动了,终于好了英文区搜索了半天,翻遍了 pve 论坛没找到好方法,博...