Saturday, September 3, 2011

雑多なRuby CGIをnginxで動かすためのメモ

雑多なRuby CGIをnginxで動かすためのメモ

ちょっとしたスクリプトのCGIをいくつか動かしているが、nginxだとCGIを実行できないのでアプリケーションサーバ経由で実行させることになる。

というわけでunicornをつかってみる。

gem1.9.1 install unicorn

/home/www/unicorn/unicorn.conf (適当)

# unicron.conf
worker_processes 4
working_directory '/home/www/unicorn'
listen '/home/www/run/unicorn.sock', :backlog => 2048
timeout 30
pid '/home/www/run/unicorn.pid'
preload_app  false
stderr_path '/home/www/log/unicorn.log'

before_fork do |server, worker|
  old_pid = "#{server.config[:pid]}.oldbin"
  begin
    if File.exists?(old_pid) && old_pid != server.pid
      Process.kill(:QUIT, File.read(old_pid).to_i)
    end
  rescue Errno::ENOENT, Errno::ESRCH
  end
end

after_fork do |server, worker|
end

/home/www/unicorn/config.ru

$:.unshift File.dirname(__FILE__)
require 'rack'
require 'foo'

app = lambda { |env| [404, { 'Content-Type' => 'text/html' }, [ '<h1>404 Not Found</h1>'] ] }

map "/cgi-bin/foo" do
  run FooApp.new
end

map "/cgi-bin/" do
  run app
end

アプリケーション /home/www/unicorn/foo.rb
処理をclassのcallメソッドに収めたらいい。返り値は [ HTTP_CODE, HEADER, [ body ] ] GET/POSTのリクエストパラメータはRack::Request.new( env )['key'] あるいはRack::Request.new( env ).paramsでとれる

class FooApp
  def call( env )
    buffer = "== Environment variables\n"
    buffer += env.map do |k,v| "#{k} = #{v}" end.join("\n")
    buffer += "\n\n== Request params\n"
    buffer += Rack::Request.new( env ).params.map do |k, v| "#{k} = #{v}" end.join("\n")
    buffer += "\n\n== rack.input=\n"
    buffer += env['rack.input'].read
    [ 200, { 'Content-Type'=> 'text/plain'}, [ buffer ] ]
  end
end

実行しとく

/var/lib/gems/1.9.1/bin/unicorn -E development -D -c /home/www/unicorn/unicorn.conf

nginx の設定

upstream unicorn {
        server unix:/var/run/unicorn/sock;
}
server {
        listen 80;

        location /cgi-bin/ {
                proxy_pass_header Server;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_read_timeout 60;
                proxy_connect_timeout 60;
                proxy_pass http://unicorn;
        }
}

蛇足ではあるが、location ~ \.cgi$ { } とかでひっかけて map "/cgi-bin/foo.cgi" にしたりすると以前のcgi pathのまま実行できるね。

1 comment:

jowdjbrown said...

I surely acquiring more difficulties from each surprisingly more little bit of it
ナイトアイボーテ