<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/ME2.2.3" -->
<rss version="0.92">
<channel>
	<title>Groove Labo Log</title>
	<link>http://labo.opengroove.com/blog</link>
	<description>株式会社オープングルーヴの開発者のブログ</description>
	<lastBuildDate>Fri, 19 Dec 2008 08:19:18 +0900</lastBuildDate>
	<docs>http://backend.userland.com/rss092</docs>
	<language>ja</language>
	
	<item>
		<title>MySQLでバックスラッシュの入った文字列を比較する際の注意点</title>
		<description>MySQLを使っていて、次の2つの文字列比較


= で比較する場合
Likeで比較する場合


でバックスラッシュの入った文字列を検索する場合、で \ の数が違いました。

= で比較の場合、2重にすることでマッチする


mysql> select 'foo\\bar' = 'foo\\bar';
+-------------------------+
&#124; 'foo\\bar' = 'foo\\bar' &#124;
+-------------------------+
&#124;                       1 &#124;
+-------------------------+
1 row in set (0.00 sec)


= で比較の場合、4重にするとマッチしない


mysql> select 'foo\\bar' = 'foo\\\\bar';
+---------------------------+
&#124; 'foo\\bar' = 'foo\\\\bar' ...</description>
		<link>http://labo.opengroove.com/blog/index.php/2008/12/19/mysql%e3%81%a7%e3%83%90%e3%83%83%e3%82%af%e3%82%b9%e3%83%a9%e3%83%83%e3%82%b7%e3%83%a5%e3%81%ae%e5%85%a5%e3%81%a3%e3%81%9f%e6%96%87%e5%ad%97%e5%88%97%e3%82%92%e6%af%94%e8%bc%83%e3%81%99%e3%82%8b/</link>
			</item>
	<item>
		<title>xen でゲストOSのネットワークインターフェイスのみ使う</title>
		<description>何もする必要はありませんでした。。

xenの仮想サーバーでDom-U(ゲスト)をインターネット向けのサーバーとして利用することになりました。

Dom-0(ホスト)用のハードウェアにはインターフェイスがeth0, eth1の2つあり、そのうち、eth1を内部LAN向けのインターフェイスとして使っています。

Dom-Uもネットワークインターフェイスを2つ作り、eth1を内部LAN向け、eth0をインターネット向けとして、それぞれ、Dom-0のブリッジとつなげました。

VMware では、ホストOSのインターフェイスを停止させると、そのインターフェイスを使っているゲストOSのインターフェイスも使えなくなってしまいます。

そのため、xenでもDom-0のeth0インターフェイスはあげておく必要があると思いましたが、落とした状態でもDom-Uの外向けインターフェイスは利用可能でした。

こんな状態と思っていましたが


INTERNET
  --+------------------------------
    &#124;
    &#124;
    &#124;  +-------------------------------+
    &#124;  &#124; +---------------------------+ &#124;
    &#124;  &#124; &#124;       Dom-U (ゲスト)      &#124; &#124;
  ...</description>
		<link>http://labo.opengroove.com/blog/index.php/2008/10/22/xen-%e3%81%a7%e3%82%b2%e3%82%b9%e3%83%88os%e3%81%ae%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af%e3%82%a4%e3%83%b3%e3%82%bf%e3%83%bc%e3%83%95%e3%82%a7%e3%82%a4%e3%82%b9%e3%81%ae%e3%81%bf/</link>
			</item>
	<item>
		<title>VMware Server 2.0 でアプリケーションエラーが。。</title>
		<description>自分のPC (Wndows XP Pro)のVMware Server を1.0.7から2.0にしたら、vmware-hostd.exe がアプリケーションエラーとなってしまった。。

Googleで検索した、こんな方法や、サポートページを調べたが、解決しませんでした。

解決方法は、以下でした。

Documents and Settings/All Users/Application Data/VMware/VMware Server/vm-list

を見てみると、次のような感じ。


# This file is automatically generated. 
# Hand-editing this file is not recommended. 
config "C:\Virtual Machines\xxxxx-dev\Other Linux 2.6.x kernel.vmx"
config "C:\Virtual Machines\xxxxx-test\Other Linux 2.6.x kernel.vmx"  </description>
		<link>http://labo.opengroove.com/blog/index.php/2008/10/16/vmware-server-20-%e3%81%a7%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%8c%e3%80%82%e3%80%82/</link>
			</item>
	<item>
		<title>プロキシサーバー pound を使うときに注意すること</title>
		<description>とあるプロジェクトで、オープンソースのプロキシサーバ「pound」を使いました。

その中で、気になったことなどをメモしておきます。

設定は簡単

特にSSLの設定は非常に楽です。
設定ファイルの書き方も明快でわかりやすいのでメンテナンス上も良いです。

バックエンドのWebサーバーはクライアントIPアドレスが変わる

バックエンドではクライアントIPアドレスがプロキシサーバーのアドレスとなるため、バックエンドのウェブサーバー(今回はapache)でログのフォーマットを修正する必要がありました。
X-Forwarded-For にクライアントIPアドレスは渡されるため、Webサーバーではこの値をログするように変更しました。

ログの出力方法によってパフォーマンスに影響がある

Poundのログはdefaultでsyslogに出力することができます。ただ、この設定をするとパフォーマンスが目に見えて悪くなりました。
LogFacilityを - に設定するとログは標準出力なります。
 1. ログ出力なし
 2. 標準出力
 3. syslogに出力
上記の3つの設定では3番の方法で極端にパフォーマンスの低下が見られました。

そのため、今回はPoundのログは標準出力にしました。

クライアントIPアドレスでのフィルタはできない

プロキシサーバーを使う前は、特定のIPアドレスに対してapacheでDenyの設定をしていましたが、この方法は使えなくなりました。
 - iptables で設定
 - アプリケーションで設定

と考えられましたが、今回はアプリケーションに実装する予定です。

設定ファイルのリロードはできない

設定ファイルを書き換えた場合、反映するためにはreload ではなく、 restartが必要となります。(reloadは無い)
今回のシステムでは瞬間的な停止は許容範囲のため、そのまま運用しています。

導入までの手間は非常に少なかったのですが、細かい設定ができないのでした。
 </description>
		<link>http://labo.opengroove.com/blog/index.php/2008/10/15/%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc-pound-%e3%82%92%e4%bd%bf%e3%81%86%e3%81%a8%e3%81%8d%e3%81%ab%e6%b3%a8%e6%84%8f%e3%81%99%e3%82%8b%e3%81%93%e3%81%a8/</link>
			</item>
	<item>
		<title>capistranoで定期処理を管理する</title>
		<description>ウェブサービスを運営していると必ず、「定期的にやるべきこと」ってありますよね。


古くなったログの処理
負荷のかかる処理をバックグラウンドで定期的に
外部データの取得


たいていの場合、手動でやるわけにはいかないので、シェルスクリプトなんかをcronで実行するわけですが、サービスの拡大に伴って、サーバ数が増えた場合、どうするんでしょう?

全てのサーバーにcronを設定すると、全てのサーバーで同じ設定になっていることを確認しなければなりません。
cronの設定自体を自動化すれば、全てのサーバーで同じ設定になっていることが保証されますが。。。

そんなわけで、Ruby on Rails のdeplyツールとして使われているCapistranoを使って、cronをCapistranoサーバーから一括実行することにしてみました。


以下の手順では、ssh接続などの設定は省いています。
(実はこの設定でかなり苦労したところではありますが。。)


1. Capistranoのインストール

gemでインストールします。


> gem install capistrano
> cap --version
Capistrano v2.4.0


2. capfileの作成

capfile はCapistranoの「レシピ」と呼ばれていて、Capistranoが実行するタスクの内容を記述します。Rubyをベースにした独自言語ですが、Rubyを知っている人にとってはほとんど同じです。


role :app, "app-server1", "app-server2"

desc "テスト用のタスク"
task "test_for_cron", :roles => :app do
  run "sh /path/to/cron/script.sh"
end


3. cronの設定

cronの設定時には、-f オプションを使って、capfileの場所を明示的に示しましょう。


> crontab -e
0 12 * * * cap -f /path/to/capfile test_for_cron > /dev/null 2> /var/log/capistrano/error.log


12時になったら、2つのアプリケーションサーバー

app-server1app-server2

でスクリプト /path/to/cron/script.sh が実行されるようになりました。

なお、/path/to/cron/script.sh は各サーバー内に存在する必要があります。
サーバーが増えたら、role に足すだけで、そのサーバーでも実行されることになります。

ただ実行するだけでは面白くないので、実行したらメールを送ります。

4. メール送信用タスクの作成

メールはlocalhost で送りますが、Capistranoっぽく、localhostにリモート接続してみます。
(というか、どこにも接続せずにtaskを実行する方法が分からんだけ？)


desc "cronを実行したらメールを送信"
task "send_email", ...</description>
		<link>http://labo.opengroove.com/blog/index.php/2008/07/18/capistrano%e3%81%a7%e5%ae%9a%e6%9c%9f%e5%87%a6%e7%90%86%e3%82%92%e7%ae%a1%e7%90%86%e3%81%99%e3%82%8b/</link>
			</item>
	<item>
		<title>xenでDomUをvirt-installするときのquoteの問題</title>
		<description>
CentOS 5.1にインストールしたxenでDomUをkickstartを使って自動的に作成する設定をしていたら、その問題が起きました。



>sudo /usr/sbin/virt-install
    --extra-args='ks=http://ks-server/kickstart.php?host=myhost&ip=192.168.1.151&mac=00:00:00:00:01:51'

What is the name of your virtual machine? myhost
 How much RAM should be allocated (in megabytes)? 512
 What would you like to use as the disk (path)? /var/xen/myhost.img
 How large would you like the disk (/var/xen/myhost.img) to be (in gigabytes)? 8
 Would you ...</description>
		<link>http://labo.opengroove.com/blog/index.php/2008/06/02/xen%e3%81%a7domu%e3%82%92virt-install%e3%81%99%e3%82%8b%e3%81%a8%e3%81%8d%e3%81%aequote%e3%81%ae%e5%95%8f%e9%a1%8c/</link>
			</item>
	<item>
		<title>MODxでsnippetを作る</title>
		<description>
MODxのsnippetを使うと、コンテンツを管理、表示するための便利な機能を作ることができます。



snippetはMODx本体と同じように、PHPで書きます。zeera document searchのページで使う、「次のページへ」のリンクを作るsnippetを作りました。


modx オブジェクトの関数


modx オブジェクトはMODxがページを表示するときに必ず作成されるオブジェクトです。
DocumentParserクラスから作られます。DocumentParserクラスはドキュメントを表示する機能を提供するクラスですが、それ以外にも



データベースから任意のドキュメントを取ってくる
ドキュメントのパラメータの取得
プレースホルダーの作成



などのAPIを提供しています。たとえば、次のようなAPIがあります。



getParentIds($id, $height, $parent) : 親ドキュメントのIDをrecursiveに取得
getChildIds($id, $height, $children) : 子ドキュメントのIDをrecursiveに取得
getDocument($id, $fields, $published, $deleted) : ドキュメントを取得してarrayで返します。
getDocuments($id, $fields, $published, $deleted) : $id に一括取得するドキュメントのIDをarrayで指定します。
getActiveChildren($id, $sort, $dir, $fields) : 子ドキュメントを一括取得します。
makeURL($id, $alias, $args, $scheme) : フレンドリーURLを返します。
getPlaceholder($name) : プレースホルダーに設定された値を取得。
setPlaceholder($name, $value) : プレースホルダーを作ります。


snippetの作成


管理画面で、[リソース]->[リソース管理]->[スニペット]->[新規作成]で、snippetを作成します。



今回は[次へ]リンクを作成するためのDocumentPager snippetを作りました。



親IDが同じドキュメントのうち、指定したソート順で次(前)のドキュメントをプレースホルダーにします。



[[DocumentPager? &sortBy='id' &sortDir='ASC' &returnId='xx']]
[+dpPrev+] [+dpNext+]



パラメータ



sortBy: 次、前のドキュメントを探す順番
sortDir: 次、前のドキュメントを探す順番
returnId: 最初と最後のドキュメントで[戻る]リンクの先ドキュメントID



作られるPlaceholder



[+dpPrevId+]: 前のドキュメントのID
[+dpPrevPagetitle+]: 前のドキュメントのページタイトル
[+dpPrevAlias+]: 前のドキュメントのAlias
[+dpPrevLink+]: ...</description>
		<link>http://labo.opengroove.com/blog/index.php/2008/05/19/modx%e3%81%a7snippet%e3%82%92%e4%bd%9c%e3%82%8b/</link>
			</item>
	<item>
		<title>[twcouch] TiddlyWikiをCouchDBに保存する。</title>
		<description>
「TiddlyWiki」はjavascriptをベースにしたWiki形式のパーソナルメモツールです。



よくあるサーバアプリケーション型のWikiツールに比べると、動作が軽快で(文書数が多くなると検索が遅くなりますが。)使いやすいため、メモ帳のようにして使っていました。



サーバアプリケーションとして実装するためのクローンやプラグインも公開されていますが、CouchDBをバックエンドにするアダプターを作ったので公開します。



CouchDBは以前の記事で書きましたが、Erlangで書かれた分散データベースです。
RESTfulなAPIを持つため、クライアントサイドのjavascriptから直接データベースへのCRUDができます。



jQueryとCouchDB用のAdaptertとなる、jqCouchを使っています。



  twcouch: TiddlyWiki + CouchDB



(右リックして保存してください。)


使い方

1. CouchDBの設定


CouchDBのインストールと設定はCouchDBのWikiページを参考にしてください。
CouchDBにデータベースを作成します。データベースのURLは http://yourserver/dbname となるようにWebサーバを設定してください。


2. TiddlyWikiの設定


WebサーバのドキュメントルートにTiddlyWikiをおきます。
http://servername/tiddlywiki.html でアクセス可能なように、htmlファイルの名前を変更しておきましょう。
(ファイル名は好きな名前にしてください。)


3. ライブラリのダウンロード


twcouch.jsで必要なライブラリは次の2つです。

  jQuery
  jqCouch

どちらもjQueryのページからダウンロードできます。


4. twcouch.jsの設定


ダウンロードしたtwcouch.jsの設定を変更します。



[twcouch.js]
config.macros.couchdb = {
    servertype: 'couchdb',
    hostname: 'servername',  &#60;= サーバ名に変更
    dbname: 'database'          &#60;= データベース名に変更
}


5. twcouch.jsのロード


これまでの設定で、ファイルは次のようにおいてあります。



 DocumentRoot
 ...</description>
		<link>http://labo.opengroove.com/blog/index.php/2008/05/07/twcouch-release/</link>
			</item>
	<item>
		<title>ccollect による日々のバックアップ</title>
		<description>ccollect - (pseudo) incremental backup with different exclude lists using hardlinks and rsync

社内の Subversion, Trac, tDiary などを実行しているサーバがあるのですが、これらのデータの世代別バックアップを取るのに ccollect を使っています。

ccollect で特徴的なところは、rsync によりインクリメンタルなバックアップを実行するようになっており shell script で出来ているところです。また、変更のないファイルは hardlink が作成されディスクを消費しないように出来ています。

インストール

現状 ccollect をパッケージにしている Linux distributor はないようなので、ソースからインストールします。まず ccollect のサイトから ccollect-0.7.0.tar.bz2 をダウンロードします。

展開する場所は、ここでは /usr/local/share にインストールすることにします。

$ tar xjf ccollect-0.7.0.tar.bz2 -C /usr/local/share


/usr/local/share/ccollect-0.7.0 に展開されます。

後で役に立つかも知れないので /usr/local/share/ccollect でアクセスできるように symlink を作成しておきます。

$ ln -s ccollect-0.7.0 ...</description>
		<link>http://labo.opengroove.com/blog/index.php/2008/04/28/backup-using-ccollect/</link>
			</item>
	<item>
		<title>MODxのサイトをテスト環境から本番環境へコピーする</title>
		<description>
OpenGrooveの検索アプライアンスサーバ「zeera document search」の製品サイトはMODx CMSを利用して構築しています。

サイトの更新は


    別に用意したテスト環境で更新

    更新に問題がないか社内でチェック
    本番環境に更新分を反映


という手順でやっているのですが、#3の反映作業は手作業にすると、手間がかかり、反映漏れが出るもとになります。

そこで、ssh, rsync, mysqldumpを使って、#3の手順を自動化し、更新分を確実に反映することにしました。

1. 反映の方法

自動化の方法の概要を簡単に説明すると以下の通りです。

- rsyncでディレクトリの同期

MODx CMSは、


   top --- manager
        +- assets

というディレクトリ構造をしていて、assetsにテンプレート,CSS,imageなどが保存されています。
逆にmanagerにはMODxのコアスクリプトと設定ファイルがあります。
そのため、assetsをrsyncで同期することにします。

- データベースの更新

MODx CMSはMySQLでデータを保存しています。
環境依存なデータはsite_settingsテーブルに集約されているため、このテーブル以外をコピーします。

- サーバ間の接続はSSHを使用する

自動化するためにパスフレーズなしの鍵をつくり、自動接続して本番環境にデータを転送します。

2. サーバの設定

自動化のためにテストサーバから本番サーバにSSHで接続するための環境を作ります。

- 鍵の作成

テストサーバで鍵を作成します。


&#62; ssh-keygen -t rsa


パスフレーズを聞かれますが、入力せずにリターンキーを押し、パスフレーズなしで作成します。
出来上がった公開鍵は本番サーバに転送し、/home/[user]/.ssh/authorized_keysに入れておきます。

3. データベースの更新の設定

mysqldumpでテスト環境のデータベースをdumpして、本番環境にdumpデータを反映します。

まず、テスト環境のデータをコピーし、本番環境に反映するためのSQL文のファイルを生成するシェルスクリプトを用意します。

[dump_modx_data.sh]


#!/bin/bash
work_dir=/home/user/xxxxx
filename=dumpfile.dump
file_path=$work_dir$filename

echo "" &#62; $file_path

# データを削除するSQL文をファイルに書き込み
echo "TRUNCATE TABLE ...</description>
		<link>http://labo.opengroove.com/blog/index.php/2008/04/21/modx%e3%81%a7staging%e7%92%b0%e5%a2%83%e3%81%8b%e3%82%89production%e7%92%b0%e5%a2%83%e3%81%b8/</link>
			</item>
</channel>
</rss>
