PVE 备份快照

PVE 备份快照 - 知乎

抄一个备份

vmware压缩整个虚拟机文件夹就可以连带快照一起打包。

PVE 自带的vzdump备份并不包含快照信息,备份之后再还原,会丢失快照信息。

备份时提示:snapshots found (not included into backup)

快照信息在循序渐进的开发模式中十分重要,遇到错误直接回退即可。

本文提供一套连带快照打包思路。PVE虚拟机的完全打包,需要关注两个目录:

1.虚拟机配置存放目录: /etc/pve/qemu-server/

2.虚拟机磁盘存放目录:/var/lib/vz/images(默认)或其他设备对应目录。

本文存放磁盘设备为(/mnt/SSD-1T/images),磁盘设备使用qcow2格式。

例如,完全备份id为101的虚拟机,只需要备份 /etc/pve/qemu-server/101.conf 和 /mnt/SSD-1T/images/101 即可。

101.conf里保存了该虚拟机的硬件配置、快照信息以及磁盘目录。

/mnt/SSD-1T/images/101 下存放了被该虚拟机指向的磁盘。

磁盘文件为稀疏文件模式,例如120G的磁盘初始占用只有44G。

为保证磁盘打包前后都保持稀疏模式,打包方法建议使用 tar命令 加-S参数。

注意,其他打包方式可能导致稀疏属性丢失,解包后占用空间为磁盘最大值。

打包命令参考:

tar -czSvf /mnt/HDD-4T/101.tar /mnt/SSD-1T/images/101

传统tar单线程打包压缩速度过慢,建议使用pigz并行压缩打包,结合pv管道统计进度:

需额外安装:apt install pigz pv -y

tar -cSf - /mnt/SSD-1T/images/101 | pv -s $(du -s /mnt/SSD-1T/images/101 | awk '{print $1}' | xargs -I {} echo "scale=0; {} * 1024" | bc) | pigz > /mnt/HDD-4T/101.tar.gz

 

使用示例#

支持交互模式,按提示输入

./backup.sh
./resume.sh

也支持单条调用模式,备份示例,参数: 需备份id , 备份文件名 , 无需确认 :

./backup.sh 101 ubt22_test yes

还原示例, 参数:备份文件路径,还原id , 无需确认 :

./resume.sh /mnt/HDD-4T/hand_back/ubt22_test.tar.gz 120 yes

备份示例:

示例还原:

 

 

复制代码
#备份
#!/usr/bin/zsh
#配置目录
conf_dir='/etc/pve/qemu-server'

#磁盘目录,改为自己机器实际目录
disk_dir='/mnt/SSD-1T/images'
#备份存储目录,改为自己机器实际目录
back_dir='/mnt/HDD-4T/hand_back'

vmid=$1
back_name=$2
confirm=$3

if [ -z "$vmid" ] || [ -z "$back_name" ]; then
   echo '已有虚拟机id和name映射如下:'
   grep 'name:' -r $conf_dir
   echo "\n"

   echo "请输入需备份vmid,如(101):"
   read vmid
   echo "你输入的vmid是:$vmid,配置如下:"
   cat $conf_dir/$vmid.conf
   echo "\n"
   echo "该虚拟机磁盘占用信息:"
   ls -lh $disk_dir/$vmid

   echo "存储备份文件夹为:$back_dir"
   echo "存储文件夹已有文件列表如下:"
   ls -lh $back_dir/*.tar.gz
   echo "\n"

   echo "请输入存储备份文件名(不包含.tar.gz后缀),如(ubt22_init):"
   read back_name
fi


echo "目标存储文件为$back_dir/$back_name.tar.gz"
if [ -e "$back_dir/$back_name.tar.gz" ]; then
   echo "目标文件已存在,需再次手动确认是否覆盖:"
   ls -lh $back_dir/$back_name.tar.gz
   confirm=""
fi

if [ "$confirm" != "yes" ]; then
   while true; do
       echo "确认开始备份 $disk_dir/$vmid -> $back_dir/$back_name.tar.gz 吗?"
       echo "输入yes或no" 
       read confirm
       case "$confirm" in
           "yes")
               echo "你输入了yes,准备开始备份..."
               break
               ;;
           "no")
               echo "你输入了no,脚本即将结束。"
               exit 0
               ;;
           *)
               echo "输入不合法,请输入yes或no。"
               continue
               ;;
       esac
   done
fi

#记录开始时间
start_time=$(date +"%Y-%m-%d %H:%M:%S")
echo "$start_time,开始备份操作:"

#备份配置文件
cp $conf_dir/$vmid.conf $disk_dir/$vmid/
echo "复制配置完成:cp $conf_dir/$vmid.conf $disk_dir/$vmid/,开始打包:"

#打包,-S 保留稀疏结构
echo "切换到:cd $disk_dir,开始备份打包:"
cd $disk_dir
tar -cSf - $vmid | pv -s $(du -s $vmid | awk '{print $1}' | xargs -I {} echo "scale=0; {} * 1024" | bc) | pigz > $back_dir/$back_name.tar.gz
echo "备份打包完成:ls -lh $back_dir/$back_name.tar.gz"
ls -lh $back_dir/$back_name.tar.gz


#summary
end_time=$(date +"%Y-%m-%d %H:%M:%S")
start=$(date +%s --date="$start_time")
end=$(date +%s --date="$end_time")
diff_in_seconds=$((end - start))

# 进行单位换算
hours=$((diff_in_seconds / 3600))
remaining_seconds=$((diff_in_seconds % 3600))
minutes=$((remaining_seconds / 60))
remaining_seconds=$((remaining_seconds % 60))

# 输出操作耗费时间和当前时间
echo "耗时:$hours 小时 $minutes 分 $remaining_seconds 秒"
echo "$end_time,备份结束"
复制代码
复制代码
#还原
#!/usr/bin/zsh

#配置目录
conf_dir='/etc/pve/qemu-server'

#磁盘目录,改为自己机器实际目录
disk_dir='/mnt/SSD-1T/images'
#备份存储目录,改为自己机器实际目录
back_dir='/mnt/HDD-4T/hand_back'

back_name=$1
vmid=$2
confirm=$3

if [ -z "$vmid" ] || [ -z "$back_name" ]; then
   echo '已有虚拟机id和name映射如下:'
   grep 'name:' -r $conf_dir
   echo "\n"

   echo '已有虚拟机磁盘如下:'
   ls "$disk_dir/"
   echo "\n"

   echo "存储备份文件夹为:$back_dir"
   echo "存储文件夹已有备份列表如下:"
   ls -lh $back_dir/*.tar.gz
   echo "\n"

   echo "请输入需还原文件(完整路径):"
   read back_name

   if [ ! -e "$back_name" ]; then
       echo "输入备份:$back_name 不存在,请检查后再试"
       exit 0
   fi

   echo "请输入还原vmid,如(101):"
   read vmid
   if [ -e "$conf_dir/$vmid.conf" ] || [ -e "$disk_dir/$vmid" ]; then
       echo "目标vmid已存在,请检查后再试"
       du -hd1 "$conf_dir/$vmid.conf"
       du -hd1 "$disk_dir/$vmid/"
       exit 0
   fi
fi


if [ "$confirm" != "yes" ]; then
   while true; do
       echo "确认开始还原 $back_name -> $disk_dir/$vmid ->  吗?"
       echo "输入yes或no" 
       read confirm
       case "$confirm" in
           "yes")
               echo "你输入了yes,准备开始还原..."
               break
               ;;
           "no")
               echo "你输入了no,脚本即将结束。"
               exit 0
               ;;
           *)
               echo "输入不合法,请输入yes或no。"
               continue
               ;;
       esac
   done
fi

#记录开始时间
start_time=$(date +"%Y-%m-%d %H:%M:%S")
echo "$start_time,开始还原操作:"

#设置临时文件夹,
tmp_dir=$disk_dir/resume_tmp

if [ ! -d "$tmp_dir" ]; then
    mkdir "$tmp_dir"
fi


#解压缩至临时文件夹
pv $back_name | tar -xzf - -C $tmp_dir

#解压后唯一文件夹名即为id;
old_id=`ls $tmp_dir|tail -n1`

echo "conf 替换id:$old_id -> $vmid"

#本处只做简单的vmid匹配替换。默认备份与还原的存储容器一致,如非一致,请手动修改vmid.conf 中磁盘路径的配置。

#只替换目录名,保留原磁盘文件名,
cp $tmp_dir/$old_id/$old_id.conf $tmp_dir/$old_id/$old_id.conf.tmp
sed "s/vm-$old_id/vm-$vmid/g; s/:$old_id\//:$vmid\//g" $tmp_dir/$old_id/$old_id.conf.tmp > $tmp_dir/$old_id/$old_id.conf

#清除临时文件
rm $tmp_dir/$old_id/$old_id.conf.tmp

echo "重命令磁盘vmid:$old_id -> $vmid"
#重命名磁盘文件
for file in $tmp_dir/$old_id/*$old_id*.qcow2; do
    new_file=$(echo "$file" | sed "s/-$old_id-/-$vmid-/g")
    mv "$file" "$new_file"
done


echo "替换完毕,移动至正式目录:mv $tmp_dir/$old_id $disk_dir/$vmid"
mv $tmp_dir/$old_id $disk_dir/$vmid
mv $disk_dir/$vmid/$old_id.conf $disk_dir/$vmid/$vmid.conf
cp $disk_dir/$vmid/$vmid.conf $conf_dir/$vmid.conf

ls -lh $disk_dir/$vmid
ls -lh $conf_dir/$vmid.conf


#summary
end_time=$(date +"%Y-%m-%d %H:%M:%S")
start=$(date +%s --date="$start_time")
end=$(date +%s --date="$end_time")
diff_in_seconds=$((end - start))

# 进行单位换算
hours=$((diff_in_seconds / 3600))
remaining_seconds=$((diff_in_seconds % 3600))
minutes=$((remaining_seconds / 60))
remaining_seconds=$((remaining_seconds % 60))

# 输出操作耗费时间和当前时间
echo "耗时:$hours 小时 $minutes 分 $remaining_seconds 秒"
echo "$end_time,还原结束"
复制代码

 

作者:上官飞鸿

出处:https://www.cnblogs.com/jackadam/p/18649998

版权:本作品采用「知识共享-署名-非商业性-禁止演绎(CC-BY-NC-ND)」许可协议进行许可。

posted @   上官飞鸿  阅读(188)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2018-01-03 NETGEAR WNDR3800CH openwrt 不能用新版, Barrier Breaker 14.07
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示