脚本 - 在更新系统之前,如何自动创建Btrfs快照?

分享于 

10分钟阅读

ubuntu

  繁體

问题:

我已经在Btrfs根分区上安装了Ubuntu 20.04。

为了尽可能简单,我想将Btrfs快照的创建集成到upgrade -alias命令中,它目前如下所示:

sudo apt update && sudo apt upgrade -y && sudo flatpak update -y && sudo snap refresh

如何最好在更新之前添加快照,以便在发生错误时回滚?

还有可能同时删除较旧的快照吗?


答案1:

btrfs中制作快照非常简单。

首先挂载包含partitition的btrfs文件系统例如,/mnt,我们假设是/dev/sda1


sudo mount /dev/sda1 /mnt


cd /mnt



同样,如果您以前创建了快照,它们也将显示在其中。

要创建//home的快照,请运行以下命令:


sudo btrfs sub snap @ @-BACKUP && sudo btrfs sub snap @home @home-BACKUP



如果要在创建新备份之前删除现有备份,命令为:


sudo btrfs sub del @-BACKUP && sudo btrfs sub del @home-BACKUP



就是如此简单。

完成从/mnt卸载分区后:

 
sudo umount /mnt



此外,我还可以添加可以使用时间戳创建快照或进行增量备份,但是这有点超出了问题的范围。

可以将这些命令组合成一个文本文件,比如backup.sh

例如:


#!/bin/sh


mount /dev/sda1 /mnt


cd /mnt


[ -d @-BACKUP ] && sudo btrfs sub del @-BACKUP #Checks is backup exists and deletes it


[ -d @home-BACKUP ] && sudo btrfs sub del @home-BACKUP


btrfs sub snap @ @-BACKUP


btrfs sub snap @home @home-BACKUP


cd /


umount /mnt



脚本应该与sudo一起运行。


答案2:

我会使用由Ignacio Nunez Hernanz编写的脚本


#!/bin/bash



#


# Script that creates BTRFS snapshots, manually or from cron


#


# Usage:


# sudo btrfs-snp <dir> (<tag>) (<limit>) (<seconds>) (<destdir>)


#


# Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>


# GPL licensed (see end of file) * Use at your own risk!


#


# Based on btrfs-snap by Birger Monsen


#


# More at https://ownyourbits.com


#



function btrfs-snp()


{


 local BIN="${0##*/}"


 local DIR="${1}"


 local TAG="${2:-snapshot}"


 local LIMIT="${3:-0}"


 local TIME="${4:-0}"


 local DST="${5:-.snapshots}"



 ## usage


 [["$*" =="" ]] || [["$1" =="-h" ]] || [["$1" =="--help" ]] && {


echo"Usage: $BIN <dir> (<tag>) (<limit>) (<seconds>) (<destdir>)



 dir │ create snapshot of <dir>


 tag │ name the snapshot <tag>_<timestamp>


 limit │ keep <limit> snapshots with this tag. 0 to disable


 seconds │ don't create snapshots before <seconds> have passed from last with this tag. 0 to disable


 destdir │ store snapshot in <destdir>, relative to <dir>



Cron example: Hourly snapshot for one day, daily for one week, weekly for one month, and monthly for one year.



cat > /etc/cron.hourly/$BIN <<EOF


#!/bin/bash


/usr/local/sbin/$BIN /home hourly 24 3600


/usr/local/sbin/$BIN /home daily 7 86400


/usr/local/sbin/$BIN /home weekly 4 604800


/usr/local/sbin/$BIN / weekly 4 604800


/usr/local/sbin/$BIN /home monthly 12 2592000


EOF


chmod +x /etc/cron.hourly/$BIN"


return 0


 }



 ## checks


 local SNAPSHOT=${TAG}_$( date +%F_%H%M%S )



 [[ ${EUID} -ne 0 ]] && { echo"Must be run as root. Try 'sudo $BIN'" ; return 1; }


 [[ -d"$SNAPSHOT" ]] && { echo"$SNAPSHOT already exists" ; return 1; }



 mount -t btrfs | cut -d' ' -f3 | grep -q"^${DIR}$" || {


btrfs subvolume show"$DIR" | grep -q"${DIR}$" || {


 echo"$DIR is not a BTRFS mountpoint or snapshot"


 return 1


}


 }



 DST="$DIR/$DST"


 mkdir -p"$DST"


 local SNAPS=( $( btrfs subvolume list -s --sort=gen"$DST" | awk '{ print $14 }' | grep"${TAG}_" ) )



 ## check time of the last snapshot for this tag


 [["$TIME" != 0 ]] && [["${#SNAPS[@]}" != 0 ]] && {


local LATEST=$( sed -r"s|.*_(.*_.*)|1|;s|_([0-9]{2})([0-9]{2})([0-9]{2})| 1:2:3|" <<<"${SNAPS[-1]}" )


LATEST=$( date +%s -d"$LATEST" ) || return 1



[[ $(( LATEST + TIME )) -gt $( date +%s ) ]] && { echo"No new snapshot needed for $TAG"; return 0; }


 }



 ## do it


 btrfs subvolume snapshot -r"$DIR""$DST/$SNAPSHOT" || return 1



 ## prune older backups


 [["$LIMIT" != 0 ]] && 


 [[ ${#SNAPS[@]} -ge $LIMIT ]] && 


echo"Pruning old snapshots..." && 


for (( i=0; i <= $(( ${#SNAPS[@]} - LIMIT )); i++ )); do


 btrfs subvolume delete"$DIR/${SNAPS[$i]}"


done



 echo"snapshot $SNAPSHOT generated"


}



btrfs-snp"$@"



# License


#


# This script is free software; you can redistribute it and/or modify it


# under the terms of the GNU General Public License as published by


# the Free Software Foundation; either version 2 of the License, or


# (at your option) any later version.


#


# This script is distributed in the hope that it will be useful,


# but WITHOUT ANY WARRANTY; without even the implied warranty of


# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the


# GNU General Public License for more details.


#


# You should have received a copy of the GNU General Public License


# along with this script; if not, write to the


# Free Software Foundation, Inc., 59 Temple Place, Suite 330,


# Boston, MA 02111-1307 USA



相关使用信息:


# btrfs-snp


Usage: btrfs-snp <dir> (<tag>) (<limit>) (<seconds>) (<destdir>)



dir │ create snapshot of <dir>


tag │ name the snapshot <tag>_<timestamp>


limit │ keep <limit> snapshots with this tag. 0 to disable


seconds │ don't create snapshots before <seconds> have passed from last with this tag. 0 to disable


destdir │ store snapshot in <destdir>, relative to <dir>



你的升级别名需要如下所示:

btrfs-snp / syschanges 3 600 && ...

然后,你可以按照btrfs最佳实践使用和恢复这些快照。


答案3
  • btrfs sub snapshot -r /mnt/btrfsroot/@/ /mnt/btrfsroot/snapshots/root-$(date +%y%m%d)
  • /mnt/btrfsroot/snapshots/@*-apthook-YYMMDDHH 那么您会例如在每月的第12天运行一次cronjob 34 03 12 * * btrfs sub delete /mnt/btrfsroot/snapshots/@*-apthook-$(date --date='15 days ago' +%y%m)*

答案4

你可以用这个shell script轻松做到这一点。

使用以下内容创建一个shell script:


# Directory for saving snapshots


SNAPDIR=/snapshots


export SNAPDIR



# Delete snapshots


sudo btrfs subvolume delete /mnt/btrfs/backup_*



# Ask user for the name of snapshot


echo -n"What will be the name of snapshot?"


read SNAPNAME



# Create the snapshot


sudo btrfs subvolume snapshot /mnt/btrfs/ $SNAPDIR/backup_$SNAPNAME



# Check if the snapshot created successfully, if not then exit


if [ $? -ne 0 ]


then


echo"Failed to create snapshot"


exit 1


fi



# Commands to execute after creating snapshot


sudo apt update && sudo apt upgrade -y && sudo flatpak update -y && sudo snap refresh



创建文件后,将/snapshots替换为保存快照的快照目录,然后把它放在地方。

现在,通过执行:


chmod +x /path/to/shell/script.sh



现在更改升级别名的命令,使它指向脚本。


AUTO  SYS  系统  scripts  SNA  snap