rails4启动过程

本篇博文会从使用rails server命令到应用启动完成的代码调用顺序,介绍rails server的启动过程,是对rails guide的一个简略翻译和一些博主的认识,翻译的不好还请各位见谅。看的时候最好找一份rails4的源码一起对照的来看。

原文地址: http://guides.ruby-china.org/initialization.html

当我们使用rails c(onsole)或者rails s(erver)时会启动一个rails的应用,rails s其实相当于在当前路径下执行了一段ruby脚本:

version = ">=0"
load Gem.bin_path(‘railties‘, ‘rails‘, version)

如果在Rails console里输入上面的命令,你会看到railties/bin/rails被执行了。

在railties/bin/rails源码的最后一行可以看到

require “rails/cli”

require了railties/lib/rails/cli,继续跟进,在railties/lib/rails/cli中:

require ‘rails/app_rails_loader‘
# If we are inside a Rails application this method performs an exec and thus
# the rest of this script is not run.
Rails::AppRailsLoader.exec_app_rails

继续进入railties/lib/rails/app_rails_loader.rb

RUBY = Gem.ruby
EXECUTABLES = [‘bin/rails‘, ‘script/rails‘]
......

class << self
    ......
    def exec_app_rails
      original_cwd = Dir.pwd
      loop do
        if exe = find_executable
          contents = File.read(exe)
     
          if contents =~ /(APP|ENGINE)_PATH/
            exec RUBY, exe, *ARGV
            break # non reachable, hack to be able to stub exec in the test suite
          elsif exe.end_with?(‘bin/rails‘) && contents.include?(‘This file was generated by Bundler‘)
            $stderr.puts(BUNDLER_WARNING)
            Object.const_set(:APP_PATH, File.expand_path(‘config/application‘, Dir.pwd))
            require File.expand_path(‘../boot‘, APP_PATH)
            require ‘rails/commands‘
            break
          end
        end
        # If we exhaust the search there is no executable, this could be a
        # call to generate a new application, so restore the original cwd.
        Dir.chdir(original_cwd) and return if Pathname.new(Dir.pwd).root?
       
        # Otherwise keep moving upwards in search of an executable.
        Dir.chdir(‘..‘)
      end
    end
       
    def find_executable
      EXECUTABLES.find { |exe| File.file?(exe) }
    end
end

可以通过上面的代码看出Rails::AppRailsLoader.exec_app_rails会在当前目录下找bin/rails或script/rails,找到了就会执行:

 exec Gem.ruby, bin/rails, *ARGV

即相当于

exec ruby bin/rails server

如果当前目录下没有bin/rails或script/rails就会一直递归向上直到找到bin(script)/rails,所以在rails项目的根目录以及子目录下的任何地方都可以使用rails server或rails console命令

bin/rails:

#!/usr/bin/env ruby
APP_PATH = File.expand_path(‘../../config/application‘, __FILE__)
require_relative ‘../config/boot‘
require ‘rails/commands‘

APP_PATH常量将会在之后的rails/commands里使用require_relative ‘../config/boot‘是require了config/boot.rb文件,boot.rb负责加载启动Bundler

config/boot.rb

# Set up gems listed in the Gemfile.
ENV[‘BUNDLE_GEMFILE‘] ||= File.expand_path(‘../../Gemfile‘, __FILE__)
 
require ‘bundler/setup‘ if File.exist?(ENV[‘BUNDLE_GEMFILE‘])

在标准的的Rails应用中,Gemfile文件申明了所有应用依赖关系,ENV[‘BUNDLE_GEMFILE‘]存放Gemfile的文件地址,当Gemfile文件存在,回去require bundle/setup,用于Bundler配置加载Gemfile依赖关系的路径。

一个标准的Rails应用需要依赖几个gem包,如:

  • actionmailer
  • actionpack
  • actionview
  • activemodel
  • activerecord
  • activesupport
  • arel
  • builder
  • bundler
  • erubis
  • i18n
  • mail
  • mime-types
  • polyglot
  • rack
  • rack-cache
  • rack-mount
  • rack-test
  • rails
  • railties
  • rake
  • sqlite3
  • thor
  • treetop
  • tzinfo

require了config/boot.rb后回到bin/rails,最后还会require rails/commands

rails/commands.rb

主要用于扩展rails命令参数的别名:

rails/commands.rb

ARGV << ‘--help‘ if ARGV.empty?
 
aliases = {
  "g"  => "generate",
  "d"  => "destroy",
  "c"  => "console",
  "s"  => "server",
  "db" => "dbconsole",
  "r"  => "runner"
}
 
command = ARGV.shift
command = aliases[command] || command
 
require ‘rails/commands/commands_tasks‘
 
Rails::CommandsTasks.new(ARGV).run_command!(command)

可以看到当不传参数时,实际上与rails --help等效,rails s等效于rails server

rails/commands/command_tasks.rb

当输入了一个错误的rails命令,run_command方法负责抛出一个错误信息。如果命令是有效的,就会调用相同名称的方法

COMMAND_WHITELIST = %(plugin generate destroy console server dbconsole application runner new version help)
 
def run_command!(command)
  command = parse_command(command)
  if COMMAND_WHITELIST.include?(command)
    send(command)
  else
    write_error_message(command)
  end
end

def write_error_message(command)
  puts "Error: Command ‘#{command}‘ not recognized"
  if %x{rake #{command} --dry-run 2>&1 } && $?.success?
    puts "Did you mean: `$ rake #{command}` ?\n\n"
  end
  write_help_message 
  exit(1)
end
          
def parse_command(command) 
  case command 
  when ‘--version‘, ‘-v‘ 
    ‘version‘ 
  when ‘--help‘, ‘-h‘ 
     ‘help‘
  else
     command 
  end
end

等下继续

时间: 2024-08-03 18:38:14

rails4启动过程的相关文章

tomcat启动过程报the JDBC Driver has been forcibly unregistered问题的修复过程

最近两天在整理关于flume的总结文档,没有启动过tomcat.昨天晚上部署启动,发现报了如题的错误,全文如下: 严重: The web application [/oa-deploy] registered the JBDC driver [com.microsoft.sqlserver.jdbc.SQLServerDriver] but failed to unregister it when the web application was stopped. To prevent a mem

Linux启动过程笔记

Linux启动过程 1.启动流程(BIOS->MBR:Boot Code->引导GRUB->加载内核->执行init->runlevel) 2./boot/grub/下有多个文件   其中stage1为MBR镜像(512字节) stage2为引导程序 3./boot/grub/grub.conf为引导的配置文件 default=0#默认加载下边哪个系统 timeout=3#引导等待时间 splashimage=(hd0,1)/boot/grub/splash.xpm.gz#引

SpringMVC启动过程

1.  对于一个web应用,其部署在web容器中,web容器提供一个其一个全局的上下文环境,这个上下文环境就是ServletContext,它为后面的spring IoC容器提供宿主环境: 2.  web.xml中有配置ContextLoaderListener,也可以自定义一个实现ServletContextListener接口的Listener方法,web.xml中的配置实例如下: <listener> <listener-class>com.manager.init.Syst

Linux内核分析 实验三:跟踪分析Linux内核的启动过程

贺邦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 一. 实验过程 1.打开shell,输入启动指令,内核启动完成后进入menu程序,支持三个命令help.version和quit. 2.然后使用gdb跟踪调试内核,输入命令qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 3.按住

systemd启动过程

理解Linux启动过程 在我们打开Linux电脑的电源后第一个启动的进程就是init.分配给init进程的PID是1.它是系统其他所有进程的父进程.当一台Linux电脑启动后,处理器会先在系统存储中查找BIOS,之后BIOS会检测系统资源然后找到第一个引导设备,通常为硬盘,然后会查找硬盘的主引导记录(MBR),然后加载到内存中并把控制权交给它,以后的启动过程就由MBR控制. 主引导记录会初始化引导程序(Linux上有两个著名的引导程序,GRUB和LILO,80%的Linux系统在用GRUB引导程

深入理解UIApplication和ios程序启动过程

在深入理解UIApplication前我们先了解ios程序的启动过程: UIApplication类在ios里面为app的管理和协调提供一个集中的点,每一个app有一个UIApplication的实例,当app启动时,系统会调用main函数里面的UIApplicationMain函数,该函数会创建一个UIApplication的实例,设置run loop,启动info.plist里面指定的main.storyboard,加载UIview.

(作业3)Linux内核的启动过程(从start_kernel到init进程启动)

作业题目: 详细分析从start_kernel到init进程启动的过程并结合实验截图撰写一篇署名博客,并在博客文章中注明“真实姓名(与最后申请证书的姓名务必一致) + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”,博客内容的具体要求如下: 题目自拟,内容围绕Linux内核的启动过程,即从start_kernel到init进程启动: 博客中需要使用实验截图 博客内容中需要仔细分析

linux基础:5、linux启动过程

linux启动过程 1.BIOS(basic in out system) 通电检查硬件,然后加载第一可用启动项的mbr: #可通过BIOS设置各种介质存储设备的启动顺序,比如:cdrom.disk.usb 2.MBR(main boot recorder) 磁盘的第一个扇区,共512字节,446字节的boot程序空间,64字节的分区表,2字节的校验位. 执行MBR内保存的boot loader程序,一般为GRUB,通过GRUB来找到kernel和initrd(centos6里面此文件更名)并将

Linux启动过程

Linux启动过程 传说]散人--南宁1,开机,读取BIOS并进行自我检测2,透过BIOS取得第一个开机装置,读取MBR取得开机管理程序3透过开机管理程序,取得KERNEL(内核)加载内存且侦测系统硬件4核心计动呼叫INIT的程序5INIT程序开始执行系统初始化6依据INIT的程序进行daemon start7加载本机设定 22:19:25[传说]Ed1 2015/1/20 22:19:25 启动第一个程序init,读取配置文件fstab22:20:37[传说]散人--南 2015/1/20 2