>> 古い記事: Gimp: スキャンした文書などの画像の傾きを修正し水平にする(2)
<< 新しい記事: SQuirreL SQL Client をインストールして SQLite3 に接続

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

(solved)Ruby/Webrick/CGI: cgi_runner.rb:47:in `exec': Permission denied ... (Errno::EACCES)

簡単なCGIを使いたくて昔書いたやつから適当にコピペして動かしたら 次のようなエラーメッセージが出て Internal Server Error になった。

2012-02-10 22:45:16] ERROR CGIHandler: /home/user/webrick-test/www/cgi/hello.rb:
/home/user/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/httpservlet/cgi_runner.rb:47:in `exec': Permission denied - /home/user/webrick-test/www/cgi/hello.rb (Errno::EACCES)
        from /home/user/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/webrick/httpservlet/cgi_runner.rb:47:in `
' [2012-02-10 22:45:16] ERROR CGIHandler: /home/user/webrick-test/www/cgi/hello.rb exit with 1 [2012-02-10 22:45:16] ERROR Premature end of script headers: /home/user/webrick-test/www/cgi/hello.rb localhost.localdomain - - [10/Feb/2012:22:45:16 JST] "GET /cgi/hello.rb HTTP/1.1" 500 354 - -> /cgi/hello.rb

パーミッションがどうとか言われているけど、 WEBrick::HTTPServer.new の引数で :CGIInterpreter を指定したら動いた。


require 'webrick'

document_root = '/home/user/webrick-test/www'

server = WEBrick::HTTPServer.new({
  :DocumentRoot => '/home/user/webrick-test/www',
  :BindAddress => '0.0.0.0',
  :CGIInterpreter => '/usr/bin/ruby', # <= これ
  :Port => 10081
})

['/cgi/hello.rb'].each {|cgi_file|
  server.mount(cgi_file, WEBrick::HTTPServlet::CGIHandler, document_root + cgi_file)
}

['INT', 'TERM'].each {|signal|
  Signal.trap(signal){ server.shutdown }
}

server.start

せっかくなのでもう少し。 該当の cgi_runner.rb:47 は次のようになっていて、 ブラウザで /cgi/hello.rb にアクセスされた時にこの行が実行されます。


# webrick/httpservlet/cgi_runner.rb

exec ENV["SCRIPT_FILENAME"]

ENV["SCRIPT_FILENAME"] は実行しようとしている cgi のフルパスです。 (この場合は "/home/user/webrick-test/www/cgi/hello.rb")

ちょっと実験:

$ ruby -e 'exec "www/cgi/hello.rb"'
-e:1:in `exec': Permission denied - www/cgi/hello.rb (Errno::EACCES)                                                                              
        from -e:1:in `
'

参考: module function Kernel.#exec

これはシェルからスクリプトのパスだけで実行しようとした場合と似てますね(同じ?)。

$ www/cgi/hello.rb
bash: www/cgi/hello.rb: Permission denied

では CGIInterpreter == "/usr/bin/ruby" な場合はというと


# webrick/httpservlet/cgi_runner.rb

if interpreter = ARGV[0]
  argv = ARGV.dup
  argv << ENV["SCRIPT_FILENAME"]
  exec(*argv) # ←こっちが実行されます
  # NOTREACHED
end
exec ENV["SCRIPT_FILENAME"]

このとき argv は ["/usr/bin/ruby", "/home/user/webrick-test/www/cgi/hello.rb"] 。

つまり、指定ありの場合は

exec( "/usr/bin/ruby", "/home/user/webrick-test/www/cgi/hello.rb" )

指定なしの場合は

exec( "/home/user/webrick-test/www/cgi/hello.rb" )

という形でCGIスクリプトが実行されていた訳ですね。

という訳で、要するに exec でした。


…もうちょっと実験。

- CGIInterpreter 指定なし
- hello.rb の実行権限あり
- hello.rb の先頭行に shebang(#!/usr/bin/ruby)あり

という条件で動かしてみたところ、 hello.rb が実行され Internal server error になりませんでした。 なるほどです。

バージョン

ruby -v          #=> ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux]
/usr/bin/ruby -v #=> ruby 1.8.7 (2010-06-23 patchlevel 299) [i686-linux]

参考

>> 古い記事: Gimp: スキャンした文書などの画像の傾きを修正し水平にする(2)
<< 新しい記事: SQuirreL SQL Client をインストールして SQLite3 に接続
** ホームに戻る

コメント

コメントの投稿

管理者にだけ表示を許可する

|
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。