インフラエンジニアの羅針盤

インフラエンジニア1〜3年目のための技術ガイド

rsync・tar・mysqldumpで復旧訓練 講座31

公開

Linuxエンジニア養成講座 第31回|全36回・フェーズ4「サーバー構築と運用」の第4回目(4/9回目)です。
前回: 第30回で MariaDB をインストールし、初期セキュリティ設定からデータベース・ユーザー作成、CRUD 操作、mysqldump によるバックアップまでを実践しました。
今回学ぶこと: rsync・tar・mysqldump を使ったバックアップの取得と、実際にデータを削除して復元するリストア訓練を行います。

前回の予告で「rsync、tar、mysqldump、cron を組み合わせたバックアップ運用と、実際にデータを削除してから復旧するリストア訓練を行います。今回取得した mysqldump のバックアップファイルを使って、復元の手順を体験します」とお伝えしました。今回はその予告どおり、バックアップの取得からリストアの実践までを一気通貫で体験します。

この記事を読み終えると、以下のことができるようになります。

  • バックアップが必要な理由を「消えることを前提にした設計」として説明できる
  • rsync でローカル・リモートへの差分バックアップを実行できる
  • tar で特定時点のアーカイブを作成・展開できる
  • mysqldump でデータベースのバックアップを取得し、復元できる
  • 「バックアップを取った後に実際に復元する」というリストア訓練を一人で実施できる
目次
  1. なぜバックアップが必要か
  2. rsync でファイルをバックアップする
    1. rsync のインストール
    2. ローカルバックアップ
    3. 末尾スラッシュの挙動に注意する
    4. リモートバックアップ(alma-sub へ転送)
    5. –delete オプションの危険性
  3. tar でアーカイブを作成する
    1. アーカイブの作成と確認
  4. mysqldump でデータベースをバックアップ・復元する
    1. テストデータの確認
    2. mysqldump でバックアップを取得する
  5. リストア訓練
    1. ファイルのリストア
    2. データベースのリストア
  6. cron と組み合わせた自動バックアップ
  7. やってみよう
    1. 課題1: ファイルのバックアップとリストア
    2. 課題2: データベースのバックアップとリストア
  8. まとめと次回予告
  9. 理解度チェック

なぜバックアップが必要か

ここで1つ考えてみてください。もしサーバーのデータがすべて消えたら、何が起きるでしょうか。

顧客情報が消える。売上データが消える。サービスの設定ファイルが消える。復旧に何日もかかり、その間サービスは止まったままです。会社によっては事業の継続自体が危うくなります。顧客から預かったデータを守ることは、サービスを提供する側の責任です。バックアップは、その責任を果たすための仕組みです。

データが消える原因は大きく3つあります。

  • 人的ミス: rm -rf / の誤実行、DROP TABLE を本番環境で叩いてしまった、間違ったサーバーで作業した
  • ハードウェア障害: ディスクの物理故障、RAID コントローラの異常、電源障害
  • 外部攻撃: ランサムウェアによるデータ暗号化、不正アクセスによるデータ破壊

ここで重要なのは「消えないようにする」のではなく「消えることを前提にして備える」という設計思想です。どんなに注意しても人はミスをしますし、ハードウェアはいつか壊れます。100%の予防は不可能です。だからこそ「消えたあとにどう復旧するか」を事前に準備しておくことが、インフラエンジニアの仕事です。

そしてもう1つ。バックアップは手段であり、復旧が目的です。バックアップを毎日取っていても、いざというときに復元できなければ意味がありません。「取ったバックアップから本当に復元できるか」を定期的に確認する。これがリストア訓練であり、今回の核心です。

rsync でファイルをバックアップする

ファイルのバックアップ手段として、rsync と tar の2つを紹介します。それぞれ役割が異なります。

  • rsync: 差分同期。変更があったファイルだけを転送する。日常的な定期バックアップに向いている
  • tar: アーカイブ。ディレクトリ全体を1つのファイルにまとめる。特定時点のスナップショットを残したいときに向いている

まずは rsync から始めます。

rsync のインストール

rsync は Minimal Install には含まれていないため、dnf でインストールします。リモートバックアップでは送信側と受信側の両方に rsync が必要です。alma-main と alma-sub の両方にインストールしてください。

alma-main で実行:

実行コマンド:

$ sudo dnf install -y rsync

alma-sub で実行:

実行コマンド:

$ sudo dnf install -y rsync

ローカルバックアップ

まずはローカル(同じサーバー内)での rsync を体験します。バックアップ用のテストデータを作成します。

alma-main で実行:

実行コマンド:

$ mkdir -p /home/developer/webapp
$ echo "Hello World" > /home/developer/webapp/index.html
$ echo "body { color: #333; }" > /home/developer/webapp/style.css
$ echo "console.log('app');" > /home/developer/webapp/app.js

テストデータが用意できたら、rsync でバックアップします。

実行コマンド:

$ rsync -av /home/developer/webapp/ /tmp/webapp-backup/

実行結果:

sending incremental file list
created directory /tmp/webapp-backup
./
app.js
index.html
style.css

sent 313 bytes  received 117 bytes  860.00 bytes/sec
total size is 52  speedup is 0.12

※ sent bytes、total size、speedup の数値は環境やファイル内容によって異なります。ファイルの一覧が同じであれば正常です。

オプションの意味は次のとおりです。

  • -a(archive): パーミッション・所有者・タイムスタンプなどの属性を保持してコピーする。バックアップ用途では必須
  • -v(verbose): 転送されたファイルの一覧を表示する

「incremental file list」と表示されていることに注目してください。rsync は初回はすべてのファイルを転送しますが、2回目以降は変更があったファイルだけを転送します。この差分同期の仕組みが、日常的なバックアップで rsync が重宝される理由です。

末尾スラッシュの挙動に注意する

rsync でよくある落とし穴が、パスの末尾にスラッシュ / を付けるかどうかで挙動が変わる点です。

  • rsync -av /home/developer/webapp/ /tmp/backup/ → webapp/ の中身が /tmp/backup/ に入る
  • rsync -av /home/developer/webapp /tmp/backup/ → webapp ディレクトリごと /tmp/backup/webapp/ に入る

末尾に / があると「そのディレクトリの中身を」、なければ「そのディレクトリ自体を」転送するという意味です。意図した構成にならない場合は、まずこのスラッシュを確認してください。

リモートバックアップ(alma-sub へ転送)

次に、ネットワーク越しに別サーバー(alma-sub)へバックアップします。rsync は SSH 経由でリモート転送を行います。第27回で alma-main から alma-sub への SSH 鍵認証を設定済みなので、パスワードなしで転送できます。

まず、SSH 接続できることを確認します。

alma-main で実行:

実行コマンド:

$ ssh developer@10.0.1.3 hostname

alma-sub のホスト名が返ってくれば鍵認証は有効です。「Permission denied」が返ってきた場合は、第27回の鍵認証設定を見直してください。

別のテストデータを作成してリモート転送します。

実行コマンド:

$ mkdir -p /home/developer/backup-test
$ echo "file1" > /home/developer/backup-test/file1.txt
$ echo "file2" > /home/developer/backup-test/file2.txt

実行コマンド:

$ rsync -avz /home/developer/backup-test/ developer@10.0.1.3:/tmp/backup-remote/

実行結果:

sending incremental file list
created directory /tmp/backup-remote
./
file1.txt
file2.txt

sent 208 bytes  received 98 bytes  612.00 bytes/sec
total size is 12  speedup is 0.04

-z オプションは転送時にデータを圧縮します。ネットワーク越しの転送では帯域を節約できるため、リモートバックアップでは -avz の組み合わせが定番です。

–delete オプションの危険性

rsync には --delete というオプションがあります。送信元にないファイルを送信先から削除し、送信元と送信先を完全に同じ状態にするものです。

一見便利ですが、ここで考えてみてください。もし送信元で誤ってファイルを消してしまった状態で --delete 付きの rsync を実行したら、何が起きるでしょうか。

答えは「バックアップ先からもそのファイルが消える」です。--delete 付きで rsync を実行すると、バックアップ先からもそのファイルが消えます。つまり「バックアップが消えたファイルの状態を忠実にコピーしてしまう」のです。

--delete を使う場合は、必ず --dry-run(実際には実行せず、何が起きるかだけ表示する)で事前確認してください。

実行コマンド:

$ rsync -avz --delete --dry-run /home/developer/backup-test/ developer@10.0.1.3:/tmp/backup-remote/

出力の末尾に「(DRY RUN)」と表示され、実際の転送は行われません。想定どおりの動作であることを確認してから、--dry-run を外して実行する。この手順を習慣にしてください。

rsync のオプションはほかにも多数あります。man rsync で確認できるので、必要になったら調べてみてください。

tar でアーカイブを作成する

tar は第7回で基本を学びました。ここでは「バックアップ目的でのアーカイブ作成」として、日付付きファイル名の習慣と合わせて実践します。

アーカイブの作成と確認

先ほど rsync で使った webapp ディレクトリを tar でアーカイブします。

alma-main で実行:

実行コマンド:

$ tar czf /tmp/webapp-backup-20260404.tar.gz -C /home/developer webapp/

オプションの意味は次のとおりです。

  • c(create): アーカイブを作成する
  • z(gzip): gzip で圧縮する
  • f(file): 出力先のファイル名を指定する
  • -C /home/developer: 指定ディレクトリに移動してから処理する(アーカイブ内のパスから /home/developer を除くため)

ファイル名に日付を入れるのはバックアップの基本的な習慣です。「いつ時点のバックアップか」が一目でわかります。

作成されたアーカイブのサイズを確認します。

実行コマンド:

$ ls -lh /tmp/webapp-backup-20260404.tar.gz

実行結果:

-rw-r--r--. 1 developer developer 224  4月  4 15:12 /tmp/webapp-backup-20260404.tar.gz

中身を展開せずに確認するには t(list)オプションを使います。

実行コマンド:

$ tar tzf /tmp/webapp-backup-20260404.tar.gz

実行結果:

webapp/
webapp/index.html
webapp/style.css
webapp/app.js

3つのファイルがアーカイブに含まれていることを確認できました。バックアップを取ったら、この tar tzf でアーカイブの中身を確認する習慣をつけてください。中身が空だったり、意図しないパスで格納されていたりといった問題を早期に発見できます。

tar のオプションは多岐にわたります。man tar で全体像を確認できます。

mysqldump でデータベースをバックアップ・復元する

第30回で MariaDB をインストールし、sampledb データベースと employees テーブルを作成しました。ここではそのデータベースを mysqldump でバックアップし、復元するところまでを体験します。

テストデータの確認

まず、第30回で作成したデータが残っていることを確認します。

alma-main で実行:

実行コマンド:

$ mariadb -u appuser -pAppPass456 sampledb -e "SELECT * FROM employees;"

実行結果:

id	name	department
1	田中太郎	開発部
2	山田花子	企画部

第30回で挿入した2件のデータが確認できました。もしテーブルが存在しない場合は、第30回の手順に従って MariaDB のインストールとテストデータの作成を行ってください。

mysqldump でバックアップを取得する

mysqldump はデータベースの内容を SQL 文としてテキストファイルに出力するツールです。出力はバイナリではなく、テキストエディタで中身を確認できる SQL 文の羅列です。

実行コマンド:

$ sudo mysqldump -u root -pTrainingPass123 sampledb > /tmp/sampledb_backup.sql

実行コマンド:

$ ls -lh /tmp/sampledb_backup.sql

実行結果:

-rw-r--r--. 1 developer developer 2.1K  4月  4 15:13 /tmp/sampledb_backup.sql

バックアップファイルが作成されました。2.1K と小さいですが、中身は CREATE TABLE 文や INSERT 文などの SQL 文です。head /tmp/sampledb_backup.sql で冒頭を確認してみると、どのような形式で出力されているかがわかります。

なお、コマンドラインにパスワードを直接書くと「Using a password on the command line interface can be insecure.」という警告が表示される場合があります。検証環境では問題ありませんが、本番環境では ~/.my.cnf にパスワードを記載するか、--defaults-file オプションで認証情報ファイルを指定する方法が推奨されます。

リストア訓練

ここからが今回の核心です。バックアップを取っていても、復元できなければ意味がありません。実際にデータを削除し、バックアップから復元する訓練を行います。

ファイルのリストア

先ほど tar で作成したアーカイブから webapp ディレクトリを復元します。まず、意図的にデータを削除します。

alma-main で実行:

実行コマンド:

$ rm -rf /home/developer/webapp/

削除されたことを確認します。

実行コマンド:

$ ls /home/developer/webapp/

実行結果:

ls: '/home/developer/webapp/' にアクセスできません: そのようなファイルやディレクトリはありません

webapp ディレクトリが完全に消えました。ここからバックアップを使って復元します。

実行コマンド:

$ tar xzf /tmp/webapp-backup-20260404.tar.gz -C /home/developer

オプション x(extract)はアーカイブを展開します。-C /home/developer で展開先を指定しています。

復元されたか確認します。

実行コマンド:

$ ls -la /home/developer/webapp/

app.js、index.html、style.css の3ファイルが復元されていれば成功です。

データベースのリストア

次に、データベースのリストアを体験します。意図的に employees テーブルを削除します。

alma-main で実行:

実行コマンド:

$ mariadb -u appuser -pAppPass456 sampledb -e "DROP TABLE employees;"

テーブルが削除されたことを確認します。

実行コマンド:

$ mariadb -u appuser -pAppPass456 sampledb -e "SHOW TABLES;"

何も表示されなければ、テーブルが削除されたことを意味します。ここからバックアップファイルを使って復元します。

実行コマンド:

$ sudo mariadb -u root -pTrainingPass123 sampledb < /tmp/sampledb_backup.sql

バックアップファイルの SQL 文が実行され、テーブルとデータが再作成されます。復元されたか確認します。

実行コマンド:

$ mariadb -u appuser -pAppPass456 sampledb -e "SELECT * FROM employees;"

実行結果:

id	name	department
1	田中太郎	開発部
2	山田花子	企画部

2件のデータが復元されました。「削除 → 復元 → 確認」のサイクルを一通り体験したことで、リストアの手順が身についたはずです。

現場ヒヤリハット: バックアップファイルが壊れていた話

あるプロジェクトで、毎日 cron でデータベースのバックアップを自動取得していました。バックアップジョブは毎日成功していたので安心していたのですが、ある日ディスク障害が発生してリストアが必要になりました。

いざバックアップファイルから復元しようとすると、ファイルのサイズが0バイト。ディスク容量不足で mysqldump の出力がリダイレクトされたときにファイルが空になっていたのです。ジョブ自体は終了コード0を返していたため、監視にも引っかからず、数か月間ずっと空のファイルを「バックアップ」として保存し続けていました。

この経験から学べることは2つあります。1つは、バックアップのファイルサイズや内容を定期的に検証すること。もう1つは、リストア訓練を定期的に実施すること。「取れているはず」を信じない。自分の目で確認する。これがバックアップ運用の鉄則です。

cron と組み合わせた自動バックアップ

第24回で学んだ cron を使えば、バックアップを自動化できます。たとえば、毎日午前2時に mysqldump を実行する cron エントリは次のようになります。

cron エントリの例:

0 2 * * * /usr/bin/mysqldump -u root -pTrainingPass123 sampledb > /tmp/sampledb_backup_$(date +\%Y\%m\%d).sql 2>> /var/log/backup-db.log

cron 内では % が特殊文字として解釈されるため、\% とエスケープしている点に注意してください。

rsync でリモートサーバーへファイルを転送する処理も cron に組み込めます。

30 2 * * * /usr/bin/rsync -avz /tmp/sampledb_backup_$(date +\%Y\%m\%d).sql developer@10.0.1.3:/tmp/db-backup/ 2>> /var/log/backup-rsync.log

このように「バックアップ取得 → リモート転送」を cron で自動化すれば、毎日手動で実行する必要がなくなります。ただし、自動化したあとも「本当にバックアップが取れているか」「ファイルサイズが0になっていないか」を定期的に確認する運用が不可欠です。本番環境では、バックアップスクリプトの中でファイルサイズを検証する処理を組み込むのが定石です(第26回のシェルスクリプトの知識が活きます)。また、日付付きのバックアップファイルを毎日作成し続けるとディスクが溢れるため、一定期間(たとえば7日間)より古いバックアップを自動削除する世代管理も忘れずに設計してください。

やってみよう

ここまでの知識を使って、2つの課題に取り組んでください。

課題1: ファイルのバックアップとリストア

以下の手順を上から順に実行してください。

  1. /home/developer/practice/ ディレクトリを作成し、その中にテキストファイルを3つ作成する(中身は自由)
  2. tar で /tmp/practice-backup.tar.gz としてアーカイブを作成する
  3. tar tzf でアーカイブの中身を確認し、3つのファイルが含まれていることを確認する
  4. rm -rf /home/developer/practice/ でディレクトリを削除する
  5. tar で /tmp/practice-backup.tar.gz/home/developer に展開して復元する
  6. ls /home/developer/practice/ で3つのファイルが復元されていることを確認する

課題2: データベースのバックアップとリストア

以下の手順を上から順に実行してください。

  1. employees テーブルに1件データを追加する: INSERT INTO employees (name, department) VALUES ('佐藤一郎', '総務部');
  2. SELECT * FROM employees; で3件のデータがあることを確認する
  3. mysqldump で sampledb のバックアップを /tmp/sampledb_exercise.sql に取得する
  4. DROP TABLE employees; でテーブルを削除する
  5. SHOW TABLES; で Empty set になっていることを確認する
  6. バックアップファイルからリストアする
  7. SELECT * FROM employees; で3件のデータ(田中太郎、山田花子、佐藤一郎)が復元されていることを確認する

どちらの課題も「削除 → 復元 → 確認」のサイクルを自分の手で実行することが重要です。手順を間違えても検証環境なので問題ありません。何度でもやり直してください。

まとめと次回予告

今回のポイントを3つにまとめます。

  • rsync は差分同期で日常的なバックアップに向いており、tar は特定時点のアーカイブに向いている。用途に応じて使い分ける
  • mysqldump はデータベースの内容を SQL 文のテキストファイルとして出力する。復元は mariadb < ファイル で行う
  • バックアップは手段、復旧が目的。取ったバックアップから復元できるかを定期的に確認するリストア訓練が不可欠

次回は第32回「監視入門」です。「サーバーが正常に動いているか」を継続的に確認する仕組みとして、監視の考え方から Prometheus + node_exporter による監視体験までを扱います。今回のバックアップと合わせて、サーバー運用の両輪となる知識です。

理解度チェック

今回の内容を○×形式で確認します。

問1: rsync は初回も2回目以降も、すべてのファイルを毎回フルコピーする。

問2: rsync でリモートバックアップを行う場合、送信側だけでなく受信側にも rsync がインストールされている必要がある。

問3: rsync -av /home/developer/webapp/ /tmp/backup/rsync -av /home/developer/webapp /tmp/backup/ は同じ結果になる。

問4: mysqldump で出力されるバックアップファイルの中身は SQL 文のテキストである。

問5: rsync の --delete オプションは、送信元にないファイルを送信先から削除する。送信元で誤ってファイルを消した場合、バックアップ先からも消える可能性がある。

問6: バックアップを毎日自動取得していれば、リストア訓練は不要である。

解答

答え: 問1 ×(rsync は差分同期であり、2回目以降は変更があったファイルだけを転送する) / 問2 ○ / 問3 ×(末尾に / があると中身を転送し、なければディレクトリごと転送する。結果のディレクトリ構造が異なる) / 問4 ○ / 問5 ○ / 問6 ×(バックアップファイルが壊れていたり空だったりする場合があるため、リストア訓練で復元可能性を定期的に確認する必要がある)

前の記事
次の記事