LoginSignup
0
0

More than 3 years have passed since last update.

crontabでrubyを実行するときに、Bundler.requireがエラーになる件の対応策

Posted at

この記事で書くこと

一つ前の記事で、cronでshell scriptをよび、rubyを実行するときに躓いたところについて書きましたが、
実はもう一つ躓いていたので、その内容を忘れないようにアウトプットします。
rubyファイルで Bundler.require するときに出たエラーについてです。

参考にさせていただいたサイト :bow: ありがとうございます。

結論

Gemfileが置いてあるディレクトリにcdで移動してからrubyを実行するようにすればいい。
でも、きちんと理解出来てない。

/home/user_name/ruby_test.sh
#!/bin/bash
cd /home/user_name/sample && ruby /home/user_name/sample/tasks/test_ruby.rb

起きたこと

状況整理

crontab
00 13 * * * /bin/bash /home/user_name/ruby_test.sh > /home/user_name/log/ruby_test.log 2>&1
/home/user_name/ruby_test.sh
#!/bin/bash
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
rbenv shell 2.7.1
ruby /home/user_name/sample/tasks/test_ruby.rb
/home/user_name/sample/tasks/test_ruby.rb
require 'bundler/setup'
Bundler.require

# 以下rubyの処理が続きます

実行されたスクリプト。
ログファイルを見ると、何かエラーが。。

/home/user_name/log/ruby_test.log
/home/user_name/sample/tasks/test_ruby.rb:2:in `<main>': private method `require' called for Bundler:Module (NoMethodError)

上手く行ってないみたい。

でも、

cd /home/user_name/sample
ruby /tasks/test_ruby.rb

を実行すると、エラーが出ずに実行できるんです。

どうしてか解らなかったですが、

Bundler.require
が何をしてるのかみてみることにしました。

bundler/lib/bundler.rb

def require(*groups)
  setup(*groups).require(*groups)
end

setup がなんなのか追ってみます。

bundler/lib/bundler.rb

def setup(*groups)
   # Return if all groups are already loaded
   return @setup if defined?(@setup) && @setup 

   definition.validate_runtime!

   SharedHelpers.print_major_deprecations!
   if groups.empty?
     # Load all groups, but only once
     @setup = load.setup
   else
     load.setup(*groups)
   end
end

今回自分は引数なしで呼び出している為、
@setup = load.setup が呼ばれそうです。

bundler/lib/bundler.rb
def load
  @load ||= Runtime.new(root, definition)
end
bundler/lib/bundler/runtime.rb
def setup(*groups)
   @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle?

   groups.map!(&:to_sym)

   # Has to happen first
   clean_load_path

   specs = groups.any? ? @definition.specs_for(groups) : requested_specs

   SharedHelpers.set_bundle_environment
   Bundler.rubygems.replace_entrypoints(specs)

   # Activate the specs
   load_paths = specs.map do |spec|
     unless spec.loaded_from
       raise GemNotFound, "#{spec.full_name} is missing. Run `bundle install` to get it."
     end

     check_for_activated_spec!(spec)

     Bundler.rubygems.mark_loaded(spec)
     spec.load_paths.reject {|path| $LOAD_PATH.include?(path) }
   end.reverse.flatten

   Bundler.rubygems.add_to_load_path(load_paths)

   setup_manpath

   lock(:preserve_unknown_sections => true)

   self
end

ここまで辿って、そもそもrequire呼べてないんだよ。先を見ても勉強になるだけだよ、と気づく。
private methodですってエラーには出てるけど、private methodに見えない。自分が見てる場所が間違ってるだけ?????

注:今はBundlerはarchiveになっています。
rubygemsを使う方がいいようです。

時間があるときに、もう一度読んでみようと思いますが、
厳密にどこがエラーを返してるのか、どうしてエラーになったのか、まだ理解できてません。。 :disappointed:

とにかく、cdしたら動くことはわかったので、そのように書いてみて試す。

/home/user_name/ruby_test.sh
#!/bin/bash
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
rbenv shell 2.7.1

cd /home/user_name/sample && ruby /home/user_name/sample/tasks/test_ruby.rb

きちんと理解はできてないけど、一応動いた。。。 :thinking: 理解出来てないの気持ち悪い。週末の宿題。。
とりあえず調べ続けてみます。 :notebook: :runner:

もし優しい方がいらっしゃったら、もし解ればコメントなどで教えていただけると嬉しいです。 :bow:

読んでいただきありがとうございました。 :bow:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0