web-dev-qa-db-ja.com

システムを更新する前に、Btrfsスナップショットを自動的に作成するにはどうすればよいですか?

スナップショット機能のために、BtrfsルートパーティションにUbuntu 20.04をインストールしました。

できるだけシンプルに保つために、Btrfsスナップショットの作成をupgrade- aliasコマンドに統合したいと思います。これは現在、次のようになっています。

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

何か問題が発生した場合にロールバックできるように、更新前にスナップショットを追加するにはどうすればよいですか?

古いスナップショットを同時に削除する可能性もありますか? (私のルートパーティションは10%未満しか満たされていないため、システム全体を複数回コピーできますが、毎週の更新ですぐにいっぱいになると思いますか?)

5
Prototype700

私にはいくつかのアイデアがあります。選び、選び、組み合わせる。

  1. apt-btrfs-snapshot または etckeeper のような専用の既製のソフトウェアで、これを舞台裏で自動的に行います。これはおそらく、今後の最良の方法です。
  2. 上記のパッケージのカスタムバージョンを複製するには aptにフック 更新ごとにスクリプトを実行します。上記のパッケージはもちろん、これがどのように行われるかについてのベストプラクティスの学習に役立ち、洗練されたスクリプトの例が another answer に示されています。しかし、それはbtrfs sub snapshot -r /mnt/btrfsroot/@/ /mnt/btrfsroot/snapshots/root-$(date +%y%m%d)のような単純なものでもかまいません。
  3. どちらの場合でも、apt/dpkgにはそのようなフックがありますが、 snapにはありません があり、他についてはわかりません。しかし、質問に従って最初にaptを実行するので、それは本当に問題にはなりません。
  4. 多数のスナップショットが作成されるため、不要なスナップショットを手動または自動で削除する方法も必要になります。自動スナップショットのパスが_/mnt/btrfsroot/snapshots/@*-apthook-YYMMDDHH_であると想定してこれがどのように行われるかを理解するには、たとえば、毎月12日ごとに34 03 12 * * btrfs sub delete /mnt/btrfsroot/snapshots/@*-apthook-$(date --date='15 days ago' +\%y\%m)*としてcronjobを実行します。詳細については、_man 5 crontab_および_man date_のマニュアルページを確認してください。

これであなたが正しい方向に進むことを願っています。繰り返しますが、私は単に_apt-btrfs-snapshot_を使用してそれを実行することをお勧めします。現在、_apt-btrfs-snapshot_ assumes は、ルートパーティションの名前が_@_であることを認識してください。これは、Ubuntuおよび他の多くのディストリビューションのデフォルトです。

不明な点がある場合は、フォローアップの質問を自由に質問してください。

PS:_/_(実行中のシステムのルート)とbtrfs-rootの違いを理解していますか?

1
MAV

私は 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 && ...は、/.snapshotsにタグsyschangesを含むスナップショットを生成しますが、過去5分間にすでにスナップショットがある場合は生成しません、これらの最大3つを保持します。

これにより、たとえばアップグレードだけでなく、1つのインストール手順で異なるリポジトリまたはPPAからインストールしたい場合などに、雑然とせずに繰り返し操作を実行するための5分のウィンドウが提供されます。

その後、btrfsのベストプラクティスに従って、これらのスナップショットを使用および復元できます。

1
emk2203

これは、このシェルスクリプトで簡単に実行できます。

次の内容のシェルスクリプトを作成します。

# 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

スクリプトをポイントするように、アップグレードエイリアスのコマンドを変更します。

エイリアスを実行すると、最初にbackup_プレフィックスが付いたスナップショットが削除され、次にbackup_で始まる名前で保存されたファイルシステムのスナップショットが取得されます。

初めて実行すると、エラーが表示される場合があります。ただし、最初の実行時には無視してください。バックアップがないため、削除するものはありません。また、バックアップスナップショットが保存されるディレクトリで、backup_で始まる名前のサブボリュームまたはスナップショットを作成しないでください。スクリプトを実行すると、そのファイルが削除されます。また、スナップショットには、他のスナップショット、サブボリューム、マウントされたパーティションのファイルは含まれません。

0
Akib Azmain