WordPress のメディアファイルを自動でバックアップしたり、CloudFront のオリジンにするために wp-content/uploads/ の中身を S3 にアップロードするようにしたいなぁとか言う要望が結構あります。
特に AutoScaling 構成にする場合は、ソースファイルについては git リポジトリなどで管理すればいいですが、ダッシュボードからアップロードされるメディアファイルについては git リポジトリに含めるわけに行かないっすよね。
そんな時、僕の作ったプラグイン絡新婦とか、Amazon S3 for WordPress with CloudFrontとか使うわけですが、なんと 4.3.x 系ではちゃんと動かないような気がするんです…
まぁ、僕が絡新婦をメンテナンスすればいいのですが、最近 php プログラム書くの辛いので代替手段として lsyncd でファイル変更を監視して S3 に自動アップロードするようにしてみました。
参考URL: lsyncdをrsync以外の用途で使う – Qiita
まず、lsyncd をインストールします。
網元なら、以下のコマンドでインストール可能です。
$ sudo rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt $ sudo yum install lsyncd
次に lsyncd 設定ファイル( /etc/lsyncd.conf )を作成します。こんな感じです。
settings { logfile = "/var/log/lsyncd/lsyncd.log", nodaemon = false, } exec = function(event) local src_path = event.sourcePathname spawnShell(event, "/bin/sh /home/ec2-user/bin/s3-uploads " .. src_path .. " || :" ); end s3_media_upload = { maxProcesses = 1, delay = 0, onCreate = exec, onDelete = exec, onMove = exec, } sync { s3_media_upload, source = "/var/www/vhosts/{instance ID}/wp-content/uploads", }
何をやってるかというと
settings {} ではログファイルの位置、デーモンモードでの起動 ( nodaemon = false ) を設定しています。
exec = function(event) では、lsyncd で変更が検知された時に実際に起動するコマンドを指定してます。
event.sourcePathname には、変更が検知されたファイルのパスがセットされます。
lsyncd では、spawnShell で呼び出されたコマンドが error を返す( リターンコード0以外 )と lsyncd 自体が終了しちゃうので、後ろに "|| :" つけて、必ず 0 を返すようにしてます。
s3_media_upload = {} では、ファイルが作成された時( onCreate )、削除された時( onDelete )、移動された時( onMove )に実行するコマンドを指定しています。
sync {} では、監視対象のディレクトリ( source )と、変更が検知された時に呼ばれる設定セット( s3_media_upload )を設定しています。
あとは、exec の中で呼ばれる /home/ec2-user/bin/s3-uploads というシェルスクリプトを作っておきましょう。
こんな感じ
#!/bin/sh s3_bucket='static.example.com' region='ap-northeast-1' aws="/usr/bin/aws --region=${region}" if [ "${1}" = "" ]; then ${aws} s3 sync /var/www/vhosts/{instance ID}/wp-content/uploads/ s3://${s3_bucket}/wp-content/uploads/ else target_path="${1}" string_filename=${target_path##*/} string_path=${target_path%/*} s3_path="${string_filename}" while [ "${string_filename}" != "wp-content" ]; do string_filename=${string_path##*/} string_path=${string_path%/*} if [ "${string_filename}" != "" ]; then s3_path="${string_filename}/$s3_path" fi done if [ -f ${target_path} ]; then ${aws} s3 cp ${target_path} s3://${s3_bucket}/${s3_path} else ${aws} s3 rm s3://${s3_bucket}/${s3_path} fi fi
引数無しで呼ばれた場合は wp-content/uploads/ 全体を sync
引数ありで呼ばれてファイルが存在する場合には s3 cp コマンドでアップロード
引数アリで呼ばれてファイルが存在しない場合には s3 rm コマンドで s3 バケットから対象ファイルを削除
します。
S3 へのアップロード権限を設定する必要があるのでインスタンス作成するときに IAM ロールで権限を与えておくか、IAM ユーザー作って aws configure で設定しておかないとですね。
lsyncd を起動する前にこのコマンドを引数無しで実行して、現在の wp-content/uploads/ の中身を全部 S3 バケットに転送しておくと良いですね。
ここまで出来たら "sudo service lsyncd" で lsyncd を起動させてやればおっけ。