結論... shebangで指定すべきインタプリタを誤って設定していた。
※コメントだとおもっていた件
前提をお伝えすると、
ソースコードのフローチャートを自動化してくれるGemを、ソースコード可視化ツールを作りたかった。
こんなの↓
関連記事:Rails要らず、CGIとRubyでソースコードをフローチャートにするツール作成
関連リポジトリ:VisualizeSrc
詰まったところ
Gemを読み込みのためのrequire bundle/setup
で「該当ファイルないぞ」って怒られる。
エラー内容は↓
/usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- bundler/setup (LoadError), referer: http://localhost/index.cgi
状況を整理すると
- 特定の実行Rubyファイル(A)にて、
require bundler/setup
がロードエラーになっていた.- rbenvで環境指定はできている。
- 同じ環境下の他のRubyファイル(B)は実行は可能
- かつRubyファイル(B)では
require bundler/setup
は成功する - しかし、Rubyファイル(B)をRubyファイル(A)に取り込んで処理させると、やはり上述のロードエラーになる。
- かつRubyファイル(B)では
- 権限問題も解消
- 全て777に変更してみたが、それでも解決せず。
問題ソースコードはこちら
# 問題ファイル(result.rb)中身
----
1 #! usr/bin/ruby
2 require "bundler/setup" ← ここで死んでいた。
3 require 'cgi'
4 cgi = CGI.new
5 print "Content-Type: text/html\n\n"
6 print "<html>\n"
7 print "<head>\n"
8 print "<title>CGI Test</title>\n"
9 print "</head>\n"
10 print "<body>\n"
11 print "<a href=\"/form.cgi\">\"こちらのページから画像が見れます\"</a>"
12 print "</body>\n"
13 print "</html>\n"
14 $src = cgi["sub"]
...
エラー内容を詳しくみてみる。
教えてApache先生
apacheのエラーログを見てみると、(再掲になるが↓)
# /var/log/httpd/error_logのログ
/usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- bundler/setup (LoadError), referer: http://localhost/index.cgi
- エラーの内容から明らかに、pathに誤りがあることがわかる。
- 失敗箇所は先に触れているが、指定ファイルがrequireできない、というもの...
- おそらく指定しているファイル/ロードパスに誤りがある...
心の声(その1)
ん?でも、同じ環境下に作っているruby fileなのに1つは実行可能で、もう一つは実行不可能ってどういうこと?? Why Ruby!
※ちなみに、/usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55
をggるとたくさん、悩んでいる人がいた印象。軒並み検証してみましたが、解決せず。requireのあとに指定しているパスが間違っているよ、というアドバイスが多かった印象でした。
ということで、冷静にみましょう、ロードパス
RubyGems Environment:
- RUBYGEMS VERSION: 3.0.2
- RUBY VERSION: 2.3.8 (2018-10-18 patchlevel 459) [x86_64-linux]
- INSTALLATION DIRECTORY: /usr/local/rbenv/versions/2.3.8/lib/ruby/gems/2.3.0
- USER INSTALLATION DIRECTORY: /root/.gem/ruby/2.3.0
- RUBY EXECUTABLE: /usr/local/rbenv/versions/2.3.8/bin/ruby
- GIT EXECUTABLE: /usr/bin/git
- EXECUTABLE DIRECTORY: /usr/local/rbenv/versions/2.3.8/bin
- SPEC CACHE DIRECTORY: /root/.gem/specs
- SYSTEM CONFIGURATION DIRECTORY: /usr/local/rbenv/versions/2.3.8/etc
- RUBYGEMS PLATFORMS:
- ruby
- x86_64-linux
- GEM PATHS:
- /usr/local/rbenv/versions/2.3.8/lib/ruby/gems/2.3.0
- /root/.gem/ruby/2.3.0
- GEM CONFIGURATION:
- :update_sources => true
- :verbose => true
- :backtrace => false
- :bulk_threshold => 1000
- REMOTE SOURCES:
- https://rubygems.org/
- SHELL PATH:
心の声(その2)
うん、rbenvで指定できている。。。Why Ruby!
と、もうわからん。頭を抱えているとshebangに出会ったのでした。
天の声(その1)
shebang/シバン(Unix) ってのがあるんだよ??
[引用] シバンまたはシェバン (英: shebang) とはUNIXのスクリプトの #! から始まる1行目のこと。起動してスクリプトを読み込むインタプリタを指定する。ハッシュ・バンまたはシェル・バン、シャープ・バンとも言うが、これらを縮めたシェバンという呼び方が一般的かつ簡素である。*
rbenv指定のrubyとgemが正しく指定できてなかった。shebangの指定先が間違っていた...YES, Ruby!!!
本来使いたかったもの(正解) | 誤って設定していたもの | |
---|---|---|
設定したshebang | #! /usr/local/rbenv/versions/2.3.8/bin/ruby | #! usr/bin/ruby |
結果 | この配下にgemは存在するので成功する | gemをinstallしていないので、ロードエラーになる |
本来は#! /usr/local/rbenv/versions/2.3.8/bin/ruby
にすべて設定していて、ここを使いたかった。が、問題Rubyファイル(A)では特に関係のない(設定していない)インタプリタを指定してしまっていた。
恥ずかしながら、shebangをずっとコメントだとおもっていたため、原因特定が難しかった。
最終的にはgem env
で右記を確認「RUBY EXECUTABLE: /usr/local/rbenv/versions/2.3.8/bin/ruby」して、shebang指定してあげたらOKだった。
[補足] 助けてくれた資料達...thanks!!
- #!/bin/sh は ただのコメントじゃないよ! Shebangだよ!
- Perl, Python 及び Ruby スクリプトにおける正しいshebangの書き方
- 「#!/usr/bin/python」と「#!/usr/bin/env python」の違い
- いまさら聞けない、#! で始まる1行目の名前とenv指定時の挙動
[余談] そもそもbundler/setupが何をしているのかは、こちらの記事がわかりやすかった。
-
Bundler入門 - setupとrequire を読み解く
- 要はgemファイルを一括で読み込んでいる
- gem同士の互換性を保ちながら各gemの導入、管理を行ってくれるのがBundler
お読み頂きありがとうございました。
以上になります。誰かのお役に立てば...
なにか間違っていたり、ベターな方法がある場合はご教示いただけると幸いです。