シェルスクリプトでバックアップのすすめ~初心者でもよくわかる!VPSによるWebサーバー運用講座(5)

VPSによるWebサーバー運用講座の連載5回目(最終回)です。
今回は、シェルスクリプトによるWebコンテンツのバックアップの方法や、OSのセキュリティアップデートについて解説します。
サーバーOSはCentOS 6.7として説明しています。

Webコンテンツの定期バックアップをしよう

VPS上にWordPressなどのCMS(コンテンツマネジメントシステム)をインストールしてWebサイトを運用しているケースは多いと思います。
こういったツールは、ファイル転送ソフトを使わなくてもブラウザだけで記事を書いたり編集したりできて便利です。しかし、作った記事コンテンツはサーバー上にしか存在せずパソコン上には残りません。何らかのアクシデントでデータベースのデータが消えてしまうと、バックアップがどこにもないので泣き寝入りするしかありません。
便利さの反面そういった落とし穴があるので、日頃からデータのバックアップを心がけておきたいものです。

ここでは、サーバーに標準付属のcronのスケジュール実行の仕組みと、シェルスクリプトを使ってデータベースのデータを含むWebコンテンツをバックアップする仕組みを構築します。

なぜシェルスクリプトを使うのか?

例えばWordPressだと便利なプラグインを使うことで、管理画面からバックアップの設定や実行を行うことができます。
BackWPupというプラグインは、ファイルやDBのバックアップを指定した時刻に取ることができます。
しかし、こういったツールに特有の不自由さもありますので、どんな場面でも便利に使えるツールではありません。

cronシェルスクリプトを使ったバックアップは、以下のような利点があります。

  1. WordPressに限らず、データベースを使うどんなCMSにも対応できる。
  2. CMS自体のバージョンアップや仕様変更にあまり影響されない。
  3. バックアップのファイルサイズや実行所要時間に制限がない。
  4. プラグインで実装でよく使われている擬似cronではないので、正確な時刻にスケジュール実行できる。
  5. Webサイトをたくさん所有しており、取得するべきバックアップ対象がいくつあっても拡張が容易で柔軟に対応できる。

逆に、シェルスクリプトによるバックアップは、cronの仕様やシェルスクリプトの知識が必要ですので、誰でも気軽に実装できるわけではありません。
少し学習が必要ですが、一度スクリプトを作ってしまうと他のサーバーや他のCMSにも再利用できますので利用価値は高いと思います。

バックアップスクリプトの仕様

以下のような仕様で、バックアップ用シェルスクリプトを作ります。

バックアップシェルスクリプト

  • 毎日1回cronでスケジュール実行して、コンテンツファイルとDBのバックアップファイルを作る。
  • バックアップファイルは10世代分(10日間分)保管する。
  • 最新のバックアップファイルは、別のサーバーにも1世代分だけ保存する
  • バックアップファイルの名前は
    wordpressfile-yyyymmdd_HHMM.tar.gz (WordPressを構成するファイル群)
    wordpressdb-yyyymmdd_HHMM.sql.gz (データベースのバックアップファイル)
    とし、/backup 以下に保存する。
  • 実行結果をメールで通知する。

CMS上の記事を間違って記事を消してしまったり、バージョンアップや更新に失敗してCMSが動作しなくなったときは、10世代分あるファイル・DBバックアップのいずれかからデータを戻して復旧できます。これは主にヒューマンエラーに対する備えです。
サーバーの障害でデータが失われてしまった場合は、別のサーバーに保存していた直前のバックアップファイルが役に立ちます。これはシステム障害に対する備えとなります。
バックアップの世代管理と保管場所を別の場所にすることで、トラブルに強いバックアップシステムを構築できます。

スクリプト作成の前準備

まず前準備として、別のサーバーへファイルを転送するときに必要な公開鍵認証の接続をセットアップします。
公開鍵認証を用意する理由は、別サーバーへパスワード/パスフレーズ無しでログインしファイルをコピーできるようにするためです。プログラムをスケジュール実行する場合は、別サーバーへログインするときにそのつどパスワード/パスフレーズを手で入力するわけにはいきませんので、パスワード/パスフレーズなしでアクセスする手段を用意します。

公開鍵認証によるパスワード無しscp

VPS側(ファイル送信側)で、公開鍵認証ファイルのペアを作成します。
rootユーザーで作業してください。

# cd
# mkdir .ssh
# chmod 700 .ssh
# cd .ssh
# ssh-keygen

ssh-keygenを実行すると、鍵を生成するための質問が表示されますが、ここではパスフレーズ無しで接続したいため、passphraseは何も入力せずリターンしてください。

Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):何も入力せずリターン
Enter same passphrase again:何も入力せずリターン
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
2b:46:fb:9f:d9:ec:3d:84:c8:54:8d:5a:34:ca:xx:xx root@xxxxxx.vs.sakura.ne.jp
The key's randomart image is:
+--[ RSA 2048]----+
|          .ooo   |
|         . o=.E  |
|          o+ o   |
|          o .    |
|      . So . .   |
|     . . .o . .  |
|      + .    .   |
|     . o   = ..  |
|        ..+.+ .. |
+-----------------+

これで、/root/.ssh の下に

  1. id_rsa
  2. id_rsa.pub

の2つのファイルが作成されます。
id_rsaの権限を変更します。

# chmod 600 id_rsa

次に、コピー先の別サーバーでの設定です。
公開鍵認証は、コピー先別サーバーのvpsuserというユーザーに対して行いますので、vpsuserというユーザーを新規作成します。
コピー先別サーバーへログインし、rootユーザーで以下のコマンドを実行します。

# adduser vpsuser
# passwd vpsuser

パスワード文字列はご自身で決めてください。

vpsuserを作成後、このユーザーでコピー先別サーバーにログインし、公開鍵を置くため次のコマンドを実行します。

$ mkdir .ssh
$ chmod 700 .ssh
$ cd .ssh

authorized_keysというファイルを作成します。
先ほどコピー元サーバーで作成したid_rsa.pubの中の文字列をこのファイルに転記します。
以下のようなイメージになります。

$ vim authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwoiyK4GkblZmYzW0rzcVipGROU7rWDhdFJDYwqswEICVL5Q5121T7YujJD0Cc/twhH7VUbwSRGggnen4GgoUT9EVDDhWbOv4WENNRdsTJEGa4q76oeIwGxFKXgaJOUbzQVwRCOyLmkaAIDcm0o77Qok1vOitZ6M8jnzSx2PG+atFHhxIomlKIJjMNexdKUTeUf/COEAu7kvpPK8kerWzuTtIPm8qDNukVF6h2aVV5lnhew/FJBjL+X4uRbc8hBg5U3QA11N+fx6SqTF0or7zRPc/PQbfyTSb+CaOZFVI2yInOCxaar38vcGVGRvl/rervyPGu+7kJn0rUV10a0Afuw== root@xxxxxxxxxxxx.vs.sakura.ne.jp

vimを保存して終了し、authorized_keysの権限を600(本人のみ書込可能)にしておきます。

$ chmod 600 authorized_keys

以上で、公開鍵認証の設定ができました。
試しに、sshでパスワード無しで接続できることを確認してみましょう。
コピー元サーバーから、rootユーザーで以下のsshコマンドを実行します。

# ssh -i /root/.ssh/id_rsa vpsuser@(コピー先別サーバーのIPアドレス)

初回接続時に

Are you sure you want to continue connecting (yes/no)?

のようなメッセージが出ますが、'yes'とタイプすれば次回以降パスワード無しでログインできるようになります。

これで、パスワード無しでコピー先別サーバーへ接続する準備が整いました。
もし、上記のssh コマンドでパスワードが求められてしまう場合は、コピー元/コピー先の.sshディレクトリの権限が正しいか、aurhorized_keysの権限が正しいかなどを確認してみてください。

公開鍵認証についてもっと詳しく知りたい方は以下の記事を参考にしてください。
「よく分かる公開鍵認証」~初心者でもよくわかる!VPSによるWebサーバー運用講座(2) - さくらのナレッジ

次に、コピー元サーバーでバックアップファイルを保存しておくディレクトリを作成します。
/backup というディレクトリをルートディレクトリ以下に作成しておきます。

# mkdir /backup

以上で前準備は完了です。

次に、以下に示すバックアップシェルスクリプトを
/usr/local/bin/cmsbackup.sh
として保存します。
青色の部分を自分の環境に合わせて変更してください。

#!/bin/bash
datestr=`date +%Y%m%d-%H%M%S`
STATUS=0

# 関数: scpを行う
# $1 コピー元ファイル名(フルパス)
# $2 コピー先ファイル名
function scpfile(){
    eval "scp -i /root/.ssh/id_rsa $1 vpsuser@IPアドレス:~/$2"
    if [ $? -ne 0 ]
    then
	echo "[ERROR]scp error. file=$1"
	STATUS=1
    fi
    return
}

# 関数: ファイルの削除を行う。
# $1: 削除対象のファイルパス(前方一致)
# 10世代分のファイルを残し、それより古いファイルは削除します。
function deletefile(){
    CNT=0
    for file in `ls -1t ${1}*`   # 更新日付が新しい順にファイル名のリストを作る
    do
	CNT=$((CNT+1))
        
	if [ ${CNT} -le 10 ]  # 10世代より過去のバックアップは削除する
        then
	    continue
        fi
	eval "rm ${file}"
    done
    return
}

# MAIN処理
# /var/www/html以下のファイルを
# /backup/wordpressfile_YYYYMMDD-HHMMSS.tar.gzとして保存します。
eval "tar czf /backup/wordpressfile_${datestr}.tar.gz /var/www/html"
if [ $? -ne 0 ]
then
    echo "[ERROR]tar error."
    STATUS=1
fi

# データベースのデータをエクスポートして
# /backup/wordpressdb_YYYYMMDD-HHMMSS.sql.gzとして保存します。
# 青色の部分を修正してください。
eval "mysqldump -u root -ppassword データベース名 |gzip -c > /backup/wordpressdb_${datestr}.sql.gz"
if [ $? -ne 0 ]
then
    echo "[ERROR]mysqldump error."
    STATUS=1
fi

# 10世代より前のファイルを削除します。
deletefile "/backup/wordpressfile_"  # WordPressファイルの削除
deletefile "/backup/wordpressdb_"  # データベースバックアップの削除

# 最新のバックアップファイルを別のサーバーへコピーします。
scpfile /backup/wordpressfile_${datestr}.tar.gz wordpress.tar.gz
scpfile /backup/wordpressdb_${datestr}.sql.gz wordpressdb.sql.gz

# 実行結果をメールで通知します。
# メールアドレスを設定してください。
if [ ${STATUS} -ne 0 ]
then
    SUBJECT="[ERROR]cms backup report"
else
    SUBJECT="[SUCCESS]cms backup report"
fi
echo "" | mailx -s "${SUBJECT}" "mail@example.com"

exit ${STATUS}

もし、vimでテキストを貼り付けたときに日本語が文字化けする場合は、
ホームディレクトリに .vimrc ファイルを作り、

set encoding=utf-8

と書いておけば文字化けは解消すると思います。

このスクリプトに実行権限をつけ、実行します。

# chmod 755 /usr/local/bin/cmsbackup.sh
# /usr/local/bin/cmsbackup.sh

うまく動作しましたでしょうか?
もし、エラーが出るなどしてうまく動かない場合は、以下のコマンドで実行すると処理をトレースできますのでデバッグに役立ちます。

# bash -x /usr/local/bin/cmsbackup.sh

バックアップ処理をスケジュール実行する

次に、毎日深夜3時にこのバックアップ処理を実行するようスケジュールしましょう。
スケジュール設定はcronという仕組みによって行います。設定ファイルは/etc/crontabです。

# vim /etc/crontab

設定ファイルに以下の行を追加して保存します。追加する場所はどこでも構いません。

0 3 *  *  * root /usr/local/bin/cmsbackup.sh

これで毎日深夜3時にroot権限で/usr/local/bin/cmsbackup.shが実行されるようになります。

設定内容の意味は以下のようになります。
crontab解説

トラブルが起きた時のリストア

以上でCMSのバックアップの仕組みが構築できました。
では、万が一トラブルが発生して、バックアップファイルからデータを復旧しなければならなくなった時はどうすればよいでしょうか?
バックアップからの復旧に関するコマンドを解説します。

CMS内のファイルや、投稿した画像ファイルなどが失われてしまいそれを復旧したい場合は、コンテンツのバックアップファイルを解凍・展開してそれを cpコマンドで本来の場所に戻します。
解凍コマンドは圧縮したときのコマンドと同じくtarコマンドを使います。オプションは解凍して展開するオプションxzfになります。

# cd /backup
# tar xzf wordpressfile_YYYYMMDD-HHMMSS.tar.gz

実行すると同じディレクトリにvar/www/html/... という階層のディレクトリが作成されますので、必要なファイルを /var/www/html の下にコピーしてください。

データベースの復旧は少し複雑です。
まずはgzipコマンドでファイルを解凍します。

# gzip -d wordpressdb_YYYYMMDD-HHMMSS.sql.gz

次に、解凍されたsqlファイルをデータベースにインポートしますが、もしこの時点でインポート先のデータベースも失われてしまっている場合は、データベースを先に作成します。
ここでは、wordpressdbというデータベースを作成しています。

# mysqladmin -u root -p create wordpressdb

パスワードを求められますので入力してください。

そして、データをmysqlコマンドでインポートします。

# mysql -u root -p wordpressdb < wordpressdb_YYYYMMDD-HHMMSS.sql

こちらもパスワードを求められます。

以上でリストアできました。

これからの運用で気をつけること

これでひと通りのVPSのサーバー運用編は終わったわけですが、今後も安定してVPSを使い続けていくには気をつけておくべきことがあります。
VPSは、レンタルサーバーと違ってサーバーの面倒を自分で見なければなりません。たまに、サーバーのセキュリティ脆弱性の問題が発生することがありますので、そういう情報を敏感にキャッチして適切な対処ができるようにしましょう。

VPSにインストールされているソフトウェパッケージのバージョンの確認は、以下のコマンドで確認できます。

# yum list installed

以下のコマンドは、セキュリティアップデートがあるソフトウェアのみをアップデートするコマンドです。定期的に実行すると良いでしょう。

# yum --security update

さくらのVPSに関する重要なお知らせは以下に掲載されます。特にソフトウェア脆弱性に関するお知らせが出た場合はすみやかに対処しましょう。
お知らせ: | さくらインターネット
https://www.sakura.ad.jp/news/sakurainfo/newsindex.php

脆弱性対策情報ポータルサイトJVNに、緊急で必要な脆弱性対応などが掲載されるので、こちらもあわせてご覧ください。
Japan Vulnerability Notes
本連載は以上です。

5回にわたりお届けした「VPSによるWebサーバー運用講座」、いかがでしたでしょうか。
一度構築したサーバーを長く使い続けるためにも、運用にも気を配って末ながいおつきあいをしていただければと思います。