Raspberry Piを使用してそれ自体のバックアップを作成できますか?


78

この質問は、外部コンピューターを使用してRPiのバックアップを作成する方法の質問に答えます。

現在使用中のSDカードのバックアップイメージを作成して、USBストレージデバイス上のファイルにコピーできるかどうか疑問に思っています。これは可能ですか?そうでない場合、別のコンピューターを使用せずにRPiのバックアップを作成する方法はありますか?


2
もちろん、/ tmp、/ run、/ proc、/ sys、/ dev、および/ mntはスキップします。イメージを作成する必要はありません。イメージを作成または更新できるバックアップが必要です。使用しないddでくださいrsync
goldilocks

1
@goldilocksこのコメントをより完全な回答に具体化して、念頭に置いてバックアップと復元のプロセスを説明していただければ幸いです。
エリックウィルソン

完了-申し訳ありませんが、時間を見つけるのに数日かかりました。
goldilocks

1
宛先ボリュームが十分に大きい場合、ファイルシステムを読み取り専用で再マウントddし、適切なブロックサイズでコピーを実行すると、「新しい」コピーの場合におそらく最速になります。フラッシュ/ SDメディアへのファイルごとのコピーを行うことは、おそらく悪い考えです。
クリスストラットン

回答:


86

以下rsyncは、Piのバックアップに使用するためのイントロです。最初のバックアップが作成されたら、この方法で最新の状態に保つことは、画像全体を絶えずリッピングするよりもはるかに高速です。これは、ローカルハードドライブまたはネットワーク経由で実行できます。

実際には、実行中のシステムの完全なコピーをバックアップとして望んでいません。これは、表面上はファイルシステムにあるものの一部が実行時にのみ存在するためです。それをバックアップに含め、それを使用して後でイメージを再作成すると、問題が発生する可能性があります。

他にもいくつかの例外があります。除外するrsyncglob)パターンのリストを受け入れることができ、それらをファイルから読み取ることができるので、最初にそのようなファイルにあるべきものを見てみましょう。エントリはの形式で/directory/*あり、ではないことに注意してください/directory。これは、それらが存在することを望んでいるが、それらの中に何もコピーしたくないためです。

/proc/*
/sys/*

これらは実際にはディスク上には存在しません。それらはカーネルへのインターフェースであり、メモリ内で作成および管理します。これらをコピーしてからシステムにコピーして再起動すると、カーネルはそれらをインターフェイスのマウントポイントとして使用するため、(せいぜい)意味がありませんデータが入っているディレクトリで試してください。動作し、害はありませんが、ディレクトリにあったものにはアクセスできなくなります。]

/sysおよび/procマウントポイントが存在することが重要であることに注意してください。 ただし、何も含めるべきではありません。次:

/dev/*

devディレクトリは全く同じものではありませんprocし、sys私たちの目的のためにそれがあります。バックアップなどで同じデバイスノードを使用できるように、これを保存する必要があると思われる場合は、間違いです。気にしないでください。コピーしないでくださいdev。昔々、Linuxはそのように機能していましたが、もう機能しません。

/boot/*

これは、Raspbianなど、Pi固有のディストリビューションのほとんど(おそらくすべて)での特殊なケースです。実際には、最初のvfatパーティションのマウントポイントです。これについては別に扱います。何をするにしても、ここに含めないでください。これもまたマウントポイントだからです。

/tmp/*
/run/*

/run通常、ディスク上でもメモリ上でもありません。おそらくそうかも/tmpしれません(これによりSDカードの動作が少し節約されます)が、いずれにしても、名前が示すように、これらは永続的なデータを保存する場所ではありません。これらを使用するアプリケーションは、起動するたびに削除される可能性があります。

/mnt/*
/media/*

これらは特に、ハードドライブまたはUSBスティックにバックアップする予定で、デバイスが/mntまたは/media(自動マウントでは後者を使用する傾向がある)場合に重要になります。ファイルシステム内のデバイスの場所を除外しない場合ドライブの容量がなくなるまで、ドライブの内容をそれ自体にバックアップするループを作成します。私は愚かな何かを見つけるのに十分賢いrsync かもしれないが、前提をテストすることを避けようとするだろと思う。

実際のバックアップについて:ローカルにマウントされたハードドライブ、USBのものなどにバックアップするディレクトリを作成します。たとえば、「pi_backup」。別の方法としてssh(以下を参照)またはネットワークマウントされたファイルシステムを使用してリモートの場所にバックアップすることもできますが、これにはおそらくしばらく時間がかかります。

除外するリストを含むファイルが/rsync-exclude.txt1で、ドライブがの/mnt/usbhd場合、実際のバックアップを実行するには:

rsync -aHv --delete --exclude-from=/rsync-exclude.txt / /mnt/usbhd/pi_backup/

に末尾のスラッシュがあることに注意してくださいpi_backup/

これにはしばらく時間がかかり、大量の出力が生成されます(代わりにログで調べたい場合は、appendを追加します> rsync.log)。 --delete最初は無意味ですが、バックアップを最新の状態に保つために使用します。これにより、後でPiで削除したものもバックアップから確実に削除されます。aディレクトリにセット再帰と、すべてのファイルが一致した属性を確認します。 ハードリンク-Hを保存することです2v冗長性のためですrsync。それが出力を得る理由です(そうでなければ静かです)。詳細man rsyncをご覧ください。

--exclude-fromファイルをスキップできるショートカットがあります。コピーしたくないもの(/tmpなど)がすべて別のファイルシステムにあることが確実な場合は、次のように使用できます。

rsync -axHv --delete-during / /mnt/usbhd/pi_backup/

-x挿入されました。これはの短い形式で--one-file-systemrsyncファイルシステムの境界を越えないようにします。個人的にはを好み--exclude-fromますが、たとえばデフォルトのRaspbianでは--one-file-systemうまく動作します。-x気をつけたい場合は両方を使用できます:D

これは完全なバックアップではありません。何も入れておらずboot、バックアップを使用してカードをコンピューターに貼り付けて実行するだけでシステムを復元することができれば十分です:

rsync -av --delete-during /mnt/usbhd/pi_backup/ /mnt/sdcard_partition2/

画像を作成する必要がある場合、それは少し効率的ではありませんが、新しい画像を含むカードでこれを行うこともできます(基本画像と同じと仮定します)(その後、ほとんどの画像を上書きするため)。そのようなイメージのあるUSBアダプターを介して別のSDカードを接続し、上記の方法を使用して重複したカードを維持することもできます。

/bootを含むもの(たとえば、カスタムカーネル)を入れた場合は/boot/config.txt、それもバックアップする必要があります(非常に簡単です-それほど多くはありません)。別々に行うだけで、復元すると、その内容が最初のパーティションに格納されます。

バックアップ可能なブランクの Raspbianスタイルのイメージを作成する場合は、こちらをご覧ください。同様の方法論を使用して、空のRaspbianスタイルカードを作成でき.imgます。ファイルを処理するのではなく、実際のデバイス(例:)を処理します/dev/sdb。つまり、パーティションテーブルを作成してfdiskから、でフォーマット/dev/sdb1およびsdb2(または何でも)mkfs

しかし、画像全体をコピーする方が簡単です!なぜこれで悩むのですか?

それほど難しくありません。10分で空のカード(最後のリンクに従ってフォーマットされた)に復元しました。はい、ddすべてを単純に使用する方が簡単です(わかりにくい単語などが見つかった場合)が、バックアップを更新するたびに100%を実行する必要があるため、かなり時間がかかります。を使用するrsyncと、バックアップが存在する場合、バックアップの更新がはるかに高速になるため、cronを使用して毎日痛みを伴わないように設定できます。ネットワーク経由でも。6時間ごと。頻繁に行うほど、時間がかかりません。

rsync 経由で ssh

以下に例を示します。

rsync [options] --rsh="ssh [ssh options]" root@[the pi ip]:/ /backup/rpi/

「オプション」は、たとえば、-av --delete --exclude-from=/rsync-exclude.txt「sshオプション」は通常使用するもの(あれば)です。sshシステムバックアップの目的でこれを行うには、rootアクセスが必要です(サーバーに設定PermitRootLogin=yes/etc/ssh/sshd_configて再起動します)。


1このファイルを保持する必要があります。#またはで始まる行にコメントを挿入でき;ます。これには実際のrsyncコマンドが含まれる場合があります。このコマンドは後でコピーして貼り付けることができるため、毎回覚えておく必要はありません。

2指摘してくれたクリスのおかげで、rsyncこれは自動的には行われません。


ゴルディロックス。これはrysyncの素晴らしい使い方のようです。それをスクリプトに組み込む可能性はありますか?
全体主義者

すべてのマウントポイントを手動で除外する代わりに、なぜそれmkdir /tmp/backupable && mount --bind / /tmp/backupableをrsyncしますか?また、そこにマウントされた何かによって「シャドウ」されている場所に保存されているデータをバックアップするという利点もあります。
n.st 14

@ n.stいいね(笑)!提案を質問に編集しました--exclude-fromが、使用する方が良いと思います。時間がある場合は、これを別の回答として書き留めてください。私の投票があり、それを参照できます。この答えは十分に長いものです。
goldilocks

1
@IgorGanapolsky意図は、イメージを作成しないことです(「イメージ全体をコピーする方が簡単です!なぜこれを気にするのですか?」の部分を読んでください)。このメソッドは、作成後のメンテナンスが簡単かつ高速であることに加えて、一般に柔軟性が高くなります。後でそれを使用して作成する.img場合は、できます。これこれは、それらがどのように構成され、作成できるかを説明するのに役立つはずです。
goldilocks

1
完全なバックアップではありません...」で始まる段落を参照してください。基本的に逆の場合もまったく同じです。これは、人々が一般的に混乱している概念について理解するのに役立ちます
goldilocks

24

Raspberry Communityのメンバーが作成した作業スクリプト。

好きなようにコードを再利用して微調整することができます。

#!/bin/bash

# Setting up directories
SUBDIR=raspberrypi_backups
DIR=/hdd/$SUBDIR

echo "Starting RaspberryPI backup process!"

# First check if pv package is installed, if not, install it first
PACKAGESTATUS=`dpkg -s pv | grep Status`;

if [[ $PACKAGESTATUS == S* ]]
   then
      echo "Package 'pv' is installed."
   else
      echo "Package 'pv' is NOT installed."
      echo "Installing package 'pv'. Please wait..."
      apt-get -y install pv
fi

# Check if backup directory exists
if [ ! -d "$DIR" ];
   then
      echo "Backup directory $DIR doesn't exist, creating it now!"
      mkdir $DIR
fi

# Create a filename with datestamp for our current backup (without .img suffix)
OFILE="$DIR/backup_$(date +%Y%m%d_%H%M%S)"

# Create final filename, with suffix
OFILEFINAL=$OFILE.img

# First sync disks
sync; sync

# Shut down some services before starting backup process
echo "Stopping some services before backup."
service apache2 stop
service mysql stop
service cron stop

# Begin the backup process, should take about 1 hour from 8Gb SD card to HDD
echo "Backing up SD card to USB HDD."
echo "This will take some time depending on your SD card size and read performance. Please wait..."
SDSIZE=`blockdev --getsize64 /dev/mmcblk0`;
pv -tpreb /dev/mmcblk0 -s $SDSIZE | dd of=$OFILE bs=1M conv=sync,noerror iflag=fullblock

# Wait for DD to finish and catch result
RESULT=$?

# Start services again that where shutdown before backup process
echo "Start the stopped services again."
service apache2 start
service mysql start
service cron start

# If command has completed successfully, delete previous backups and exit
if [ $RESULT = 0 ];
   then
      echo "Successful backup, previous backup files will be deleted."
      rm -f $DIR/backup_*.tar.gz
      mv $OFILE $OFILEFINAL
      echo "Backup is being tarred. Please wait..."
      tar zcf $OFILEFINAL.tar.gz $OFILEFINAL
      rm -rf $OFILEFINAL
      echo "RaspberryPI backup process completed! FILE: $OFILEFINAL.tar.gz"
      exit 0
# Else remove attempted backup file
   else
      echo "Backup failed! Previous backup files untouched."
      echo "Please check there is sufficient space on the HDD."
      rm -f $OFILE
      echo "RaspberryPI backup process failed!"
      exit 1
fi

元のフォーラムにコメントを追加するか、コンテンツを完成させるために独自のバージョンを投稿することを検討してください。少し取って少し与えてください。

* AndersW(GITスクリプトのクリック)を返してくれてありがとう


2
piのバックアップ中にファイルシステム(ファイルの削除、新しいファイルの追加)が変更された場合はどうなりますか?
ケイキ

2
rsyncで実行中に複数のディスクをバックアップし、これらのファイルバックアップから必要なものを正確に取得できることが頻繁にありました。ただし、一般的に、ファイルシステムがマウントされている間(*)、Unixファイルシステムを完全にコピーすることはできません(すべてのビットが適切に配置され、正しい状態で)。システムのマウント中に作成されたコピーは、「ダーティコピー」と呼ばれることもあります。ダーティコピーの品質を向上させるためにいくつかの手段を講じることができます(上記のスクリプトが行うように、cronとmysqlを停止します)が、完璧ではありません。乾杯!*-私はこれについて間違っています、それはファイルシステムに依存します。
タイViinikka

1
Debianが推奨するバックアップユーティリティを見て、Piにそれらの移植版があるかどうかを確認できます。rsnapshotプロモーションの音
ピョートルクラ

1
@TaiViinikka完璧なコピーは必要ありません。元のベースイメージに(すばやく簡単に)再配置できる部分コピーが必要です。 rsync行く方法です。明日時間があれば、答えを追加します。 rsnapshot調査する価値もあります。
goldilocks

3
上記のppumkinsの回答に基づいて、「dd」スクリプトを元のスレッドの最新のコメントと同期し、いくつかのマイナーな改善を自分で追加しました。最終結果は、< github.com/aweijnitz/pi_backup >から入手できます。改善を追加し、プルリクエストを私に送信することをheしないでください。
-AndersW

14

piのバックアップ用にrsyncで@goldilocksの回答を採用しました。ext4PiにマウントされたHDDのパーティションにバックアップします。HDDがマウントされていない場合、rsyncはマウントディレクトリにコピーします(SDカードがいっぱいになるまで)。HDDがrwモードでマウントされていない場合、大量のエラーメッセージが生成されます。どちらも望ましくないため、rw続行する前にパーティションがモードでマウントされていることを確認します。

注2015-03-03ハードリンクを正確にコピーするように回答を変更しました。オリジナルは機能しましたが、多くのハードリンクをファイルに変換しました。スペースを浪費することに加えて、これはハードリンクが適所にあると仮定する多くの用途を妥協します。(私の現在の画像には869個のリンクがあり、その多くはRaspbian自体にあります。)

これを行うスクリプトは次のとおりです。(私のパーティションは PiData、にマウントされています/mnt/PiData

#!/bin/bash
# script to synchronise Pi files to backup
BACKUP_MOUNTED=$(mount | awk '/PiData/ {print $6}' | grep "rw")
if [ $BACKUP_MOUNTED ]; then
    echo $BACKUP_MOUNTED
    echo "Commencing Backup"
    rsync -avH --delete-during --delete-excluded --exclude-from=/usr/bin/rsync-exclude.txt / /mnt/PiData/PiBackup/
else
    echo "Backup drive not available or not writable"
fi

次を使用して復元(または別のPiを更新):

sudo rsync -avH /mnt/PiData/PiBackup/ /

rsync-exclude.txt不要なファイルを削除するように拡張しました。

最初のグループは、@ goldilocks https://raspberrypi.stackexchange.com/users/5538/によって文書化されたディレクトリです

2番目のグループは、AFP(Apple Filing Protocol)を使用してPiにアクセスするときにOS Xによって作成されるファイルとディレクトリです。(これらは通常OS Xでは見えませんが、Raspbianでは見えません。いずれにしても、バックアップする必要はありません。)AFPを使用したことがない場合でも、これらは害を及ぼしません。

3番目のグループは、バックアップする必要のない(そして別のPiにコピーされない)ファイルです。例fake-hwclock.data、RPi-Monitorレポート。他の人もいるでしょう。

/proc/*
/sys/*
/dev/*
/boot/*
/tmp/*
/run/*
/mnt/*

.Trashes
._.Trashes
.fseventsd
.Spotlight-V100
.DS_Store
.AppleDesktop
.AppleDB
Network Trash Folder
Temporary Items

.bash_history
/etc/fake-hwclock.data
/var/lib/rpimonitor/stat/

1
その出力を.imgファイルにする方法はありますか?
イゴールガナポルスキー

@IgorGanapolskyさて、すべての重要なファイル(ブートファイルを除く)があるので、それは明らかに可能ですが、画像が必要な場合は画像を作成します。コメントではなく、新しい投稿で新しい質問をする必要があります。
ミリウェイズ

@Milliwaysなぜ「sudo rsync ...」を使用しないのですか?同期できないファイルがいくつかありますか?
スミリア

6

ローカルネットで3つのPiを実行しており、それらが実行されているときに、cronを使用して定期的にバックアップする必要があります。そのため、dd、tar、およびrsyncのバックアップを作成して復元できるスクリプトを作成しました。バックアップにrsyncを使用することを好みますが、他の人はddまたはtarを好みます。すでに多くの人が使用しています。他の人にも役立つことを願っています:-) raspibackup-Raspberryは自身のバックアップを作成します


1
いいえ、申し訳ありません。HTTP経由でダウンロードしたスクリプトを(rootとして)ユーザーに実行するように依頼することは無責任です。このスクリプトを安全なチャンネルで配布してください。
クレメント

1
私はそれが話題から外れているとは思わないし、ルートかどうかはさほど重要ではない。要点は、ソフトウェアは安全なチャネルで配布されるべきであり、あなたの答えは悪いセキュリティ慣行を奨励することです。
クレメント

1
これは大きな前進、イエス:)だろう
クレマン

2
HTTPS経由の配信は、この場合にセキュリティを追加するものではありません。インターネットからスクリプトをダウンロードして実行しています。安全なプロセスは、スクリプトをダウンロードし(http / httpsは無関係です)、エディターでスクリプトを開き、上から下に読み、奇妙な点と不安定な点をチェックします。満足した場合にのみ実行してください。Frampは、私たちのすべてのいずれかを知っているため、ハッカーかもしれないし、HTTPS経由の配信は、彼だけが、その場合には笑顔になるだろう:)(ところで、それは告発Frampではありません!)
ジュリアン・ナイト

2
仰るとおりです。、手動1. installerScript 2.ダウンロードし、それを、コードをチェックして、手動でインストール:2つの方法がスクリプトをインストールする方法が記載されている理由です
framp

3

このような目的のための安定したツールは次のとおりです。https//github.com/aktos-io/aktos-dcs-tools

このツールはに書き込まれmake ssh、接続make backup-rootmake mount-root最初は心の中で離れた場所から、その後、地元のセッションが追加されます。そのため、ローカルバックアップ、直接リモートバックアップ、プロキシリモートバックアップをサポートしています。バックアップは増分で行われ(差分のみが転送されます)、バックアップディレクトリはスタンドアロンです(復元するディレクトリ/バージョンを選択するだけで、どのディレクトリにも完全バックアップがあります)。もちろん、バージョンがあります(backup.last-0が最新です)。バックアッププロセスをいつでも中断して、後で続行できます。

特定の問題の手順は次のとおりです。

 ssh to-your-raspberry
 cd /mnt/usb0/my-rpi-backups
 git clone https://github.com/ceremcem/aktos-dcs-tools backup-tools
 ln -s backup-tools/Makefile .

 ./backup-tools/configure # you do not need to make any settings for local sessions, just save the default 

 # just for the first time
 make set-local-session  # a flag file is created
 make init               # snapshots directory is created

 # anytime you want to back up
 make backup-root        # backup with rsync

編集

新しいターゲットが追加されました。1つのコマンドでバックアップから物理SDカードを作成できます。

make create-disk-from-last-backup

指示に従って、SDカードを作成し、この新しく作成されたSDカードでRaspberryPiを起動します。


1

これは完全に異なるアプローチです。あなたは使うことができLVML ogical Vの olumeのMの一貫性バックアップを作成するanagerを)。ストレージを簡単に追加、拡張、削減したり、スナップショットからオペレーティングシステムを以前の状態に復元したりするなど、その他の改善点に加えて、バックアップを作成することもできます。バックアップ中に動的に変更されるファイル、ファイルシステムを読み取り専用に設定すること、特定のディレクトリなどを除外することについて心配する必要はありません。ではLVMあなたは、単にスナップショットを作成し、ご希望の方法でこのスナップショットやバックアップ、それをマウントします。でコピーを作成しcp -aたり、ミラーをrsync作成しtarたり、アーカイブを作成したり、イメージを作成したりできます。dd。バックアップデバイスをマウントしたと仮定すると/mnt/usbhd/pi_backup/、たとえば次のことができます。

rpi ~$ sudo lvcreate --snapshot --name rpi_snap --size 1G rpi_vg/root_lv
rpi ~$ sudo mkdir /mnt/snapshot
rpi ~$ sudo mount /dev/mapper/rpi_vg-rpi_snap /mnt/snapshot

# make backups
rpi ~$ sudo cp -a /mnt/snapshot/ /mnt/usbhd/pi_backup/
rpi ~$ sudo rsync -aH --delete /mnt/snapshot/ /mnt/usbhd/pi_backup/
rpi ~$ sudo tar -czf /mnt/usbhd/pi_backup/backup.tar.gz -V "Backup of my Raspberry Pi" -C /mnt/snapshot/ ./
rpi ~$ sudo dd if=/mnt/snapshot/ of=/mnt/usbhd/pi_backup/backup.img bs=4M

rpi ~$ sudo umount /mnt/snapshot/
rpi ~$ sudo lvremove rpi_vg/rpi_snap

LVMをセットアップするのに少しの労力しかかかりません。その方法は、LVMで実行中のシステムの簡単なバックアップとスナップショットを見ることができます。


0

インストール可能なイメージを作成するバックアップツールを見つけました。

また、イメージをマウントおよび縮小するユーティリティもあります。

これは他の人に役立つかもしれません

それに付属するドキュメントは非常に短いので、次のことに注意してください:

  1. ユーティリティを任意のディレクトリに抽出し、スクリプトを実行可能にします。
  2. マウントしext4、あなたの中にパイにフォーマットされたパーティションを/mnt/media(大きなファイルを可能にし、パイなどのexFATまたはネットワークドライブでサポートされている任意の形式を使用することができます)。
  3. 最初の実行では、バックアップイメージ名の入力を求められます。例 /mnt/Image/BusterBackup.img
  4. Image ROOTファイルシステムのサイズ(MB単位)の入力を求められます。これは、可能な限り最小の場合は0、完全バックアップの場合は空白にすることができます。
  5. 後続の実行で、バックアップイメージのパスを入力して、増分更新します。
An example of the commands I used:-
# Mount USB
sudo mount /dev/sda1 /mnt/Image/
# Update backup
sudo image-utils/image-backup /mnt/Image/BusterBackup.img
# Mount backup
sudo image-utils/image-mount /mnt/Image/BusterBackup.img  MountedImages
When done, run:
sudo umount MountedImages; sudo losetup -d /dev/loop0
# Compress backup
sudo sh -c "gzip -9c /mnt/Image/BusterBackup.img  > Images/BusterBackup.img.gz"

パーティションのオフセットとサイズを正しく計算し、コメントをいくつか追加するために、オリジナルを少し(マウントポイントをコピーするために)変更しました。

#!/bin/bash
# Original https://raspberrypi.org/forums/viewtopic.php?p=1528736
# 2019-09-26    Modified to set size of boot sector

trap '{ stty sane; echo ""; errexit "Aborted"; }' SIGINT SIGTERM

ADDBLK=0

# Set BOOT_SIZE_MB to the Desired boot sector size (in MB) - should be multiple of 4MB
BOOT_SIZE_MB=256
BOOTSIZEM=$BOOT_SIZE_MB'M'

BOOTBEG=8192
BOOT_SIZE="$((BOOT_SIZE_MB * 1024 * 1024))"
ROUND_SIZE="$((4 * 1024 * 1024))"
# Ensure root sector starts on an Erase Block Boundary (4MB)
ROOTBEG=$(((BOOT_SIZE + ROUND_SIZE -1) / ROUND_SIZE * ROUND_SIZE / 512 + BOOTBEG))

MNTPATH="/tmp/img-backup-mnt"

ONEMB=$((1024 * 1024))

# create BOOT loop device
mkloop1()
{
  local INFO1=""
  local SIZE1=0
  local START1=0

  sync
  INFO1="$(sfdisk -d "${IMGFILE}")"
  START1=$(grep type=c <<< "${INFO1}" | sed -n 's|^.*start=\s\+\([0-9]\+\).*$|\1|p')
  SIZE1=$(grep type=c <<< "${INFO1}" | sed -n 's|^.*size=\s\+\([0-9]\+\).*$|\1|p')
  LOOP1="$(losetup -f --show -o $((${START1} * 512)) --sizelimit $((${SIZE1} * 512)) "${IMGFILE}")"
  if [ $? -ne 0 ]; then
    errexit "Unable to create BOOT loop device"
  fi
}

rmloop1()
{
  if [ "${LOOP1}" != "" ]; then
    sync
    losetup -d "${LOOP1}"
    LOOP1=""
 fi
}

# create ROOT loop device
mkloop2()
{
  local INFO2=""
  local SIZE2=0
  local START2=0

  sync
  INFO2="$(sfdisk -d "${IMGFILE}")"
  START2=$(grep type=83 <<< "${INFO2}" | sed -n 's|^.*start=\s\+\([0-9]\+\).*$|\1|p')
  SIZE2=$(grep type=83 <<< "${INFO2}" | sed -n 's|^.*size=\s\+\([0-9]\+\).*$|\1|p')
  LOOP2="$(losetup -f --show -o $((${START2} * 512)) --sizelimit $((${SIZE2} * 512)) "${IMGFILE}")"
  if [ $? -ne 0 ]; then
    errexit "Unable to create ROOT loop device"
  fi
}

rmloop2()
{
  if [ "${LOOP2}" != "" ]; then
    sync
    losetup -d "${LOOP2}"
    LOOP2=""
  fi
}

# Mount Image partitions
mntimg()
{
  MNTED=TRUE
  if [ ! -d "${MNTPATH}/" ]; then
    mkdir "${MNTPATH}/"
    if [ $? -ne 0 ]; then
      errexit "Unable to make ROOT partition mount point"
    fi
  fi
  mkloop2
  mount "${LOOP2}" "${MNTPATH}/"
  if [ $? -ne 0 ]; then
    errexit "Unable to mount image ROOT partition"
  fi
  if [ ! -d "${MNTPATH}/boot/" ]; then
    mkdir -p "${MNTPATH}/boot/"
    if [ $? -ne 0 ]; then
      errexit "Unable to make BOOT partition mount point"
    fi
  fi
  mkloop1
  mount "${LOOP1}" "${MNTPATH}/boot/"
  if [ $? -ne 0 ]; then
    errexit "Unable to mount image BOOT partition"
  fi
}

umntimg()
{
  umount "${MNTPATH}/boot/"
  if [ $? -ne 0 ]; then
    errexit "Unable to unmount image BOOT partition"
  fi
  rmloop1
  umount "${MNTPATH}/"
  if [ $? -ne 0 ]; then
    errexit "Unable to unmount image ROOT partition"
  fi
  rmloop2
  rm -r "${MNTPATH}/"
  MNTED=FALSE
}

errexit()
{
  echo ""
  echo "$1"
  echo ""
  if [ "${MNTED}" = "TRUE" ]; then
    umount "${MNTPATH}/boot/" &> /dev/null
    umount "${MNTPATH}/" &> /dev/null
    rm -rf "${MNTPATH}/" &> /dev/null
  fi
  rmloop1
  rmloop2
  exit 1
}

LOOP1=""
LOOP2=""
MNTED=FALSE

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

if [ $(id -u) -ne 0 ]; then
  errexit "$0 must be run as root user"
fi

PGMNAME="$(basename $0)"
for PID in $(pidof -x -o %PPID "${PGMNAME}"); do
  if [ ${PID} -ne $$ ]; then
    errexit "${PGMNAME} is already running"
  fi
done

rsync --version &> /dev/null
if [ $? -ne 0 ]; then
  errexit "rsync not installed (run: apt-get install rsync)"
fi

if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
  SYSTEMD=1
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
  SYSTEMD=0
else
  errexit "Unrecognized init system"
fi

if [ ${SYSTEMD} -eq 1 ]; then
  ROOT_PART="$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p')"
else
  if [ ! -h /dev/root ]; then
    errexit "/dev/root does not exist or is not a symlink"
  fi
  ROOT_PART="$(readlink /dev/root)"
fi

ROOT_TYPE=$(blkid "/dev/${ROOT_PART}" | sed -n 's|^.*TYPE="\(\S\+\)".*|\1|p')

ROOT_DEV="${ROOT_PART:0:(${#ROOT_PART} - 1)}"
if [ "${ROOT_DEV}" = "mmcblk0p" ]; then
  ROOT_DEV="${ROOT_DEV:0:(${#ROOT_DEV} - 1)}"
fi

PTUUID="$(blkid "/dev/${ROOT_DEV}" | sed -n 's|^.*PTUUID="\(\S\+\)".*|\1|p')"

DEVSIZE=$(blockdev --getsize64 "/dev/${ROOT_PART}")
BLKSIZE=$(blockdev --getbsz "/dev/${ROOT_PART}")
BLKCNT=$((${DEVSIZE} / ${BLKSIZE}))
INFO="$(df | grep /dev/root)"
DFKSIZE=$(awk '{print $2}' <<< "${INFO}")
DFKFREE=$(awk '{print $4}' <<< "${INFO}")
ROOTSIZE=$((${BLKCNT} * ${BLKSIZE}))
ROOTUSED=$(((${DFKSIZE} - ${DFKFREE}) * 1024))
IRFSMIN=$(((${ROOTUSED} + (${ADDBLK} * ${BLKSIZE}) + (${ONEMB} - 1)) / ${ONEMB}))
IRFSMAX=$(((${ROOTSIZE} + (${ONEMB} - 1)) / ${ONEMB}))

IMGFILE="$1"
if [ "${IMGFILE}" = "" ]; then
# Create Image file
  while :
  do
    echo ""
    read -r -e -i "${IMGFILE}" -p "Image file to create? " IMGFILE
    if [ "${IMGFILE}" = "" ]; then
      continue
    elif [[ ! "${IMGFILE}" =~ ^/mnt/.*$ && ! "${IMGFILE}" =~ ^/media/.*$ ]]; then
      echo ""
      echo "${IMGFILE} does not begin with /mnt/ or /media/"
      continue
    fi
    if [ -d "${IMGFILE}" ]; then
      echo ""
      echo "${IMGFILE} is a directory"
    elif [ -f "${IMGFILE}" ]; then
      echo ""
      echo -n "${IMGFILE} already exists, Ok to delete (y/n)? "
      while read -r -n 1 -s answer; do
        if [[ "${answer}" = [yYnN] ]]; then
          echo "${answer}"
          if [[ "${answer}" = [yY] ]]; then
            break 2
          else
            break 1
          fi
        fi
      done
    else
      break
    fi
  done
  IRFSSIZE=""
  while :
  do
    echo ""
    read -r -e -i "${IRFSSIZE}" -p "Image ROOT filesystem size (MB) [${IRFSMAX}]? " IRFSSIZE
    if [ "${IRFSSIZE}" = "" ]; then
      IRFSSIZE=${IRFSMAX}
      break
    elif [ ${IRFSSIZE} -ge ${IRFSMIN} ]; then
      break
    else
      echo ""
      echo "Requested image ROOT filesystem size (${IRFSSIZE}) is too small (Minimum = ${IRFSMIN})"
      IRFSSIZE=${IRFSMIN}
    fi
  done
  echo ""
  echo -n "Create ${IMGFILE} [${IRFSSIZE} MB] (y/n)? "
  while read -r -n 1 -s answer; do
    if [[ "${answer}" = [yYnN] ]]; then
      echo "${answer}"
      if [[ "${answer}" = [yY] ]]; then
        break
      else
        errexit "Aborted"
      fi
    fi
  done
  if [ -f "${IMGFILE}" ]; then
    rm "${IMGFILE}"
    if [ $? -ne 0 ]; then
      errexit "Unable to delete existing image file"
    fi
  fi
  ROOTEND=$((${ROOTBEG} + ((${IRFSSIZE} * ${ONEMB}) / 512) - 1))
  truncate -s $(((${ROOTEND} + 1) * 512)) "${IMGFILE}"
  if [ $? -ne 0 ]; then
    errexit "Unable to create image file"
  fi
# create image/partitions
  sync
  fdisk "${IMGFILE}" <<EOF > /dev/null
p
n
p
1
${BOOTBEG}
+${BOOTSIZEM}
t
c
p
n
p
2
${ROOTBEG}
${ROOTEND}
p
w
EOF

  mkloop1
  mkloop2
  mkfs.vfat "${LOOP1}" > /dev/null
  if [ $? -ne 0 ]; then
    errexit "Unable to create image BOOT filesystem"
  fi
  dosfsck "${LOOP1}" > /dev/null
  if [ $? -ne 0 ]; then
    errexit "Image BOOT filesystem appears corrupted"
  fi
  if [ "${ROOT_TYPE}" = "f2fs" ]; then
    mkfs.f2fs "${LOOP2}" > /dev/null
  else
    mkfs.ext4 -q -b ${BLKSIZE} "${LOOP2}" > /dev/null
  fi
  if [ $? -ne 0 ]; then
    errexit "Unable to create image ROOT filesystem"
  fi
  rmloop2
  rmloop1
# Initialise image PARTUUID
  fdisk "${IMGFILE}" <<EOF > /dev/null
p
x
i
0x${PTUUID}
r
p
w
EOF
# Create empty directories in image root partition
  mntimg
  mkdir "${MNTPATH}/dev/" "${MNTPATH}/media/" "${MNTPATH}/mnt/" "${MNTPATH}/proc/" "${MNTPATH}/run/" "${MNTPATH}/sys/" "${MNTPATH}/tmp/"
  if [ $? -ne 0 ]; then
    errexit "Unable to create image directories"
  fi
  chmod a+rwxt "${MNTPATH}/tmp/"
  umntimg
  echo ""
  echo "Starting full backup (for incremental backups, run: $0 ${IMGFILE})"
# END of create image/partitions
else

# Check existing Image
  if [[ ! "${IMGFILE}" =~ ^/mnt/.*$ && ! "${IMGFILE}" =~ ^/media/.*$ ]]; then
    errexit "${IMGFILE} does not begin with /mnt/ or /media/"
  fi
  if [ -d "${IMGFILE}" ]; then
    errexit "${IMGFILE} is a directory"
  elif [ ! -f "${IMGFILE}" ]; then
    errexit "${IMGFILE} not found"
  fi
  echo "Starting incremental backup to ${IMGFILE}"
fi

# rsync root partition
mntimg
sync
rsync -aDH --partial --numeric-ids --delete --force --exclude "${MNTPATH}" --exclude '/dev' --exclude '/media' --exclude '/mnt/*/*' --exclude '/proc' --exclude '/run' --exclude '/sys' \
--exclude '/tmp' --exclude 'lost\+found' --exclude '/etc/udev/rules.d/70-persistent-net.rules' --exclude '/var/lib/asterisk/astdb.sqlite3-journal' / "${MNTPATH}/"
if [[ $? -ne 0 && $? -ne 24 ]]; then
  errexit "Unable to create backup"
fi
sync
umntimg

-1

ターミナルを開き、「lsblk -f」と入力します。
これにより、接続されているすべてのストレージデバイスが表示されます。
次に、「dd if = / dev / [SDカードの名前] bs = 1M」と入力します。
これにはしばらく時間がかかるため、バックグラウンドで実行することをお勧めします。
これは、Linuxでsdカードをバックアップするのとまったく同じ方法です。


これにより、不要なファイルや不要なファイルもすべてバックアップされます。
イゴールガナポルスキー

3
実行中のシステムではバックアップ中に状況が変化するため、これにより一貫性のないバックアップが作成されます。
インゴ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.