Rails 8脚本引入environment后重复执行问题求助
问题原因及解决方案
核心原因
这是因为你的Rails 8生产环境中,bin目录被意外加入到**预加载路径(eager_load_paths)或自动加载路径(autoload_paths)**中,而Rails生产环境会预加载所有这些路径下的Ruby文件。
你的bin/odd脚本是一个Ruby文件,当执行require_relative '../config/environment'时,Rails的Zeitwerk自动加载器会预加载bin目录下的odd.rb,导致整个脚本被第二次执行,从而重复输出quack。
开发环境不会出现这个问题,是因为开发环境默认是按需加载,只有当代码引用到对应常量时才会加载文件,你的脚本里没有触发Odd常量的引用,所以不会重复执行。
验证方法
在bin/odd脚本中添加一行输出当前文件路径的代码,确认是否被执行两次:
#!/usr/bin/env ruby puts "Executing: #{__FILE__}" puts 'quack' require_relative '../config/environment' puts 'done'
执行生产环境命令后,如果输出两次相同的Executing: .../bin/odd,即可确认是预加载导致的重复执行。
解决方案
检查并修正加载路径
打开config/application.rb,查找是否有类似以下代码:config.autoload_paths << Rails.root.join('bin') config.eager_load_paths << Rails.root.join('bin')如果有,删除这些行——
bin目录不应该被加入到自动加载或预加载路径中。修改脚本名称
如果不想调整加载路径,可以将bin/odd改名为不会被Zeitwerk识别为可加载文件的名称,比如bin/odd_runner(Zeitwerk会将odd.rb映射为Odd常量,改名可避免这种触发)。添加执行防护
在脚本开头添加一个标记,防止重复执行:#!/usr/bin/env ruby # 防止脚本被重复执行 return if defined?(ODD_SCRIPT_RAN) ODD_SCRIPT_RAN = true puts 'quack' require_relative '../config/environment' puts 'done'
内容的提问来源于stack exchange,提问作者jjg
相关产品推荐
相关产品推荐

