#0006 [上級編]WordPressを自動バックアップしよう (1) – シェルスクリプト作成 –

以前、こちらでWordPressのバックアップをコマンドラインから実施しました。毎回SSHでログインしてコマンドを実行してもよいのですが、人が手でコマンドを打つと間違うリスクを排除しきれません。複数回同じコマンドを実行するのであれば、これらのコマンド群をひとまとめにしたシェルスクリプトを作成し、cronで実行するようにしましょう。今回はシェルスクリプト作成について解説します。

SHELLSCRIPT_0001

今回のゴール

今回のゴールは、さくらのレンタルサーバーへインストールしたWordPressを定時バックアップすることです。これを実現する仕組みとして「シェルスクリプト」と「cron (crontab)」の仕組みを利用します。

シェルスクリプトとは

シェルスクリプトは、オペレーティングシステムのシェルまたはコマンドラインインタプリタ向けに書かれたスクリプトである。シェルスクリプトは他のツールを組み合わせるためのグルー型のドメイン固有言語とみなされることもある。シェルスクリプトで書かれる典型的処理としては、ファイル操作、プログラム実行、テキストの印刷などがある。

wikipedia 「シェルスクリプト」より引用。

cronとは

crontab(クロンタブ、あるいはクローンタブ、クーロンタブとも)コマンドはUnix系OSにおいて、コマンドの定時実行のスケジュール管理を行うために用いられるコマンドである。標準入力からコマンド列を読み取り、crontabと呼ばれるファイルにそれを記録する。この記録を元に定時になると、その命令内容を読み取り、実行が行われる。cronという名称はギリシア語のクロノス (χρόνος)に由来するという説がある(Command Run ON の略という説も)。日本ではクーロンという読みが慣習的に広く用いられているが、海外では通常クロンまたはクローンと発音する。

wikipedia「crontab (cronより転送)」より引用。


シェルスクリプトやcronそのものの解説をここで全部やろうとすると非常に冗長になってしまうので、今回のゴールへ向けた説明だけいたします。もしご興味があれば、以下の書籍がおすすめですので、是非ご一読ください。

WordPressバックアップシェルスクリプト「WPARC」を作成する

シェルスクリプトというプログラムは、ものすごく端折った説明をすると、複数のプログラムを順に実行するテキストファイルです。なので、シェルスクリプトそのものをコンパイルしたりする必要はなく、好きなエディタで編集して実行権をつけて実行するだけで出来上がりです。

また、拡張子はつけてもつけなくても構いません。lsコマンドを実行して「あ、これシェルスクリプトなんだ」と人間が判断するために拡張子「.sh」をつけても構いませんし、二重拡張子をつけても構いませんし、本章の見出しのように拡張子をつけなくても構いません。

今回は、さくらのレンタルサーバーに最初からインストールされているエディタviを用いて編集しますが、viやvimの扱いに慣れていない場合は、手元のパソコンで編集してさくらのレンタルサーバーへアップロードして実行権をつけても構いません。

WPARCの仕様

今回作成する、さくらのレンタルサーバーのWordPressバックアップスクリプトですが、以下の仕様で作っています。

  • ドキュメントルート ( ${HOME}/www ) とデータベースのバックアップを一撃で行う
  • 毎日実行することで直近3日ぶんのバックアップを作成し、4日目になると、古いバックアップを1世代削除する

細かい点としては、中でmysqldumpコマンドを実行しているのですが、引数にホスト名やパスワードを指定するとpsコマンドでパスワードが見えてしまうので、これを防ぐために ${HOME}/.my.cnf がなければ生成するようにしています。

もっとも、これを書いている時点では、さくらのレンタルサーバーではpsコマンドで他人のプロセスを見ることはできないのですが、今後rootの取れるVPSや専用サーバー、さくらのクラウドへ移行する場合には覚えておいて損はないでしょう。

どこにシェルスクリプトを作成するか

自身が読み書きできる(そして、cdコマンドで中に入れる)ディレクトリであれば、どこにシェルスクリプトを作成しても構いません。例えばホームディレクトリ以下に「SHELLSCRIPT」というサブディレクトリを作成してそこで実行しても構いませんが、ここではホームディレクトリ以下に「bin」ディレクトリを作成し、その中にシェルスクリプトを配置することにします。まずは bin ディレクトリを作成してみましょう。

mkdirコマンドのあとに「-p」オプションをつけて、ホームディレクトリ ( ${HOME} ) 直下に bin ディレクトリを作成します。 -p をつけることで、もし作成しようとするディレクトリがなければ、という条件をつけて実行することができます。

ディレクトリを作成し終えたら、いきなりviでスクリプトを編集しても構いません。が、シェルスクリプトを作成したはいいものの実行権をつけ忘れるというのはよくある話なので、私は最初に touch コマンドでファイルを生成し、 chmod コマンドで実行権をつけ、それから vi で編集するようにしています。そうすると、シェルスクリプトができた時点でもう実行可能になっているということになります。つまり、忘れやすいコマンドは、可能であれば先に実行してしまえというお作法です。

シェルスクリプトを作成する

viコマンドでシェルスクリプトを作成します。viには「コマンドモード」と「編集モード」という2つのモードがあります。前者はキーボードで入力した文字をコマンドとして解釈し、後者はキーボードで入力した文字をファイルへ打ち出します。

viを起動すると、最初はコマンドモードとして起動されますので、まだ文字列の入力はできません。カーソルのある位置に文字列を入力したい場合には、「i」を入力し、それから入力したい文字列を入力します。

viを終了したりファイルを保存してviを終了したりするときなどは、コマンドモードで行います。先ほど文字列を入力したときは「編集モード」でしたが、編集モードからコマンドモードへ戻るときは「ESC」キーをを押します。今どのモードかわからない場合、ESCキーを押せば、今どちらのモードであるかにかかわらずコマンドモードへ戻るので、困ったらESCを押す癖をつけておくのもよいでしょう。

ファイルの保存は先ほどの説明の通りコマンドモードになりますが、今度はviの中でファイル保存コマンドを実行します。大文字で「ZZ」とタイプするか、「:wq」とタイプしたあとエンターを押します。これらのうち、どちらかのコマンドを実行することで、ファイルを保存してviを終了することができます。もし「あ、今編集した内容イケてないな?でもお昼に出ちゃうからファイルを保存しないでviを閉じよう」といった場合には、コマンドモードで「:q!」と入力してエンターを押すと、ファイルを保存せずにviを終了することができます。それでは、viでシェルスクリプトを作成しましょう。

ソースコードは以下の通りです。

1行目の「#!/usr/bin/env bash」はシバン(シェバン)といい、これからどの言語で実行しますよ、という宣言をしています。よくいろんなサイトで見る例として「#!/bin/sh」「#!/bin/bash」「#!/usr/local/bin/bash」などがありますが、bashをどこにインストールするか、はOSをインストールする管理者によって変更する場合もあるかと思いますので、envを使って、シェルのパスを意識しないようにしました。

※ 2016/03/18 10:48 追記
envだとcronから実行したときに「bashなんてないぞ」とエラーになるので、シバンは「#!/usr/local/bin/bash」の決め打ちに変更しました。。。

上記の例では改行も含めて26行目まではすべて変数の宣言です。このスクリプトの中で使う固有の値はすべて変数へ格納するようにしています。こうすることで、例えばサーバーを引っ越したり、複数のさくらのレンタルサーバーで同じ処理を行いたい場合に、変数の宣言部分を書き換えればよいということになります。

もう1つ付け加えると、これはさくらのレンタルサーバー間で使いまわす分には不要なのですが、ファイル名に日付を与えるところでdateコマンドの出力結果を食わせているのですが、FreeBSDのdateコマンドとLinuxのdateコマンドで同じことをしようとするとオプションが違ったりするので、OS間の差異を吸収するようにしています。

上記のスクリプトは、あまりエラーハンドリングを考えて作っていません。1日1回、手動またはcronで実行することを前提としていますので、例えば二重実行しようとすると、ドキュメントルートのバックアップ、つまり tarコマンドを実行しようとすると「上書きするけどいいの?」と聞かれます。

手動で実行してターミナルの進捗を見ていれば気がつくので「y」をタイプすれば上書きしてくれますが、cronで実行する場合はえんえん待ってしまうことになってしまいます。このまま何日も放置してしまうと、共用サーバーですから処理待ちのプロセスが増えて他のユーザーに迷惑をかけてしまいます。なので、バックアップ処理開始の部分はこう書き換えるとベターです。

これはどういう仕組みかといいますと、シェルスクリプト(bash)のif文の条件分岐を使い、MySQLのダンプファイルの圧縮ファイルが存在しなければmysaldumpコマンドを実行し、同様にコンテンツのバックアップ(ドキュメントルート ${HOME}/www 以下の圧縮ファイル)がなければドキュメントルート以下を圧縮する、という処理を行っています。

バックアップ処理開始の部分をこのように書き換えることで、いわゆる「こんなこともあろうかと」を実現することができます。

今回は単純なバックアップでしたので、これ以上複雑な条件分岐は必要ないでしょう。シェルスクリプトに限らず、プログラムというものは「誰が何度実行しても同じ結果を得る」ためにあります。自分に代わって誰かにコマンドを叩いてもらうときも、コマンドを複数回叩かせるよりは「ログインして WPARC を実行してね」と伝えるだけでよくなります。

もう1つ、プログラムというものは「思った通り」に動いてくれません。「書いた通り」に動くものです。脅かすようで申し訳ないのですが、もし「思った通りにプログラムが動いていない」と感じた場合、それは「思った通りに書いていない」だけなのです。しかし、複雑な処理がキマったときは大きな達成感を得ることができるのも事実です。仕事で個人の快楽を優先するのはいけませんが、こうした喜びがあるというのも、プログラミングをやる動機であるには違いないので、ささやかな喜びにするのもよいでしょう。

シェルスクリプトを学ぶには、先ほどご紹介したこちらの書籍が非常に役立ちます。

入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界

シェルスクリプトを実行するOSがFreeBSDか、Linuxか、そして、使うシェルがshなのかbashなのか、cshなのか、zshなのか・・・などによって差異はありますが、おおよその基本的なことがらはこれに書いてありますので、手元に1冊置いておくことをおすすめします。

さて、長くなってしまいましたが、WordPressバックアップの自動化に向けて、シェルスクリプトの準備ができました。次回はcronからシェルスクリプトを実行し、毎日寝ててもバックアップが取れている、という状態にしたいと思います。