君に友だちはいらない

君に友だちはいらない

君に友だちはいらない

誕生日プレゼントでもらったこの本を読み終わりました。

要は「同じ目的をもった仲間を作りましょう」って話でした。

たしかに、ダラダラ話すための友達が一杯いても、 飲み会して終わりなので、金がかかるだけです。

なにかを成し遂げるための友達は、一緒に活動を行うことで 研ぎすまされますし、プロジェクトが終ってから何年かぶりにあっても、 なんだか久々に会った感じもしないし、現状を聞いていて楽しいです。

最後の方の著者の燃え上がりっぷりがとても良いので、 是非多くの人に読んでみてほしいです。

vagrantのawsプラグイン入れようとして積んだ

やりたいこと

vagrantでEC2を使ってみたいなと思っていた。

vagrant plugin install vagrant-aws

でインストールしようとしたけど、インストールできなかった。

答え

NOKOGIRI_USE_SYSTEM_LIBRARIES=1 vagrant plugin install vagrant-aws

経緯

先週、vagrantaws立ち上げたくて、諸々いじってたんだけど、

vagrant plugin install vagratn-aws

が通らなくてあきらめてた。こんな感じでnokogiriのインストールエラーね。

Building nokogiri using packaged libraries.
Building libxml2-2.8.0 for nokogiri with the following patches applied:
        - 0001-Fix-parser-local-buffers-size-problems.patch
        - 0002-Fix-entities-local-buffers-size-problems.patch
        - 0003-Fix-an-error-in-previous-commit.patch
        - 0004-Fix-potential-out-of-bound-access.patch
        - 0005-Detect-excessive-entities-expansion-upon-replacement.patch
        - 0006-Do-not-fetch-external-parsed-entities.patch
        - 0007-Enforce-XML_PARSER_EOF-state-handling-through-the-pa.patch
        - 0008-Improve-handling-of-xmlStopParser.patch
        - 0009-Fix-a-couple-of-return-without-value.patch
        - 0010-Keep-non-significant-blanks-node-in-HTML-parser.patch
        - 0011-Do-not-fetch-external-parameter-entities.patch
************************************************************************
IMPORTANT!  Nokogiri builds and uses a packaged version of libxml2.

If this is a concern for you and you want to use the system library
instead, abort this installation process and reinstall nokogiri as
follows:

    gem install nokogiri -- --use-system-libraries

If you are using Bundler, tell it to use the option:

    bundle config build.nokogiri --use-system-libraries
    bundle install

However, note that nokogiri does not necessarily support all versions
of libxml2.

For example, libxml2-2.9.0 and higher are currently known to be broken
and thus unsupported by nokogiri, due to compatibility problems and
XPath optimization bugs.
************************************************************************
Bundler, the underlying system Vagrant uses to install plugins,
reported an error. The error is shown below. These errors are usually
caused by misconfigured plugin installations or transient network
issues. The error from Bundler is:

An error occurred while installing nokogiri (1.6.2.1), and Bundler cannot continue.
Make sure that `gem install nokogiri -v '1.6.2.1'` succeeds before bundling.

まーいろいろやったんですが、さっぱり上手く行かない。vagrantvagrantでgemも閉じてるから、よくわからないなーっと。

そんで、色々ググると大抵、stackoverflowにあたるわけで、askは見つかったんですが、 まだ、だれも answerしてなくてうろたえて、一旦あきらめて、週末あけてみると、stackoverflowを見たと同僚が教えてくれました。

同僚のブログ

そして、stackoverflow

ちゃんとanswerされてる。すごいなstackoverflow

最近読んだ本

読んだ本はメモ代わりにブログに書いておこうと思ったんだが、最近忘れてるのでまた書き始めようと思う。取り敢えずはメモだけ

capistrano + unicornではまった。

以外と語られていないような気がするんだが、railscapistranounicornをつかっていると、思わぬ落とし穴がある。

今まで順調だったcapistranoでのデプロイでunicornの立ち上げが失敗するようになる。 unicornのupgrade(SIGUSR2)がきかなくなった。

upgradeってのは、gracefulなんだけど、

/usr/local/rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/bundler-1.5.2/lib/bundler/definition.rb:23:in `build': /xxxxxxx/releases/日付的なやつ/Gemfile not found (Bundler::GemfileNotFound)
        from /usr/local/rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/bundler-1.5.2/lib/bundler.rb:152:in `definition'
        from /usr/local/rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/bundler-1.5.2/lib/bundler.rb:115:in `setup'
        from /usr/local/rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/bundler-1.5.2/lib/bundler/setup.rb:17:in `<top (required)>'
        from /usr/local/rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
        from /usr/local/rbenv/versions/1.9.3-p448/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'

みたいな感じでエラーが出て再起動が出来ない。

解決方法

下記URLのBUNDLE_GEMFILE for Capistrano usersを見ればわかると思います。

capistranoをつかってると、多分、RAILS_ROOT/config/unicorn/production.rb とか作ってると思うんで、そこに、

before_exec do |server|
  ENV["BUNDLE_GEMFILE"] = "/path/to/app/current/Gemfile"
end

を追記してやる unicornの実行直前にRAILS_ROOT/current/GemfileのGemfileを見るように``BUNDLE_GEMFILE```を差し替えてやればいい。

普通、大体配置は同じと思うんで、さらしておくけど、下記のように出来るかなーと。

before_exec do |server|
  ENV["BUNDLE_GEMFILE"] = File.join(File.expand_path("../../../../", __FILE__), "current", "Gemfile")
end

注意してほしいのは、一回この現象が起きちゃった人、もしくは、対応する前の起動設定で起動しちゃった人は、Unicornをstop startして再起動してあげないとだめ。SIGUSR2 では解決できないと思う。

原因

原因としては、僕はcapistranoで5世代まで昔のディレクトリを保存しておくようにしているんだけど、それが、始めにunicornを立ち上げたディレクトリが消されたタイミングで Gemfile が存在しなくなってしまうことにある。

capistarano unicornはこんな感じで、unicornを立ち上げる。

RAILS_ENV=vm BUNDLE_GEMFILE=/xxxxxxx/releases/日付的なやつ/Gemfile bundle exec unicorn -c $UNICORN_CONFIG_PATH -E vm -D

この時点でENV["BUNDLE_GEMFILE"]にはRAILS_ROOT/releases/日付的なやつ/Gemfileが入ってしまうので、これをunicornプロセスが覚え続けてしまう。

そうすると、そのうちSIGUSR2がなげられても、一旦BUNDLE_GEMFILEの方にGemfileを確認してしまうので、既に存在しないGemfileを確認にいってしまう。

そして該当のエラーがでてしまうのだっ! だので対応は、解決方法の所で示した通りだっ!

shell script

なんかshellって忘れやすいので色々メモ

特殊変数

shellでもperlでもrubyでもいいんだけど、 特殊変数という、たとえば、$1みたいな変数がある。

これを特殊変数というんだけど、 特殊変数という言葉を良く忘れて、ググれなくなったりする。

特殊変数とちょっと関係ありそうな奴。

$#

$@

$*

$0

$1 から $9

shift はまたあとで書く。

$? 最後に実行した結果がはいってる。

$$ プロセス番号

$-

$!

IFS 区切り文字

環境変数

もちろん、もってますよね。実行ユーザがいるんだから。

envとかprintenvとかdeclareでみれる。

消したいときは、

export -n ENV_VAR

で、変数名ごときえて、中身だけ消したければ、

export ENV_VAR=

とかやる。

ファイルネームまわり

ファイルパスの文字列からいろいろ取得するためのもろもろ

FILE_PATH="/etc/httpd/httpd.conf"
 
# ファイル名を取得
FILE_NAME=${FILE_PATH##*/}

# 拡張子を取得
EXT=${FILE_PATH##*.}

# 拡張子を除いたファイル名
FILE=${FILE_NAME%.*}
 
# ディレクトリ名を取得
DIR_NAME=${FILE_PATH%/*}
# もしくは
DIR_NAME=`dirname ${FILE_PATH}

良くあるかきかたとして、今実行しているファイルの絶対パス

ABS_PATH=$(cd $(dirname $0);pwd)

関数

つーか変数の話でいうと、関数の中で宣言した変数もそのままだとグローバル変数になっちゃうので、

hoge() {
    local VALUE='aaaa'
}

みたいに、localをつけて宣言する。

ちなみに、read_onlyを付けると定数を作れる。

local read_only VALUEとかやれば、ローカルの定数。

returnは普通のshellを実行したときの終了ステータスになるから、0から255。 返り値が欲しいときは、echoしたりする。実行側で上手く使う例えば、こんな感じ

hoge() {
    local VALUE='aaaa'
    echo ${VALUE}
}

HUGA=`hoge`

引数は特殊変数とshiftをつかって取得する

外部ファイルのよみだしとか

関数があるとファイル分割したくなるんで、ファイル読み出しは、

sourceかもしくは、.をつかう、 たとえば、

source 'unlearned.sh'

みたいな。

unicornとunicorn_railsのオプションの違い

unicornunicorn_railsはほとんど同じ挙動をして、 application serverを立ち上げてくれますが、一部オプション指定の意味が違います。

ちょっとハマったので書いておくことにします。

結論

  • unicornのオプション-ERACK_ENVを設定
  • unicorn_railsのオプション-ERAILS_ENVを設定

参考: http://unicorn.bogomips.org/

経緯1

Capistrano 3を導入しまして、unicornを使っていたので無邪気に

を使っていました。(僕の環境では0.3.2) 普通に動かしていたんですが、muninがunicornのmemory statusをうまく取得できていないようでした。

該当のmuninのplugin

pluginに目をちゃんと通すとわかるんですが、

   def memory_usage
      result = { :master => {master_pid => nil}, :worker => {} }
      ps_output = `ps auxw | grep unicorn_rails`
      ps_output.split("\n").each do |line|

なるほど。unicorn_railsgrepしてます。

ということで、よく調べてみると、sepastian-capistrano3-unicornのデフォルトでは unicornを使ってunicornプロセスを起動していて、このままではこのunicorn_memory_status に引っかからないわけです。

ということで、unicorn立ち上げをunicorn_railsを通して実行する必要があるわけですがこれはわけなく行えます。 sepastian-capistrano3-unicorn は、unicorn_binというパラメータを用意してまして、これのデフォルトがunicornになっているわけなので、ここを変更する。

RAILS_ROOT/config/deploy.rbに下記記述を追記します。

set :unicorn_bin, ->{"unicorn_rails"}

(ラムダで囲んでんのは特に深い意味は無いんですが、評価時にいろいろ変更するようなモノが多いので念のため標準的にこうするようにしています。)

とここで世界は平和に終ると思っていました。

経緯2

unicornの時の-EパラメータがRACK_ENVであるということは理解していたので、RAILS_ENVunicorn実行前に設定するようにしてたわけです。 こんな感じで

RAILS_ENV=hogehoge; unicorn -E development .....

僕はVM上でrailsを動かすコトが多くて、vmというRAILS_ENVをつくっていました。 しかしunicorn_railsに変更してみたら、僕のVMで急にunicornが立ち上がらなくなりました。

RAILS_ENV=vm; unicorn_rails -E development .....

どうも、dababase.ymlにadapterの指定がない的なエラーがはかれていて、おかしーなーと思ったんです。 と、ここで気付きました。

-Eオプションが、RAILS_ENVを上書いていることを。

んで、下記をみた

なるほどね。

以上!

Rackのステータスコードとシンボルの表

ちょっとブックマークとかでも、あとでなんて検索したらいいかわからなくなりそうなので、メモしておく

下記のブログの抜粋です。

status code description symbol
100 Continue :continue
101 Switching Protocols :switching_protocols
102 Processing :processing
200 OK :ok
201 Created :created
202 Accepted :accepted
203 Non-Authoritative Information :non_authoritative_information
204 No Content :no_content
205 Reset Content :reset_content
206 Partial Content :partial_content
207 Multi-Status :multi_status
226 IM Used :im_used
300 Multiple Choices :multiple_choices
301 Moved Permanently :moved_permanently
302 Found :found
303 See Other :see_other
304 Not Modified :not_modified
305 Use Proxy :use_proxy
306 Reserved :reserved
307 Temporary Redirect :temporary_redirect
400 Bad Request :bad_request
401 Unauthorized :unauthorized
402 Payment Required :payment_required
403 Forbidden :forbidden
404 Not Found :not_found
405 Method Not Allowed :method_not_allowed
406 Not Acceptable :not_acceptable
407 Proxy Authentication Required :proxy_authentication_required
408 Request Timeout :request_timeout
409 Conflict :conflict
410 Gone :gone
411 Length Required :length_required
412 Precondition Failed :precondition_failed
413 Request Entity Too Large :request_entity_too_large
414 Request-URI Too Long :request_uri_too_long
415 Unsupported Media Type :unsupported_media_type
416 Requested Range Not Satisfiable :requested_range_not_satisfiable
417 Expectation Failed :expectation_failed
422 Unprocessable Entity :unprocessable_entity
423 Locked :locked
424 Failed Dependency :failed_dependency
426 Upgrade Required :upgrade_required
500 Internal Server Error :internal_server_error
501 Not Implemented :not_implemented
502 Bad Gateway :bad_gateway
503 Service Unavailable :service_unavailable
504 Gateway Timeout :gateway_timeout
505 HTTP Version Not Supported :http_version_not_supported
506 Variant Also Negotiates :variant_also_negotiates
507 Insufficient Storage :insufficient_storage
510 Not Extended :not_extended