rsyncとシェルスクリプトを使った自動バックアップ環境の構築手順

背景

レンタルサーバ上のwordpressのファイルや、ローカルにあるファイル共有サーバ内のファイルを定期的に自動でバックアップしたいと思ったことがある人は多いと思います。私も常々そう思っていましたが、まあまだデータが消えるようなことは起きないだろうと根拠なく考え、結局やらずじまいでした。ただ、最近大事なデータが危うく無くなる事態に遭遇し、やはりバックアップは大事だと実感しました。そこで指定したファイルのバックアップを指定時刻に自動で作成する環境をようやく構築したので、その手順をメモしておきます。

やりたいこと

以下の図のように、ローカルにあるバックアップ保存用の1台のバックアップサーバ(図中のBackup server)が、同じローカルにあるファイル共有サーバ(図中のFile sharing server)とインターネットを介した先にあるリモートサーバ(図中のRemote server、レンタルサーバなど)のファイルをバックアップサーバに接続された外付けHDDに毎日午前3時に保存させるようにします。


rsync_image
具体的には、バックアップサーバがrsyncというLinuxコマンドによってバックアップを作成します。また、rsyncによるバックアップ作成を定期的に実行するために、Linuxのcronという仕組みを利用します。

環境の構築とは言っていますが、単純にrsyncを実行するシェルスクリプトをcronで定期実行するだけです。

rsyncについて

rsyncはscpと似ています。私自身rsyncとscpの違いについてよくわかっていませんでしたが、大事な違いとしては、rsyncは差分転送できるという点です。一方でscpは差分転送はできないです。rsyncとscpの違いについては以下のサイトに詳しく書いてあり、大変参考になりました。ありがとうございました。

rsyncとscpについて調べてみた | Pandora Pocket
scpとrsyncの所作の違い。気をつけるところ | kenjiskywalker’s diary
scpとrsyncの違い | sasata299’s blog


環境

以下の環境で構築しました。なお、今回の方法ではリモートサーバ(今回はレンタルサーバ)はssh接続が可能であることを前提としています。

  • バックアップサーバ:Ubuntu Server 13.04 64bit
  • ファイル共有サーバ:Windows7 Ultimate 64bit
  • レンタルサーバ:さくらインターネット
  • バックアップ用外付けHDD:WD Elemetns Portable 1.0TB(こちらにレビュー書いてます。おすすめです。)

以降では、ローカルのファイル共有サーバの共有フォルダのファイル、レンタルサーバのファイル、それぞれのバックアップをバックアップサーバに接続された外付けHDDに作成する環境構築の手順についてメモします。

ファイル共有サーバのバックアップを作成する

事前準備

事前準備として以下が必要になります。

  • バックアップサーバにバックアップ用外付けHDD、ファイル共有サーバの共有フォルダのマウント先ディレクトリを作成
  • 外付けHDDをバックアップサーバにマウント
  • 共有フォルダをバックアップサーバにマウント

まずこれらの事前準備についてメモします。ただし、Ubuntu Desktop 14.04で確認したところ、外付けHDDは「/media/user/」(userはUbuntu Desktopのユーザ名)に自動でマウントされていたので、すでにマウントされている場合は以下の外付けHDDのマウントについては不要になります。

外付けHDD、共有フォルダのマウント用ディレクトリを作成

これは以下のコマンドでOKです。以下では外付けHDDのマウント先として「/media/external」、共有フォルダのマウント先として「/mnt/smbfs」というディレクトリを作成しています。

ちなみに、マウントポイントとして「/media」、「/mnt」のどちらを使うかは、厳密なルールはないようです。たぶん。個人的な使い分けとしては、USB、外付けHDDなどのリムーバルディスクは「/media」にマウントし、「/mnt」は共有フォルダとか用にしてました。一応以下のURLに「/media」、「/mnt」の目的が載っているので興味のある方は参照ください。

Filesystem Hierarchy Standard

ファイル共有サーバのフォルダをバックアップサーバにマウント

ファイル共有サーバの共有フォルダをマウントするために、「cifs-utils」をインストールする必要があります。

「cifs-utils」をインストールしたら、あとは以下のコマンドで共有フォルダをマウントすることができます。

よって、例えば以下のような場合は、

  • ファイル共有サーバのIPアドレス(ホスト名も可):192.168.1.10
  • 共有フォルダのパス://192.168.1.10/Users/user/share
  • マウント先:/mnt/smbfs (上記で作成したマウント先ディレクトリのパス)
  • 共有フォルダのユーザ名:user
  • 共有フォルダのユーザ名に対するパスワード:pass

以下のコマンドによってWindowsの共有フォルダをマウントすることができます。

ただし、毎回上記のコマンドを実行してマウントするのは手間なので、Ubuntu Serverの起動時に自動でマウントするようにします。そのためには、「/etc/fstab」を編集して起動時にマウントしたい共有フォルダの情報を追記します。

追記内容は以下のとおりです。最後の1行が追記した部分でそれ以外は私の環境でのデフォルトで記述されていた内容です。

追記した部分は、以下のように共有フォルダのパス、マウント先、ユーザ名、パスワードです。

なお、最後にある2つの0は、それぞれdump(バックアップ)オプション、fsck(ファイルシステムのチェック)オプションを意味しており、0で無効、1ならば有効です。fstabの書式とオプションについては以下のサイトが参考になりました。

fstabの設定 | UNIXLife
/etc/fstabに記述されている数字の意味 | すぱいだー日記

fstabに追記し終えたら、試しに以下のmountコマンドでマウントし直してみます。「-a」はfstabに記載されたファイルシステムすべてをマウントするためのオプションです。

実行結果に何も表示されなければ正常にマウントされたはずです。試しにマウントディレクトリに移動して中身を確認してみるといいです。

ちなみに、もし以下のようにmemory allocate エラーが出る場合は、以下のサイトを参考にWindows7のレジストリの値を変更することで直る場合があるようです。ただし、レジストリをいじることになるので慎重に自己責任でお願いします。

Windowsの共有フォルダをLinuxでマウントして使用する方法


rsyncを使ったシェルスクリプト

事前準備ができたら次にrsyncコマンドを含むシェルスクリプトを作成します。今回作成したシェルスクリプトを以下に載せます。以下のシェルスクリプトの使用は自己責任でお願い致します。また、シェルスクリプトの中に全角スペースが入ると動作しないので気をつけてください。

なお、上記のシェルスクリプトでは、rsyncでできない部分のうち、以下の点をその他のLinuxコマンドで実現しています。

  • 作成してから指定日数以上経過したバックアップは削除し、指定した日数分のバックアップだけを残す。
  • バックアップ作成の結果をログとして残し、さらに指定したメールルアドレスにログ内容を送信する

以下に上記のシェルスクリプトの簡単な説明をメモします。

7,10行目

ここではそれぞれバックアップを作成する元のディレクトリとバックアップ作成先のディレクトリを指定しています。なお、バックアップ作成元は上記で作成した共有フォルダのマウントディレクトリ、バックアップ作成先には同じく上記で作成した外付けHDDのマウントディレクトリを指定しています。

25、28行目

この行では、3つのコマンドをパイプでつなげて$DESTDIRにある最新のバックアップフォルダの名前を取得してそれを変数LASTBACKUPに保存しています。

具体的には、「ls -t $DESTDIR」で$DESTDIRにあるファイル、ディレクトリの一覧をタイムスタンプの新しい順番で取得し、次に「grep backup」によってその中から文字列「backup」を含むものを抽出、そして最後に「head -1」よって抽出してリストしたもののうち一番上にあるもの、すなわちタイムスタンプが最新のディレクトリ名を取得しています。

そして28行目は逆に$DESTDIRにある最古のバックアップフォルダの名前を取得してそれを変数OLDESTBACKUPに保存しています。「ls -tr」のrがタイムスタンプの古い順での表示を指示するオプションです。

31行目

ここでは、「20140101backup」といったようにシェルスクリプト実行日の年月日に文字列「backup」が結合された文字列を変数NEWBACKUPに保存しています。このNEWBACKUPが新しく作成バックアップディレクトリの名前になります。
なお、「date+%Y%m%d」で日付の表示形式を指定しており、これらをバッククオートで囲むことでコマンドとして認識し実行させています。

37行目

条件式の中の「-n」はNon-zeroであるかどうかを判定するためのものです。これでLASTBACKUPに格納された名前と同じ名前を持つディレクトリが存在するかを判定しています。

41行目

mailコマンドを使って$TMPLOGの内容をメールで送信しています。

上記の記述によって、catコマンドで$TMPLOGの内容を表示、そしてその表示結果をパイプでmailコマンドに渡しています。このようにすることで、$TMPLOGの内容を本文とするメールを送信できます。なお、mailコマンドに続く「-s “rsync log from $HOSTNAME”」は件名です。「-s」が件名を指定するオプションです。$HOSTNAMEはubuntuのホスト名を表す環境変数です。そして最後にある$MAILADDが送信先のメールアドレスになります。
mailコマンドを使ってメールをgmailに送信するための手順をこちらにまとめたので、必要な方は参照下さい。

50,58行目

rsyncのオプションを指定しています。「-av」のうちのaオプションは、元ファイルのパーミッションやグループなどを保持したままコピーするためのもので、オプションとして「-rlptgoD」を付加したのと同じ意味です。vオプションは、コピーしたファイル名を表示するためのものです。

なお、LASTBACKUPが存在する場合は、「-av」に加えて差分バックアップを指示するために「- -link-dest」をオプションとして付加し、続けて差分を取る対象となるディレクトリ、すなわちLASTBACKUPを指定しています。LASTBACKUPが存在しない場合は、「- -link-dest」を付加せずにオプションとして「-av」だけ指定します。

つまり、ここでのLASTBACKUPの存在可否によるオプション指定によって、rsyncコマンドが最終的に以下のように分かれます。

  • LASTBACKUPが存在する場合
  • LASTBACKUPが存在しない場合
  • なお、「>> $TMPLOG」を指定することでrsyncによってコピーされるファイル名などのログが、$TMPLOGに追記されていきます。そのため、場合によっては $TMPLOGで指定したログファイルのサイズがかなり大きくなります。このシェルスクリプトでは、最終的に$TMPLOGの内容をメール送信しその後削除してしまいますが(92、93行目)、もしログを削除せず残す場合は、ログローテーションの仕組みを取り入る必要があります。もしくは、追記ではなく最新のログ内容だけ残せば十分な場合は、単純にリダイレクトを「>> $TMPLOG」から「> $TMPLOG」に変更してログを残すようにすればいいかと思います。

    また、「–link-dest」オプションを使って外付けHDDに差分バックアップを作成する場合、差分バックアップの作成先となる外付けHDDのフォーマットがext3などである必要があります。詳しくはこのページの最後にメモしました。

    67,70行目

    変数codeに格納される「$?」は特殊変数というもので、この特殊変数が呼ばれた直前に評価された判定結果を参照できるそうです。すなわち、ここでは、rsyncコマンドの評価結果が変数codeに格納されます。そしてその値が0(正常終了)でなかった場合の処理がエラー対策処理として次の行に記述しています。特殊変数などシェルスクリプトに関して参考にしたサイトを以下にメモしておきます。

    シェルスクリプトにおける条件式や演算子について参考にしたサイト
    演算比較 | シェルスクリプト入門
    $?などの特殊変数について参考にしたサイト
    bash変数と特殊変数 | webzoit.net

    72行目

    rsyncの実行結果が正常終了でなかった場合の処理です。この場合はLOGの内容とcodeの内容をメールで$MAILADDに送信しています。「mail」コマンドによるメールの送信については、こちらにまとめましたので必要な方は参考にして頂ければと思います。

    82行目

    25、28行目と同じ要領で$DESTDIRにあるバックアップフォルダの数を取得しています。「wc -l」が行数を数えるコマンドで、これによって文字列「backup」を含むフォルダ数を取得しています。そして後はMAXNUM以上あった場合に一番古いバックアップフォルダを削除しています。

    あとは作成したシェルスクリプトには用途に合わせて適切な実行権限を与えておきます。今回は以下のようにしました。


    シェルスクリプトを自動実行するためにcronに登録

    上記で実行権限を与えたシェルスクリプトをcronに登録して指定した時刻に自動実行させます。cronについては、以下のサイトにわかりやすく解説してあるので省略します。大変参考になりました。ありがとうございました。

    crontabの使い方 | omnioo lab. records
    cron力をつけよう!全てのcrontab入門者に贈る9個のテクニック | DQNEO起業日記

    rsyncを含むシェルスクリプトがcronに設定した時間に自動で実行できれば、これでバックアップを自動作成する環境の構築の完了です。

    リモートサーバのバックアップを作成する

    リモートサーバのバックアップを作成する場合もファイル共有サーバの場合とほぼ同じです。ただ、シェルスクリプトにいくつか追加する情報と修正する部分があるのでその部分のみをメモします。

    リモートサーバにssh接続するための情報を追記

    リモートサーバにssh接続するために必要なユーザ名、パスワード、ホスト名をシェルスクリプトの「#!/bin/bash」の下あたりに追記します。また、公開鍵認証をして接続する場合は、鍵の指定もします(KEY=/home/ubuntu/.ssh/hogehoge.keyの部分が該当)。ssh接続する場合のポート番号はリモートサーバ、レンタルサーバによって異なるので、適宜変更してください。


    expectコマンドでパスワード入力を自動化してssh接続

    まずexpectコマンドを使用するために以下でインストールしておきます。

    上記のシェルスクリプトでは、rsyncコマンドの実行部分が以下のようになっていました。

    これを以下のように置き換えます。なお、以下はパスフレーズありの公開鍵認証でssh接続する場合です。

    上記で行っているのは、expectコマンドを使用したssh接続に必要なパスワード入力の自動化です。簡単に説明すると、上記の「Are you sure you want to continue connecting (yes/no)?」のようにコマンドを実行した時に予期される質問をexpectの後に記述し、質問に対する答えをsendのあとに記述しておくことで自動入力します。これによって、yes/noの入力やパスワード入力を自動化することができます。詳しくは以下のサイトが参考になりました。ありがとうございました。

    対話型のコマンドを自動化できるexpectコマンド | A day in the boys life

    また、rsyncコマンドの部分は「-e」オプションによって、ssh接続で必要な設定を行っています。例えば以下の場合は、

    「-i」オプションで鍵ファイルを指定し、「-p」オプションでポート番号を指定しています。sshのオプションについては以下のサイトで確認できます。

    SSH (1) | OpenSSH日本語マニュアルページ

    ちなみに、パスフレーズありの公開鍵ではなくパスワード認証でのssh接続を自動化したい場合は、以下のようにします。

    expectに続く質問内容とそれに対応する答えをパスワード認証の場合に合わせた形にし、またrsyncコマンドの「-e」の後にはポート番号を指定する「-p $PORT」のみを記述しています。

    なお、当然ながらexpectの後に続く質問内容や、sendの後に続く答えが正確でなければ、expectコマンドは動作しないです。また、今回はすぐにできたexpectコマンドを使ってしまいましたが、expectコマンドは日本語入力ができないなどの問題点もあるようです。よって、ssh接続の他の方法としてsshpassコマンドを使う方法なども考えたほうがいいかもしれません。ここらへんについては以下が勉強になりました。ありがとうございました。

    sshにパスワードで自動ログインするならexpectよりもsshpassを使おう | PCと遊ぶ日々の記録


    rsyncで遭遇したエラー

    rsync: link operation not permitted(1) が出る

    rysncのログを確認すると大量にこのエラーが出ていました。これは、今回のようにバックアップ作成先である外付けHDDのフォーマット形式がハードリンクに対応してないに関わらず、「- -link-dest」オプションを使用してハードリンクを作成しようとしていたことが原因のようです。すなわち、FATなどWindowsのフォーマットのHDDだとハードリンクを作成できずにこのエラーが出るようです。よって、このエラーを出さずに差分でバックアップを作成したい場合は、HDDのフォーマットをext3などにする必要があります。

    Operation not permitted (link) | Back In Time (英語)


    まとめ

    Linuxのコマンドやシェルスクリプトは奥が深く勉強不足だと改めて感じました。正直、なんとか調べながら自分が望む動作をさせるようにすることができましたが、色々な観点から見て無駄や間違っている部分、不十分な点があるのだと思います。なので。もし何かおかしい点や改善点があったらぜひとも教えて頂ければと思います。よろしくお願いします。

このエントリーをはてなブックマークに追加

SPONSORED LINK

この投稿へのコメント

コメントはありません。

コメントを残す

メールアドレスが公開されることはありません。

この投稿へのトラックバック

  1. […] Linuxでサーバを立ててログをとっている場合、そのログの内容を指定したアドレスにメールで送信したいということがあると思います。私はrsyncで自動バックアップを取る環境を構築するときに必要となりました。そこで、ログ内容をメール送信する方法を調べたので、その方法と手順をメモします。 […]

  2. […] 上記の自動振り分けの時に貼り付けたシェルスクリプトを以下のものに変更するだけで、フォルダに追加されたファイルを自動でレンタルサーバのフォルダにアップロードすることができます。なお、以下のシェルスクリプトはrsyncとsshの鍵認証を使っています。これらについて不明な方はこちらのrsyncの記事が参考になるかもしれません。 […]

  3. […] rsyncとシェルスクリプトを使った自動バックアップ環境の構築手順 […]

トラックバック URL