capistranoで特定のコミットまでをデプロイ
デプロイして、なんかわかんないけど挙動が変でとりあえず前のバージョンに戻したいなってときがあったんですが、capistranoはもちろん対応していました。
cap -S revision=XXXXXXXXXX production deploy
あんまり使わないけど一応メモ。
rvmからrbenvへ乗り換えにちょっと苦労した
まずは rbenvと必要なものをインストール。このころはさくっと終わると思っていました。。
brew install rbenv ruby-build rbenv-gem-rehash readline
で、rubyをinstallしようとしたが失敗。
takayukishimizu-no-MacBook-Pro:trabby takayuki$ rbenv install 2.0.0-rc2 Downloading ruby-2.0.0-rc2.tar.gz... -> http://dqw8nmjcqpjn7.cloudfront.net/9d5e6f26db7c8c3ddefc81fdb19bd41a Installing ruby-2.0.0-rc2... BUILD FAILED Inspect or clean up the working tree at /var/folders/7z/5nqy88hd35j8q35jkt3hgbsh0000gn/T/ruby-build.20131210192317.25684 Results logged to /var/folders/7z/5nqy88hd35j8q35jkt3hgbsh0000gn/T/ruby-build.20131210192317.25684.log Last 10 log lines: installing default gems: /Users/takayuki/.rbenv/versions/2.0.0-rc2/lib/ruby/gems/2.0.0 (build_info, cache, doc, gems, specifications) bigdecimal 1.1.0 io-console 0.4.1 json 1.7.5 minitest 4.3.2 psych 2.0.0 rake 0.9.6 rdoc 4.0.0.rc.2.1 test-unit 2.0.0.0 The Ruby openssl extension was not compiled. Missing the OpenSSL lib?
http://nick.hateblo.jp/entry/2013/06/12/232300 をみて足りないものを入れる
brew install openssl
そしたらまたエラー
curl: (7) couldn't connect to host Error: Download failed: http://openssl.org/source/openssl-1.0.1e.tar.gz
ぐぐるとこれがでてきたので、FIX: Error: Download failed: http://openssl.org/source/openssl... https://gist.github.com/devinbrown/5073115
brew edit openssl
してmirrorサイトに切り替える。
require 'formula' class Openssl < Formula homepage 'http://openssl.org' url 'http://mirrors.ibiblio.org/openssl/source/openssl-1.0.1e.tar.gz' ...
でもういっちょトライ。
brew install openssl
イケタ! ので再チャレンジ!
rbenv install 2.0.0-rc2
・・・\(^o^)/
さっきと同じエラー・・・ あ、よく記事をみると依存ライブラリを指定するらしい。
RUBY_CONFIGURE_OPTS="--with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl`" rbenv install 2.0.0-rc2
・・・・(´・ω・`)・・・・
いけた!
この状態だとsystemのrubyが使われるので、いれたrubyをデフォルトに指定。
rbenv global 2.0.0-rc2
rvmのuninstallは切腹と打てばいいそう。
rvm seppuku
bash_profileにあったrvmの記述も忘れずに消す。
全部gemがなくなっちゃったみたいだから地道にいれなおす。
$ bundle install Fetching source index from https://rubygems.org/ Could not verify the SSL certificate for https://rubygems.org/. There is a chance you are experiencing a man-in-the-middle attack, but most likely your system doesn't have the CA certificates needed for verification. For information about OpenSSL certificates, see bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile sources and change 'https' to 'http'.
また怒られました(´・ω・`)
またググると Installing Ruby 2.0 - Benjamin Curtis http://www.bencurtis.com/2013/08/installing-ruby-2-dot-0/ とあって、たしかにssl入れた時にcurl-ca-bundle入れろよって言われてスルーしてたなと反省しつつ
$ brew install curl-ca-bundle
~/.bash_profileに追記
$ export SSL_CERT_FILE=/usr/local/opt/curl-ca-bundle/share/ca-bundle.crt
したあとbundle install するとやっと成功。
SSL_connect returned=1 errno=0 state=SSLv3 read server key exchange B: bad ecpoint
とコケていたのも解決されました。
mongoDB用のO/RMapperにMongoidを使う
fluentdで吐いたデータをmongoDB用のormを使って扱いたいので準備をしていきます。
ORMは
- Mongoid: Home http://mongoid.org/en/mongoid/index.html
- MongoMapper http://mongomapper.com/
あたりがメジャーらしいですが、MongoManagerは以前使ったことある&検索してみるとMongoidのほうが記事数が多い&ドキュメントが豊富、ということでMongoidを使ってみることにします。
rails+mongoidセットアップ
2,3ステップで済んだのでとても簡単でした。
- gemのインストール
- 設定ファイルconfig/mongoid.ymlを作成
- (デフォルトのORMをactive recordに戻す)
まずはgemを追加.
#ORMapper for mongodb gem 'mongoid' gem 'bson_ext'
install.
bundle install
で、コマンドでmongoid用の設定ファイルを作ろうとしたら、エラー(ヽ'ω`)
i$ rails generate mongoid:config /Users/takayuki/.rvm/gems/ruby-1.9.3-p385/gems/kaminari-0.14.1/lib/kaminari/models/mongoid_extension.rb:24:in `block in <module:Document>': undefined method `scope' for Mongoid::Document:Module (NoMethodError) ・・・
undefined method `scope' for Mongoid::Document:Module · Issue #415 · amatsuda/kaminari によると「rails4に対応してるこっち使いなYO!」ということなのでGemfileのmongoidのところを書き換えて、入れなおす。
gem 'mongoid', '~> 4', github: 'mongoid/mongoid'
次は問題なくコマンド通りました。
$ rails generate mongoid:config create config/mongoid.yml
mongoidはデフォルトのormであるactive recordを置き換えてる形になっているのですが、今回はログ用にサブで使うので、デフォルトをactive recordに戻します.
config/application.rb:
config.generators do |g| g.orm :active_record end
これでmongo generate model hogeとしたときは、activerecordのモデルが今まで通りできます。 mondoidのmodelを作りたいときは
$ rails generate mongoid:model
とすればOK。
あと参考にさせていただいた RailsでActiveRecordとMongoidの共存のさせ方 - Qiita [キータ] によるとclassのロードがデフォだとmodels以下すべてになってしまうそうなので、逐次設定します。 アナログ設定になりますが、自分のケースだとそこまでmodel数も増えないだろうからそんな手間にはならなそうです。
これであとはもうコマンドでmodelを逐次追加するだけ!
fluentd+rails+mongoでサクッとログ環境を整備してみる
今更さわりだしたfluentdですが、簡単に導入まわりをまとめておきます。 rails上でない場合はライブラリは変わりますが、やることはほとんど同じだと思います。
fluentd+railsを動かすまでの手順
fluentd+railsを最短で確認するためは以下のステップが必要です。
- fluentd or td-agentのinstall
- gemfileにtd-loggerを追加してbundle install
- td-loggerの設定ファイル追加
- fluentdサーバーの設定ファイルを作成(fluentd.conf)
- fluentdサーバーを起動
- ログをアプリケーションコードに仕込んでアクセス
- ログがfluentdサーバーから出力されているのを確認
そのあとおまけでmongoDBに出力するところまでやってみます。
実際やってみる
macへfluentdをインストール
gem install fluentd
注:linuxの場合はyumで入れる /etc/yum.repos.d/td.repo
[treasuredata] name=TreasureData baseurl=http://packages.treasure-data.com/redhat/$basearch gpgcheck=0 $ yum update $ yum install td-agent
Gemfleに追加
gem 'td-logger'
gemをインストール
bundle install
送り側となるtd-loggerの設定ファイルをconfig/treasure_data.ymlに作成。ここでどこのfluentdサーバーに送るか定義します。今回は受け側もlocalhostなので以下のようになります。 trpとなってるところはプロジェクトネームなどをおいて下さい。
development: agent: localhost:24224 tag: trp debug_mode: true # enable debug mode production: agent: localhost:24224 tag: trp test:
プロジェクトのルートにfluentdの設定ファイルを作る。
mkdir fluentd vim fluentd/fluentd.conf
とりあえず出力してみる。 fluentd/fluentd.conf
<source> #setting for sending type forward port 24224 </source> <match trp.**> #setting for receiving type stdout </match>
fluentdを起動させましょう。
fluentd -c fluentd/fluentd.conf 2013-11-14 15:30:34 +0900 [info]: starting fluentd-0.10.33 2013-11-14 15:30:34 +0900 [info]: reading config file path="fluentd/fluentd.conf" 2013-11-14 15:30:34 +0900 [info]: using configuration file: <ROOT> <source> type forward port 24224 </source> <match trp.**> type stdout </match> </ROOT> 2013-11-14 15:30:34 +0900 [info]: adding source type="forward" 2013-11-14 15:30:34 +0900 [info]: adding match pattern="trp.**" type="stdout" 2013-11-14 15:30:34 +0900 [info]: listening fluent socket on 0.0.0.0:24224
ちゃんと動くか任意の場所に以下を追加してアクセスしてみます。
TD.event.post('test', {:foo=>:bar})
rails sでサーバーを起動して、アクセスしてみると、先ほどのfluentdのconsole画面に
2013-11-14 15:37:23 +0900 trp.test: {"foo":"bar"}
と出力されます。 シンプルですがこれでinput/outputを確認できました。
ついでに向け先をmongoDBにしてみます。
まずはローカルのmongoを起動させます。
$ /usr/local/bin/mongod all output going to: /usr/local/var/log/mongodb/mongo.log
mongoの様子を見たいときは上記のlogをtail -fすればいいですね。
受け側の定義を変えて、typeをmongoにするだけ。
<source> type forward port 24224 </source> <match trp.access> type mongo # output type database trp # db name collection access # table name # Following attibutes are optional host localhost port 27017 </match>
ログもtable名をaccessに変更します。
TD.event.post('access', {:foo=>:bar})
アクセスが終わったらmongo shellで確認。
$ mongo > use trp switched to db trp > db.access.find() { "_id" : ObjectId("5284760e8b5f352e17000001"), "foo" : "bar", "time" : ISODate("2013-11-14T07:04:03Z") }
mongoにfoo => barが記録されていることを確認!
mongoに入ったログはオブジェクトとして扱えるようになるので集計が楽になりますし、カラムを自由に変更できたり、気軽にログを追加できるメリットもあります。
自由度が高い分、カラムやテーブルを自由気ままに作ってしまうといざほしいデータを整形するときにいろいろメンドくさかったので、ある程度そのログをどう集計するか、なにに使うかを予め決めてから使うと良いと思います。その辺はまたの機会に。
参考:
treasure-data/td-logger-ruby https://github.com/treasure-data/td-logger-ruby
cohakim's blog » Railsからfluentdにイベントログを出力する(開発環境編) http://blog.yabasoft.biz/archives/4401
chef soloの基本コマンド
vagrantつかってvirtualbox上でchefの勉強中。抵抗あったけど整理すれば思ったより複雑じゃないかも。 とりあえず主要なコマンドたちを。
公式サイトはこちら。
All about Chef ... — Chef Docs
chef用のrepoを作る
knife solo init chef-repo
こんなディレクトリ構成が作られます。
├── cookbooks(オープンソースからとってきたもの) ├── data_bags ├── environments ├── nodes │ └── hostname.json ├── roles └── site-cookbooks(自分のサイト用に変更したもの)
ここでいろいろ作業していきます。
対象のnode(server)をchef対応にする。
chefで環境を作る前に、まずサーバーにchefを入れます。
knife solo prepare hostname
cookbookを反映する
chef-repoに移動して
knife solo cook hostname
あとは
cookbookを作る
- knife cookbook create cookbookname -o site-cookbooks/
node/hostname.jsonに使うcookbookを追加する。
- site-cookbooks以下にあるcookbookを編集する。
- cookbookを反映する
をぐるぐると回りながらカスタマイズしていく感じのようです。recipeの書き方はdocsを見て別途勉強が必要。
Bufferクラスから16進数の文字列を取り出す
APNs=Apple Push Notification serviceを叩いてたら、エラーのコールバックでBufferクラスなるものでtoken が帰ってきた。無知すぎるのでggり、もとのtokenの文字列にしたいんだけど
var token = notification.device['token'] console.log(token.toString('utf8', 0, token.length));
とやったらめっちゃ文字化けしてたのでおかしいな~と思ったら
はじめてのNode.js:Node.js内でバイナリデータを扱うための「Buffer」クラス | SourceForge.JP Magazine
にあるようにutf8じゃなくてhexでとれってさ。
var token = notification.device['token'] console.log(token.toString('hex', 0, token.length));
すると 3fa1327c1e25b58dc351c110d1b55a613168cd6b91a7b911e47ef88ce3XXXXXX みたいな文字列になってちゃんと取れました。
nodeでAPIサーバーをつくろうとおもった時のメモ
nodeでシンプルなAPIサーバーはどう作るのが( ・∀・)イイ!!んだろう
ってことでとりあえず2つの方法でやってみました。 とりあえずAPIインターフェースをどう作るかが目的なので、RESTful*かどうかは置いときます。
*RESTfulなAPIって?→連載:ASP.NET Web API 入門:第2回 RESTfulなAPIの設計を学ぼう (2/2) - @IT
今回の選択肢
- compoundJS
- express-resource
WAFとライブラリなので比較する話じゃないですが(そもそもcompoundJSはexpressベースだし)、APIでググって引っかかった2つをチョイス。Tower.js とかもほぼcompoundJSと同じ方向性なので省略。
compoundJSでAPI作ってみる
まずはnpmでinstall.
$ sudo npm install compound -g
プロジェクト作成。
$ compound init api_sample && cd api_sample
package.jsonの内容をinstall.
$ sudo npm install -l
controllerを作成
$ compound g controller test index
routes.jsに/test/indexを追加。
exports.routes = function (map) { map.get("/test/index", "test#index"); map.all(':controller/:action'); map.all(':controller/:action/:id'); };
test_controllerを若干編集。
load('application'); action('index', function () { send({ status : 200, title: "test#index" }); });
サーバーを起動。
$ compound server
以下のようなjsonレスポンスが取れます。
{ status : 200, title: "test#index" }
express-resouceでAPI作ってみる
とりあえずinstall.
$ sudo npm install express-resource
expressが入ってない人はこちらも.
$ sudo npm install -g express
プロジェクト作るよ。
$ express api_test
package.jsonにexpress-resourceを追加して
$ sudo npm install
routes/user.jsを下記のように書き換え。 express-resourceは
express-resource provides resourceful routing to express
とあるようにREST APIのルーティングを提供してくれるもの。
module.exports = { index: function(req, res){ res.send("index: called as GET method"); } ,new: function(req, res){ res.send("new: called as GET method"); } ,create: function(req, res){ res.send("create: called as POST method"); } ,show: function(req, res){ res.send("show: called as GET method"); } ,edit: function(req, res){ res.send("edit: called as GET method"); } ,update: function(req, res){ res.send("update: called as PUT method"); } ,destroy: function(req, res){ res.send("destroy: called as DELETE method"); } };
app.jsを編集してroutingを変更します。
app.get('/', routes.index); //app.get('/users', user.list); app.resource('users', require('./routes/user'), { id: 'id' });
node app.jsをしてサーバーをたてたら、http://localhost:3000/usersにアクセス。「index: called as GET method」というレスポンスが帰ってきました。
jsonで返すようにするには、routes/user.jsでindexのところを
res.json({ "status": 200 });
と変更すれば、
{ status: 200 }
と帰ってきました。 その他にもjson、xmlなどのフォーマットの出し分けをスマートにかけたりするそう。
まとめ
apiをサクッと作るのであればcompoundJSでやろうかなーと思いました。
ormとしてSequelize ∴ A multi-dialect Object-Relational-Mapper for Node.JSというのがあってそれを使うとMVCそろってexpress でも書きやすくなりそうなのでそこまでやって比較かなーと思うけど、compoundJSに入ってるjugglingdbで問題なさそうなので,そのあたりはまたの機会に。
compoundJSはもろもろ入ってるexpressベースのようなのだがブラックボックスなところ多いのでソースを読んでみようと思う。
参考
- node.jsでSequelizeを使うための準備/前編 | Inhale n' Exhale http://h2plus.biz/hiromitsu/entry/631
- CompoundJS http://compoundjs.com/docs.html