nginx の後ろで thin を unix socket で動かす

Railsを起動するとき、いつもPoundの後ろで複数ポートで振り分けっていうのをよくやっていたのだけど、unix socket で nginx の後ろで thin を動かすと早いらしいとのことで、試してみた。

環境はOSX

thinのインストール

$ sudo gem install thin
$ sudo gem install eventmachine --source http://code.macournoyer.com

2行目は、thinをsocket指定して動かす時に eventmachin の 0.11.0 以上が必要とのことで、OSXでデフォルトで入らなかったので入れた。

インストールはこれで完了。

nginxのインストール

Portで入るのが 0.5.1 ?とかで、ちょっと古かったので公式サイト(http://nginx.net/)から現時点で安定版の 0.6.31を取得してインストール

$ wget http://sysoev.ru/nginx/nginx-0.6.31.tar.gz
$ tar xvzf nginx-0.6.31
$ cd nginx-0.6.31
$ ./configure --prefix=/usr/local
$ make
# make install

で、無事インストールが終わるはず。configure で pcre チェックされてたので、 pcre とか入ってない場合はいれたほうがよさげ。VirtualHostの設定するときに使われるのかな?

nginxの設定

configure のオプションで –prefix=/usr/local とした場合、設定ファイルは /usr/local/conf/nginx.conf に生成されていて、デフォルトでこれを読みに行きます。

編集します。最低限の設定だけ。

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
 
    sendfile        on;
    keepalive_timeout  0;
 
    upstream backend {
        server unix:/tmp/thin.0.sock;
        server unix:/tmp/thin.1.sock;
        server unix:/tmp/thin.2.sock;
        server unix:/tmp/thin.3.sock;
    }
 
    server {
        listen       80;
        location / {
            proxy_pass http://backend;
 
        }
    }
}

これで、80番ポートにきたものを、unix socket の /tmp/thin.[0-3].sock で動いてる何かに転送出来るようになりました。

以下のように、-t をつけて設定ファイルの文法チェックをします。OKなら以下のようなメッセージが出ました。

$ sudo /usr/local/sbin/nginx -t
2008/06/25 01:05:12 [info] 14511#0: the configuration file /usr/local/conf/nginx.conf syntax is ok
2008/06/25 01:05:12 [info] 14511#0: the configuration file /usr/local/conf/nginx.conf was tested successfully

thinの設定(起動)

Rails でしか使ったことないので、以下 Rails アプリのディレクトリ直下で叩いてくだしあ。コマンドに引数渡すだけだけど、先ほど nginx.conf で指定した unix socket で動かす。

* s は サーバ4つで、–socket で /tmp/thin.sock とするとサーバの数だけ /tmp/thin.n.sock が出来るようだ。

$ thin start -s 4 --socket /tmp/thin.sock

nginxの起動

以下のコマンドで起動します。ぼくの環境だと、何も標準出力されずに起動しました。起動したら lsof -i:80 とかして80番で立ち上がってることを確認します。

$ sudo /usr/local/sbin/nginx

これで動いてるようだ。

この状態で、裏を切ってみる。Rails だと、thin の pid ファイルが tmp/pids/ 以下に出来ますんで、今 /tmp/thin.[0-2].sock で動いてるところを切ってみます。

$ kill cat `tmp/pids/thin.0.pid`
$ kill cat `tmp/pids/thin.1.pid`
$ kill cat `tmp/pids/thin.2.pid`

これで3だけが動いてる状態になりましたが、正常につながっているようです。ちゃんと振分けられてるみたいですねー。

Pound に比べていいなって思うところが、バックエンドが落ちたときの挙動です。Pound は Alive で指定した秒数でポーリングでバックエンドを死活監視をしてるみたいなので、後ろが落ちちゃったあと次のポーリングまではエラー画面が出てしまいます。

nginx で今回試してみた感じ、後ろが落ちても前にエラーが表示されることはないみたい?全部落ちると、もちろんエラー画面が出ますけど。

参考URL: http://wiki.codemongers.com/Main (nginx の wiki)

中国行ってるとき、家のサーバ落ちたら終わりかと(‘A`)

nginx の後ろで thin を unix socket で動かす

薔薇空間

 土曜日、渋谷のBunkamura で開催されていた薔薇空間へ行ってきた。薔薇ってこんなに種類あるんだ?てくらいたくさんの薔薇の絵を見ることが出来ます。

 薔薇はあまりその辺じゃ見かけないけど、生活の中には「薔薇」という花は綺麗なものっていう位置づけで結構存在してると思います。その辺にありふれた花じゃないからこそなのかも。

 絵を見ると、ひとくちに薔薇と行っても全然違う花に見えるものもあって新鮮です。植物の絵って小学生のときと大学の実験くらいでしか書いたことないけれど、ずっと薔薇の絵を書き続ける情熱っていうのはすごい。

 薔薇といったら棘みたいなイメージが強いんですが、その辺も含めて緻密に描かれているので足を運ぶと薔薇の美しさを再認識できるかも。

 薔薇と行ったら、MALICE MIZER の薔薇の聖堂が頭に浮かんでCD をiMacに入れたものの、認識されず取り出しも出来なくなったね(‘A`) 再起動しないととれないか… iMacカコイイんだが、困ったものだ。

薔薇空間

芸術都市パリの100年展

先々週の日曜日、芸術都市パリの100年展 へ行ってみた。「一滴の水のための一滴の涙」っていう絵にかなり魅入ってしまいました。水を持った女性が怖いくらい綺麗というか、怖すぎて綺麗なのか。

色々な絵が楽しめるんですが、昔の人は絵画、詩、戯曲、政治など様々な分野に渡って有名な人が多くてすごいなって思います。今でもそういう人はいるけれど、昔は今よりきっと何をするにも気軽にっていう風ではなかったんじゃないかなと思うとなおさら。

それよか、今みたいにTVやラジオやネットなどで情報が急速に広まるような世の中でなくても、評価される人はされて有名になるんだなーっていうことが面白いと思います。

ボードレールって名前しか知らなかったけど、さわりだけでも知ってみようかなと思います。

この展覧会は上野の東京都美術館だったんだけど、上野は美術館がたくさんあってあと動物園もあってゆっくり行きたいなーと思ってます。家から近いのに今まで全然行ってなかったよ。

芸術都市パリの100年展

Macでzshを使ってみようと思った

 Macでzshを使ってみた。漢のzsh っていうのを参考に設定してみた。

 まず、デフォルトのログインシェルを変更する。

 システム環境設定 -> アカウント -> 自分のアカウントで Ctrl + Click -> 詳細オプション -> ログインシェルを /bin/zsh

 とすればおk。

 上記URLをもとに設定ファイルを書いてみたけど、よく分かってない。デフォで Bash の Ctrl + R みたいな感じな設定なんだけど、慣れたら速そう。慣れるまでストレスになりそう。

autoload colors
colors
case ${UID} in
0)
  PROMPT="%B%{${fg[red]}%}%/#%{${reset_color}%}%b "
  PROMPT2="%B%{${fg[red]}%}%_#%{${reset_color}%}%b "
  SPROMPT="%B%{${fg[red]}%}%r is correct? [n,y,a,e]:%{${reset_color}%}%b "
  [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] &&
    PROMPT="%{${fg[white]}%}${HOST%%.*} ${PROMPT}"
  ;;
*)
  PROMPT="%{${fg[red]}%}%/%%%{${reset_color}%} "
  PROMPT2="%{${fg[red]}%}%_%%%{${reset_color}%} "
  SPROMPT="%{${fg[red]}%}%r is correct? [n,y,a,e]:%{${reset_color}%} "
  [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] &&
    PROMPT="%{${fg[white]}%}${HOST%%.*} ${PROMPT}"
  ;;
esac
 
 
export LSCOLORS=gxfxcxdxbxegedabagacad
alias ls='ls -G'
zstyle ':completion:*' list-colors ${(s.:.)LSCOLORS}
autoload -U compinit
compinit
PROMPT="%/%% "
PROMPT2="%_%% "
SPROMPT="%r is correct? [n,y,a,e]: "
 
 
case "${TERM}" in
kterm*|xterm)
  precmd() {
    echo -ne "\033]0;${USER}@${HOST%%.*}:${PWD}\007"
  }
  ;;
esac
 
# 履歴を10000件保存する
HISTFILE=~/.zsh_history
HISTSIZE=10000
SAVEHIST=10000
setopt hist_ignore_dups     # ignore duplication command history list
setopt share_history        # share command history data
 
# viのキーバインドになる
bindkey -v
 
# 履歴検索 Ctrl+P, Ctrl+N でたどれる
autoload history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^P" history-beginning-search-backward-end
bindkey "^N" history-beginning-search-forward-end
 
# cd が pushd になる
setopt auto_pushd
 
# 自動補完設定
autoload predict-on
predict-on
 
# alias設定
Macでzshを使ってみようと思った

サーバ復旧しますた

 サーバが3日くらいダウンしてました。ネットワークがおかしくなったのが原因だけど、どうやらPCIが一個だめになったてしまった模様。3枚のLANカードを3個のPCIスロットにさして見てみたけど、今まで使ってたとこが使えなくなってしまってるようだ。

 マザーボードが初代A7V なので、もう8年前のM/Bです。はじめて自作したときに買ったマザーを未だに使ってます。

 今日は薔薇空間に行ってみようと。

サーバ復旧しますた

ActiveScaffoldのまとめ

 Rails で ActiveScaffold を使用するときに知っておくと良い事。

インストール

git clone git://github.com/activescaffold/active_scaffold.git vendor/plugins/active_scaffold && rm -rf vendor/plugins/active_scaffold/.git

日本語化

script/plugin install http://svn2.assembla.com/svn/activescaffold_japanese_l10n

基本設定

class Admin::UserController < Admin::AdminController
  active_scaffold :user do |config|
    config.label = 'ユーザ管理' # 一番左上に出る見出しの文字列を設定
 
    # 各列の名称を設定する。一覧、作成画面などで表示される
    config.columns[:name].label = 'なまえ'
    config.columns[:email].label = 'メールアドレス'
 
    # 作成画面で表示する列を指定する(全部指定する形式)
    config.create.columns = [:name, :created_at]
 
    # 一覧画面で表示する列を指定する(取り除く形式)
    config.list.columns.exclude :updated_at
 
    # 編集画面で表示する列を指定する(追加する形式)
    config.edit.columns << :telephone
  end
end

belongs_to の入力形式をセレクトボックスにしたい

デフォルトだと、belongs_to の入力がその場で入力して変更出来るようなUIになってる。これを、セレクトボックスのみにする方法。例えば、 User belongs_to Company というときは以下のようにする。

active_scaffold :user do |config|
  config.columns[:company].form_ui = :select
  ...
end

公式サイトのQ&Aかなんかに、 ui_type = :select としなさいって書いてあるけど、ActiveScaffold 2.0 から ui_type は消えて form_ui になるのでこっちを使ってね。っていう警告が出るよ。

active scaffoldのform_ui に一覧を載せている方がいました。

:calendar
カレンダーで日付入力。calendarプラグインが必要
:checkbox
チェックボックス
:country
国名。optionsに:priorityを設定できる
:password
パスワード入力用のテキストフィールド
:textarea
テキストボックス。optionsでサイズ(:cols,:rows)を指定できる
:usa_state
アメリカの州名リスト。optionsで:priorityを設定できる
:select
プルダウンの選択リスト。optionsで選択肢を設定できる[[‘男’, ‘male’], [‘女’, ‘female’]]みたいな
:crud
デフォルト

表示をカスタマイズしたい

表示をカスタマイズする方法は何通りかある。

  • 1. モデルにインスタンスメソッドを定義
  • 2. ヘルパメソッドをオーバーライド
1. モデルにインスタンスメソッドを定義

例えば、名前と年齢を同じ表示項目にして 「ちゅう(23歳)」 のような表示にしたい時、モデルにメソッドを追加します。

class User < ActiveRecord::Base
  # なまえ(年齢) という形式で文字列を返す。
  def name_with_age
    "#{self.name}(#{self.email}歳)"
  end
  ...
end

ただ、これを定義しただけでは ActiveScaffold が列を拾ってくれないので設定で追加します。今回は、name_with_age= のメソッドは定義していないので表示系のみで出す形になります。例えば、一覧画面に出すときは以下の様にします。

active_scaffold do |config|
  config.list.columns < < :name_with_age
  config.columns[:name_with_age] = 'なまえ(年齢)'
end

全部の操作に追加したいときは、以下の様にすると全部に適用出来ます。

active_scaffold do |config|
  config.columns < < :name_with_age
end
2. ヘルパメソッドをオーバーライド

ActiveScaffold が、 #{column_name}_column というヘルパメソッドを作っているようなので、これを自分でオーバーライドしてあげればいいみたい。 例えば、 メールアドレスに mailto: のリンクをつけたいときは以下のようにすればいい。モデル : User, コントローラ : Admin::UserController のとき、オーバーライドを定義するヘルパは Admin::UserHelper になる。メールアドレスは email とする。

module Admin::UserHelper
  # リンク付きメールアドレス
  def email_column(record)
    link_to record.email, "mailto:#{record.email}"
  end
end

record は、Userクラスのインスタンスが入ります。

フォームをカスタマイズしたい

  • 1. ヘルパメソッドをオーバーライド
  • 2. パーシャルでオーバーライド
1. ヘルパメソッドをオーバーライド

各フォームは、 #{column_name}_form_column というヘルパメソッドでオーバーライド出来ます。例えば、User.name の入力フィールドを変更するときは以下の様にすればいけます。:size を 10 にしただけだけど、ちゃんと変わってるのが分かるはず。

module Admin::UserHelper
  def name_form_column(record, input_name)
    text_field :record, :name, :size => 10
  end
end

引数にある input_name には、上記だと record[name] という文字列が入っています。ActiveScaffold が吐き出すHTMLを見ると、Rails の Scaffold 的な user[name] ではなく、 record[name] となっています。なので、上のコードは、下と同義です。

module Admin::UserHelper
  def name_form_column(record, input_name)
    text_field :record, :name, :size => 10, :name => input_name
  end
end

変更したければ変えるっていうことなのかな。

ただ、これで変更してしまうとActiveScaffold デフォルトの CSS を適用してるときはフォームの枠がなくなって残念な気分になるので、例えば text_field ならば次のDOMクラスを足してあげると良いです。'term-input text-input'

結局、こんな感じになる。

def name_form_column(record, input_name)
  text_field :record, :name, :size => 10, :class => 'term-input text-input'
end

統一させるなら、同様の形式のフォームのクラスを firebug などで見て真似すればよいかと。

2. パーシャルでオーバーライド

form の1要素 + label を partial ファイルに書くとオーバーライド出来る。

Admin::UserController に該当する view ファイルが置かれるべきディレクトリ app/views/admin/user/ に、 _#{column_name}_form_column.rhtml という partial ファイルを置けばよい。

<label>なまえ!</label>
< %= text_field :record, :name, :size => 10 %>

上記のようなファイルを作ると、入力フォームのなまえ入力の部分が置き換わる。ただ、上記だと他の部分と DOM 構造が違って CSS が効かなくて残念な表示になる。やはり他と統一するなら真似てある程度コピーコピーで。

日本語化する

active_scaffold_localization.rb の記事を見ると分かります、

あと調べること

nested
関連するレコードをその場で表示,編集出来るような設定を行える。
search
検索系全体的に調べる。
map.resources :user, :active_scaffold => true
今知った。Flex でごにょごにょ
ActiveScaffoldのまとめ