dotcloud上にWordpressを立ててBlog的に使っていたのですが、dotcloudの無料プランが終了してしまいました。。。(今はアクセスも出来ない)
記事や記事で利用した画像ファイルは丁度先月ぐらいにdropboxAPIを利用して毎日バックアップするようにしていたので何とか全ての記事を復活させる事が出来ました。バックアップの詳細はこちら。[dropbox]dotcloudからdropboxAPIを利用してwordpressをバックアップしてみた[dotcloud]
どこかまた違うPaaSにWordpress立てても良いかと思いましたが、今回みたいな事がまた起きるような気もしたのでやめときました。
まあ、そんな感じでこちらでも時間を見つけて何か思いついたりしたら色々書いていこうと思います。
2013年4月29日月曜日
[dropbox]dotcloudからdropboxAPIを利用してwordpressをバックアップしてみた[dotcloud]
Bloggerへの移行前のWordpressにて2013-03-31に投稿した記事です。 このBlogというかWordpressはdotcloudで動いているのですが、今までバックアップをとっておらず、それめっちゃ怖いと今更思い、定期的にバックアップをするようにしてみたのでその時のメモ。
概要
バックアップ対象としてはWordpressのDBとwp-contentで、バックアップ先はdropboxになります。 バックアップ方法としてはDropboxAPIのPython版をdotcloudで動かせるようにしてcronで定期的にファイル送信するという感じです。 Dropboxへファイルを送信するする方法はdotcloudに特化している訳ではないので、それ以外のPasSや自分で管理しているサーバーでも出来るかも。 なお、dotcloudの場合、dbとWebサーバーが別インスタンスみたいなのでそれぞれに環境及びcronの設定を行いました。(一つの環境でできるやり方を知っている方いましたら教えて下さい。。。) ちなみにプラグインがうまく動くようであれば、BackWPupとかが良い感じみたいです。(dotcloudだと上記プラグインうまく動きませんでした。。。。)
目次
- Dropbox Applicationの登録
- Python環境の準備
- DropboxAPIの設定、確認
- PUT用スクリプトの作成
- backup.shの作成
- cronの設定
1.Dropbox Applicationの登録
DropboxAPIを利用する為にアプリケーション登録を行います。 この情報は適当にググれば出てくるので省略します。 Access typeについはapp_folderにしました。(本エントリの確認も上記が前提です。) 下記サイトが参考になりました。 DROPBOX API(PYTHON)を使ってみる
2.Python環境の準備
Pythonが利用出来るようにvirtualenvを利用します。 dotcloudではPython自体は既にインストールされていましたが、モジュールをインストールする際に必要なsetuptoolsが無かったのでvirtualenvを利用しています。(virtualenvを利用するとsetuptoolsは一緒にインストール出来る) dotcloudのwww,dbインスタンスの確認。
$dotcloud conncet <アプリケーション名> $dotcloud info === wordpressapp flavor: sandbox cost to date: Free +------+-------+------------+-----------------+ | name | type | containers | reserved memory | +------+-------+------------+-----------------+ | db | mysql | 1 | N/A | | www | php | 1 | N/A | +------+-------+------------+-----------------+wwwサーバーにログイン。
$dotcloud run wwwDBサーバーにログイン。
$dotcloud run www
以降の処理は両サーバーで実行する。 ダウンロード、解凍
$wget https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.9.1.tar.gz $tar -zxvf virtualenv-1.9.1.tar.gzインストール、有効化
$cd virtualenv-1.9.1 $python virtualenv.py --distribute ENV $source ENV/bin/activate
3.DropboxAPIの設定、確認
DropboxAPIのインストール及び、接続確認を行います。 基本的には公式のドキュメントDropbox Developerに書いてある通りに実行しました。 DropboxAPIのダウンロード、解凍
$wget https://www.dropbox.com/static/developers/dropbox-python-sdk-1.5.1.zip $unzip dropbox-python-sdk-1.5.1.zipDropboxAPIのインストール
$cd dropbox-python-sdk-1.5.1 $python setup.py install
Exampleコードを利用して接続確認を行います。 1.Dropbox Applicationの登録で登録したアプリケーションの情報でApp key,App secretが必要なので確認しておいて下さい。(webから確認できます。) App key,App secretの編集
$cd example $vi cli_client.pycli_client.py
# XXX Fill in your consumer key and secret below # You can find these at http://www.dropbox.com/developers/apps APP_KEY = '' APP_SECRET = '' ACCESS_TYPE = 'app_folder' # should be 'dropbox' or 'app_folder' as configured for your app
APP_KEY,APP_SECRETを入力して下さい。 また、Dropboxへのアプリ登録時にAccess typeをapp_folderじゃなく設定した場合にはACCESS_TYPEの変更が必要そうですがうまくいくかは未確認です。 適当にDropboxに送信するファイルを作成します。
$touch put.txt
サンプルコードの実行。 CLIでdropboxAPIが利用出来ます。 まずはログイン。
$python cli_client.py Dropbox>login url: https://www.dropbox.com/1/oauth/authorize?oauth_token=xxxxxxxxx Please authorize in the browser. After you're done, press enter.
表示されたURLをブラウザで表示すると認証するかの確認画面になるのでAllowを選択。 その後、コンソールに戻ってenterを押します。 その後はDropboxAPIが使えます。(詳細はhelpを入力) 試しにファイルをputします。put後の名前はabc.txtとします。
Dropbox> ls 2013-03-31_04:00:01_UTC.data.tar.gz 2013-03-31_04:00:01_UTC.sql.gz Dropbox> put put.txt abc.txt Dropbox> ls 2013-03-31_04:00:01_UTC.data.tar.gz 2013-03-31_04:00:01_UTC.sql.gz abc.txt
これでサーバーからファイルが送信出来る事が確認できました。
4.PUT用スクリプトの作成
下記参考にさせていただき、コードを少しだけ変えてシェルスクリプトから実行出来るようにします。 DROPBOX API(PYTHON)を使ってみる2
$cd dropbox-python-sdk-1.5.1/example/ $vi backup-wordpress.pybackup-wordpress.py
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import cmd
import locale
import os
import pprint
import shlex
import time
from dropbox import client, rest, session
# XXX Fill in your consumer key and secret below
# You can find these at http://www.dropbox.com/developers/apps
APP_KEY = ''
APP_SECRET = ''
ACCESS_TYPE = 'app_folder' # should be 'dropbox' or 'app_folder' as configured for your app
def command(login_required=True):
"""a decorator for handling authentication and exceptions"""
def decorate(f):
def wrapper(self, *args):
if login_required and not self.sess.is_linked():
self.stdout.write("Please 'login' to execute this command\n")
return
try:
return f(self, *args)
except TypeError, e:
#self.stdout.write(str(e) + '\n')
print str(e)
except rest.ErrorResponse, e:
msg = e.user_error_msg or str(e)
#self.stdout.write('Error: %s\n' % msg)
print ('Error: %s' % msg)
wrapper.__doc__ = f.__doc__
return wrapper
return decorate
class DropboxTerm():
def __init__(self, app_key, app_secret):
self.sess = StoredSession(app_key, app_secret, access_type=ACCESS_TYPE)
self.api_client = client.DropboxClient(self.sess)
self.current_path = ''
self.sess.load_creds()
def do_ls(self):
"""list files in current remote directory"""
resp = self.api_client.metadata(self.current_path)
if 'contents' in resp:
for f in resp['contents']:
name = os.path.basename(f['path'])
encoding = locale.getdefaultlocale()[1]
#self.stdout.write(('%s\n' % name).encode(encoding))
print ('Filename=%s' % name).encode(encoding)
#print ('FullFilename=%s' % f['path']).encode(encoding)
@command()
def do_cd(self, path):
"""change current working directory"""
if path == "..":
self.current_path = "/".join(self.current_path.split("/")[0:-1])
else:
self.current_path += "/" + path
@command()
def do_put(self, from_path, to_path):
"""
Copy local file to Dropbox
Examples:
Dropbox> put ~/test.txt dropbox-copy-test.txt
"""
from_file = open(os.path.expanduser(from_path), "rb")
#from_file = open(from_path, "rb")
self.api_client.put_file(self.current_path + "/" + to_path, from_file)
@command()
def do_rm(self, path):
"""delete a file or directory"""
self.api_client.file_delete(self.current_path + "/" + path)
class StoredSession(session.DropboxSession):
"""a wrapper around DropboxSession that stores a token to a file on disk"""
TOKEN_FILE = "token_store.txt"
def load_creds(self):
try:
stored_creds = open(self.TOKEN_FILE).read()
self.set_token(*stored_creds.split('|'))
print "[loaded access token]"
except IOError:
pass # don't worry if it's not there
def write_creds(self, token):
f = open(self.TOKEN_FILE, 'w')
f.write("|".join([token.key, token.secret]))
f.close()
def delete_creds(self):
os.unlink(self.TOKEN_FILE)
def link(self):
request_token = self.obtain_request_token()
url = self.build_authorize_url(request_token)
print "url:", url
print "Please authorize in the browser. After you're done, press enter."
raw_input()
self.obtain_access_token(request_token)
self.write_creds(self.token)
def unlink(self):
self.delete_creds()
session.DropboxSession.unlink(self)
def main(s):
if APP_KEY == '' or APP_SECRET == '':
exit("You need to set your APP_KEY and APP_SECRET!")
term = DropboxTerm(APP_KEY, APP_SECRET)
print(s);
#term.do_rm(s[1])
term.do_put(s[0],s[1])
if __name__ == '__main__':
import sys
args = sys.argv
if len(args) > 1:
s = args[1:]
main(s)
引数を利用してファイルをputするようにしました。(といってもmain文をほんの少し変えただけですが。。。)
ファイルをputする処理を実行する場合、以下のようにします。
$python backup-wordpress.py put.txt abc.txt
5.backup.shの作成
次に上記スクリプトを実行するシェルを作成します。 といってもdotcloudではバックアップ用のシェルスクリプトが用意されており、それを少しだけ変更すればOKです。 下記を参考にさせて頂きました。 DotCloudをDropboxへバックアップ 2 まずはdotcloudの公式サイトからバックアップ用のシェルをダウンロードしてきます。
$wget http://docs.dotcloud.com/_downloads/backup.sh
次に上記を変更します。
#!/bin/bash
# Syntax:
# backup.sh <what> <how> <where> [whereexactly]
# <what> indicates what you want to backup: mysql, pgsql, riak, data.
# <how> indicates the backup method: ssh, ftp, s3.
# <where> is a <user[:password]@host>.
# [whereexactly] is an optional path on the <where> target, when applicable.
set -e
TAG="$HOSTNAME_$(TZ=UTC date +%Y-%m-%d_%H:%M:%S_UTC)"
source ~/virtualenv-1.9.1/ENV/bin/activate
: <<'#__COMMENT_OUT__'
[ "$3" ] || {
echo "Please specify what to backup, how, and where."
exit 1
}
#__COMMENT_OUT__
case "$1" in
mysql)
FILENAME="$TAG.sql.gz"
FILEPATH="/tmp/$FILENAME"
mysqldump --all-databases | gzip > "$FILEPATH"
;;
pgsql)
FILENAME="$TAG.sql.gz"
FILEPATH="/tmp/$FILENAME"
pg_dumpall | gzip > "$FILEPATH"
;;
riak)
FILENAME="$TAG.bitcask.tar.gz"
FILEPATH="/tmp/$FILENAME"
tar -czf "$FILEPATH" /var/lib/riak
;;
data)
FILENAME="$TAG.data.tar.gz"
FILEPATH="/tmp/$FILENAME"
tar -C "$HOME" -czf "$FILEPATH" "data"
;;
*)
echo "Sorry, I don't know how to backup $1."
exit 1
;;
esac
: <<'#__COMMENT_OUT__'
if [ "$4" ]
then
DEST="$4/$FILENAME"
else
DEST="$FILENAME"
fi
#__COMMENT_OUT__
case "$2" in
ssh)
scp -q -o BatchMode=yes "$FILEPATH" "$3:$DEST"
;;
ftp)
curl -sST "$FILEPATH" "ftp://$3/$DEST"
;;
s3)
s3cmd put "$FILEPATH" "s3://$3/$DEST"
;;
s3multi)
split --numeric-suffixes --bytes=4G "$FILEPATH" "$FILEPATH".
s3cmd put "$FILEPATH".?? "s3://$3/$DEST/"
;;
dropbox)
cd ~/dropbox-python-sdk-1.5.1/example/
python backup-wordpress.py "$FILEPATH" "$FILENAME"
;;
*)
echo "Sorry, transfer method $2 is not supported."
exit 1
esac
SIZE="$(stat --printf %s "$FILEPATH")"
echo "Backup $TAG completed. Its (compressed) size is $SIZE bytes."
rm -f "$FILEPATH"
変更点は以下の通りです。
- shをbashにした
- source ~/virtualenv-1.9.1/ENV/bin/activateを利用してvirtualenvを使う。
- 引数$3,$4は使わないのでコメントアウト(必須ではない)
- 第2引数にdropboxと指定した場合、dropboxAPIを利用する用に設定
実行権限設定。
$chmod +x backup.sh
下記に利用方法について記載します。 1.MySQLのバックアップをdropboxへ送信する場合。
$./backup.sh mysql dropbox
2.wp-conentのバックアップをdropboxへ送信する場合。
$./backup.sh data dropbox
6.cronの設定
最後にcronの設定をします。といっても特別な事はしません。 必要に応じて時間は適当に変更して下さい。 DBインスタンス側。
$crontab -e
00 4 * * * ~/backup.sh mysql dropbox >> result.txtwwwインスタンス側。
$crontab -e
00 4 * * * ~/backup.sh data dropbox >> result.txt
[FuelPHP]FuelPHPのScaffoldで作成した画面をdotcloudにデプロイしてみた[dotcloud]
Bloggerへの移行前のWordpressにて2013-01-12に投稿した記事です。 dotcloudにFuelPHPをデプロイした時のメモ。
前提
ローカル環境にはFuelPHPがインストールされている事。また、MySQLがインストールされている事。やり方が分からない人は以前のエントリ[FuelPHP]FuelPHPでMySQLに接続してScaffoldで画面作成した時のメモをご確認ください。 また、以下で確認を行いました。
- FuelPHP1.5
- MySQL
- ローカル操作はMacOSX
- dotcloudのCLIは0.9
目次
- ローカル環境でScaffold
- dotcloud利用の準備
- Welcomeページの表示
- Scaffoldで作成した画面の表示
1.ローカル環境でScaffold
以前のエントリでも実施しましたが、おさらいも兼ねて。 プロジェクトの作成をします。
$ cd ~/Site/ $ oil create blogoilコマンドでScaffoldを実施します。
$ php oil g scaffold post title:varchar[255] summary:varchar[255] body:textmigrationを実行してDBにテーブルを作成します。
$ oil refine migrate
この状態で「http://localhost/blog/public/post/」にアクセスします。するとScaffoldの画面が表示されるかと思います。
2.dotcloud利用の準備
dotcloudを利用する為にアカウント情報の登録とCLIのインストールを行って下さい。 dotcloud CLI0.9のインストールをMacOSXで実施する際は以下の通りです。(Linux,Windowsの方法は公式Documentをご確認ください)
$ sudo easy_install pip && sudo pip install dotcloud
インストール実施後、以下のコマンドを実行し、dotcloudのログイン情報などを設定して下さい。
$ dotcloud setup
3.Welcomeページの表示
DB接続などが必要ないWelcome画面までをdotcloudで表示します。 まずは必要に応じてドキュメントファイルを削除します。(必須では有りません。)
$ cd ~/Site/blog/ $ rm *.md $ rm -rf docs
次にdotcloudでアプリケーションを作成します。 下記例では「fuelphpapp」という名称のアプリケーションとしております。 アプリケーション名を別にした場合には以降の「fuelphpapp」としている箇所は自分の作成したアプリケーション名に置き換えて下さい。
$ dotcloud create fuelphpapp
アプリケーションが作成されたかを「dotcloud list」コマンドを利用してアプリケーション名一覧を取得して確認します。
$ dotcloud list
作成したアプリケーション名が表示されればOKです。 次にdotcloudにdeployする際に必須となる「dotcloud.yml」を新規に作成します。 このファイルにはどのサービスを利用するか、DocumentRootがどこかを指定します。 今回の場合、PHPを利用し、DBはMySQLを利用し、DocumentRootはpublicフォルダである事を記載します。
$ cd ~/Site/blog/ $ vi dotcloud.yml
www:
type: php
approot: public
db:
type: mysql
最後にfuelphpappに接続し、ソースコードをpushします。
dotcloud connect fuelphpapp dotcloud push
dotcloud pushコマンドが完了すると最後に本アプリケーションのアクセスURLが表示されるので、そのURLをブラウザで開きます。Welcome画面が表示されるかと思います。 URLについてはdotcloudのサイトにブラウザからアクセスしてログインを行っても確認出来ます。
4.Scaffoldで作成した画面の表示
dotcloudのWebサーバーはNginxのため、Nginxでrewriteルールを設定します。 nginx.confというファイルに設定を書く事でdotcloudで設定の読み込みを行ってくれます。 以下の通りファイルの新規作成を行います。 参考:FuelPHPをNginxで動かしてみる
$ vi public/nginx.conf
try_files $uri /index.php?$uri&$args;
次にMySQLにDB、ユーザー、テーブルを作成します。 利用しているサービスの内容を確認します。
$ dotcloud info === fuelphpapp flavor: sandbox cost to date: Free +------+-------+------------+-----------------+ | name | type | containers | reserved memory | +------+-------+------------+-----------------+ | db | mysql | 1 | N/A | | www | php | 1 | N/A | +------+-------+------------+-----------------+
DBの内容を確認します。
$ dotcloud info db == db type: mysql instances: 1 reserved memory: N/A config: mysql_password: ********* mysql_masterslave: True URLs: N/A === db.0 datacenter: Amazon-us-east-1c service revision: mysql/1120eda9aa82 (latest revision) ports: ssh: ssh://mysql@fuelphpapp---------.azva.dotcloud.net:47618 mysql: mysql://root
上記のようにDBの接続先やポート番号、rootパスワードなどが表示されます。 rootユーザーでDBに接続する場合は適宜メモを取って下さい。(本エントリではDBユーザーを新規に作成しております) では、DBにリモートログインします。
$ dotcloud run db -- mysql
DBの作成と確認をします。 作成するDB名は「test_db」としています。
mysql>create database test_db default character set UTF8; mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | test_db | +--------------------+ 3 rows in set (0.00 sec)
次にユーザーを作成し、確認します。 作成するユーザー名は「test_db」としまいます。パスワードを記載する「******」の箇所は適宜変更して下さい。
mysql>GRANT ALL ON test_db.* TO 'dbuser'@'%' IDENTIFIED BY '******'; mysql> select host,user from mysql.user where user='dbuser'; +------+--------+ | host | user | +------+--------+ | % | dbuser | +------+--------+ 1 row in set (0.00 sec)
最後にtableを作成し確認します。
mysql> use test_db
Database changed
mysql> CREATE TABLE posts
-> (
-> ID INT(11) NOT NULL AUTO_INCREMENT,
-> TITLE VARCHAR(255) NOT NULL,
-> SUMMARY VARCHAR(255) NOT NULL,
-> BODY TEXT NOT NULL,
-> CREATED_AT INT(11) NOT NULL,
-> UPDATED_AT INT(11) NOT NULL,
-> PRIMARY KEY (ID)
-> );
Query OK, 0 rows affected (2.00 sec)
mysql> show tables;
+-------------------+
| Tables_in_test_db |
+-------------------+
| posts |
+-------------------+
1 row in set (0.00 sec)
最後にDB接続情報を記載する「db.php」をdotcloudの情報に合わせます。 こちらはUbuntu 12.04 にて dotCloud の MySQL を試してみる (PHP編)を参考にさせて頂きました。 なお、パスワードの「*******」の箇所は適宜変更ください。
vi fuel/app/config/development/db.php
<?php
/**
* The development database settings. These get merged with the global settings.
*/
$filepath = $_SERVER['HOME'].'/environment.json';
$env = json_decode(file_get_contents($filepath), true);
$host = $env['DOTCLOUD_DB_MYSQL_HOST'];
$port = $env['DOTCLOUD_DB_MYSQL_PORT'];
$dbname = 'test_db';
$dsn = 'mysql:host='.$host.';port='.$port.';dbname='.$dbname;
return array(
'default' => array(
'connection' => array(
'dsn' => $dsn,
'username' => 'dbuser',
'password' => '*******',
'persistent' => false,
'compress' => false,
),
),
);
上記設定ファイル例では接続先情報についてはdotcloudの各種設定が記載された「environment.json」をパースし、$dsnとして設定しております。 ファイルを確認し、直接書く事も可能ですが、私はコピペミスをしてDBに接続出来ない!という事があったので、上記のようなファイルから値を取得し、反映させる方法が確実かと思います。 最後に再度ソースコードをpushします。
dotcloud push
「http://[hostname]/post/」というようにブラウザに入力するとScaffold画面が表示されるかと思います。
長い文章になってしまいました、お疲れ様でした。 なお、上記のままだとローカルのFuelPHPが動かなくなってしまうので、ローカルとdotcloudの環境を分けると良いかと思います。(localhostは\Fuel::DEVELOPMENT,dotcloudは\Fuel::PRODUCTIONなど。)
2013年4月28日日曜日
TwitterのbotをdotCloud環境で動かしてみた時のメモ
Bloggerへの移行前のWordpressにて2012-10-11に投稿した記事です。
タイトルの通り、TwitterのbotをdotCloud環境を利用して動作させてみた。せっかくなので、自分の好きな音楽に関係のあるものを作ろうという事で、10月6日、7日に開催される、「朝霧JAM」というフェスまでの日数をカウントダウンするbotを作成。(@asagiri_countとして稼働中)概要は以下の通り。
タイトルの通り、TwitterのbotをdotCloud環境を利用して動作させてみた。せっかくなので、自分の好きな音楽に関係のあるものを作ろうという事で、10月6日、7日に開催される、「朝霧JAM」というフェスまでの日数をカウントダウンするbotを作成。(@asagiri_countとして稼働中)概要は以下の通り。
本当は細かく書きたいのですが、別に何かに書こうとか考えてなくて、適当に作業してたので自分の中のポイントだけ。(本当に役に立たない)
- rubyで作成
- dotCloud上にアプリケーションは配置
- cronで1日4回実行
- dotCloudのサーバーの時間と日本の時間の差
- Twitterの重複投稿エラー?
- cronが止まる?
1.dotCloudのサーバーの時間と日本の時間の差
まあ、そりゃそうだろ、って思ってたけど差分あり。ただ、ありがたいことにdotCloudのサーバーへはssh接続が出来るのでログイン後、確認。dotcloud@ramen-default-www-0:~$ date Sun Sep 30 14:10:36 UTC 2012
toshihiro308$ date 2012年 9月30日 日曜日 23時10分59秒 JSTという事でだいたい9時間ほど違うようなので、それだけプログラムで引いた。そんだけっす。
2.Twitterの重複投稿エラー?
全く同じ投稿をするとエラーになって以下のステータスが返却される。Status is a duplicate. (Twitter::Error::Forbidden)
そういえば、自分も連投してしまった時エラーになってたけど、内部ではこれが発生していたのね。これは単純にtweetする内容の先頭にランダムで文言を追加するようにして逃げた。どうやら少しでも違えば大丈夫らしいので。
3.cronが止まる??
これが一番厄介だった。dotCloudではcronが設定出来て、僕の場合は1日に4回投稿したかったので、6時間毎にrubyを実行するようにしておいた。が、1日ほど経過するとcronが動いてないのか、投稿されなくなってしまう。ついでにsshも繋がらない。とりあえず、サイトのURL(Webアプリケーションとして登録しているので)を叩くと、すぐに表示されず、以下の文章とローディング画面が。This application has no recent traffic and has been put into hibernation. It may tala up to 30 seconds to wake up….上記に書いてある通り、30秒ほど待つとページが表示される。それからはsshが接続出来るようになった。これより仮説として、一定時間リクエストがないとWebアプリは落ちてしまって、cronもついでに動作しなくなるのではないかと考えてた。そこで実験的に1時間に1回自分のWebサイトにアクセスするようにした。
00 0-23/1 * * * wget http://myapplicationname.dotcloud.com/これ以降はcronがかずっと停止せずに動くようになったので、上記仮説は正しかったのかも。(それらしい文献を見つけれなかった)そもそももっと根本的な解決法方法があったのかもしれないけど、よく分からなかったのでこれでOKという事にさせて下さい
登録:
投稿 (Atom)

