ブログのバックアップを取る仕組みを作った

先日のエントリで「バックアップを自動で行う仕組みづくり」に言及したので、実際に作りました。

やりたいことを整理します。

EC2でやりたいこと

  • MySQL(実体はMariaDB)のWordPressのDBのバックアップ(ダンプ)をとる。
  • WordPressのディレクトリのバックアップをとる(これはtar+gzipでOKとしよう)。

ローカル(家)でやりたいこと

  • EC2で取得した2つのバックアップファイルをコピーしてくる。

EC2、ローカル共通でやりたいこと

  • 古い、一定期間経過したバックアップは削除する。
  • 削除のタイミングはEC2は早め(保管期間短め)、ローカルは遅め(長め)にする。

というあたりは、深く考える(考えた)というよりは、文字に起こす過程で整理した、というのが正直なところです。そもそもそんなに複雑なことをやりたいわけじゃないですし。シェルスクリプトを書いて、配置して、cronでキックするだけです。このブログを書く方がずっと時間がかかっています。これでも誤字脱字誤変換に気を付けたり、読みやすいように文章推敲したりしているんですよ。ホントですって!

ただ、既存の知識と経験でお手軽に作ったので、せっかくクラウドサービスに乗っているのに、それを活用したことを何もやれていないのが残念なところです。例えば、バックアップをEC2/EBSではなくてS3に保管する、S3に保管したファイルの操作(削除)をLambdaで行う、などといったことです。追い追い、できるようにしていきたいものです。

近々東京リージョンからオレゴンリージョンPhoenixゾーンにお引越しをするので、その時の構築でリストアの試験をするのは必須として、クラウドサービスを活用した仕組みに変えていくのも出来たらいいなと思います。

さて、作ったスクリプトをそのまま晒すことも考えたのですが、結局説明は書くので、日本語の説明で行きたいと思います。こういう、他人には価値ゼロであろうオレオレスクリプトも、GitHubにおいていいんですかねー。悩みます。

さて、書いたスクリプトは次の3本です。

  1. EC2、ローカル共通の変数を定義する。次の2つのスクリプトからsourceする
  2. EC2でMySQLのダンプ、WordPressディレクトリのバックアップを取得する
  3. ローカルでEC2からバックアップを取得する

スクリプト1の役割は変数の定義で、次のことをしています。

  1. EC2上でのバックアップの取得場所の親ディレクトリの絶対パスを変数に代入する
  2. ローカルでのバックアップファイルの置き場所となる親ディレクトリの絶対パスを変数に代入する
  3. 各バックアップファイルの置き場になるサブディレクトリとファイル名のプレフィックス(面倒なので共通、同じ文字列)を変数に代入する
  4. 各バックアップファイルに付ける名前の一部の今日の日付(YYYYmmdd)を変数に代入する
  5. 1,3,4と拡張子で構成される各バックアップファイルのEC2での絶対パスを変数に代入する
  6. ホスト名を取得して、削除対象となるバックアップファイルの日付(YYYYmmdd)を変数に代入する(とりあえずEC2/EBSは3週間、ローカルは半年にしました。前者は短くするかも、後者は長くするかも)
  7. 2,3,6で構成される削除対象となるバックアップファイルのファイル名を変数に代入する

スクリプト2の役割はEC2でのMySQLのダンプとWordPressのディレクトリのバックアップで、次のことをしています。

  1. スクリプト1を読み込む
  2. mysqldumpコマンドでWordPressデータベースのダンプを取得する
  3. 2で取得したダンプをgzipコマンドで圧縮する
  4. WordPressディレクトリのバックアップを取る(tar+gzipコマンド)
  5. 削除対象のバックアップファイルを削除する

スクリプト3の役割はローカルへのバックアップファイルの取得で、次のことをしています。

  1. スクリプト1を読み込む
  2. スクリプト2で取得したWordPressのバックアップ2ファイルをEC2から取得して、スクリプト1の2の変数+スクリプト1の3の変数のディレクトリに置く
  3. 削除対象のバックアップファイルを削除する

実際には、上記の箇条書きで2つ番号が振られた処理を1行でやったり、逆に1つの番号の処理を複数に分けたりしています。
例えば、スクリプト2の2と3は、mysqldumpコマンドの出力をパイプでgzipコマンドに渡してスクリプト1の5のファイルの絶対パスにリダイレクトしています。逆に、同じくスクリプト2の4は、実は次の2に分かれています。

  1. tarコマンドでWordPressのディレクトリを1ファイルにまとめる
  2. gzipコマンドで1のファイルを圧縮する

tarコマンドの-zオプションを使わなかったのは圧縮率優先にしたかったからです。tarコマンドでgzip -9に相当する処理をさせる方法を私が知らないので、tarコマンドではファイルをまとめるだけ、圧縮はgzipに明示的に-9をつける、と処理を分割しました。ちなみにtarコマンドの-fオプションに指定するファイル名とgzip -9の対象にするファイルの名前は変数で${FILENAME%.gz}としています。

古いバックアップファイルの削除をスクリプト2,3の最後で行っているのは、バックアップ取得前に削除するのは違うだろ、と思ったからです。スクリプト1で実行すると多少コード量削減になるはずですが、あえてやりませんでした。スクリプトはset -euを付けて、どこかでなにかが失敗したら止まるようになっています。最悪、バックアップが取得されず、過去のバックアップだけ日々削除する、といった事態は避けられるようになっています。

同じノリで、というかスクリプトの再利用に近い形で、Apacheのアクセスログとエラーログもローカルに保管するスクリプトも書いてcronに仕込みました。Splunkにログをインポートするのは、まだ自動化していません。自宅のグローバルIPアドレスを日々取得してフィルタ(grep -v)する仕組みがまだ作れていないからです。
既存の仕組みに乗っかって、利用させてもらって作るのは難しくないですが、せっかくなので自分で作ってみたいなーと思っています。

今日はこのくらいで。