Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Ruby Environment Variable API

The Ruby Environment Variable API

Jack Danger Canty

November 16, 2015
Tweet

Other Decks in Programming

Transcript

  1. The ideal world: # myonlyapp.rb module Rails # … ten

    million lines of Ruby # copied and pasted from Rails source end module My class Application < Rails::Application # … way more stuff end end
  2. Reality: $ > rvm list known # MRI Rubies [ruby-]1.8.6[-p420]

    [ruby-]1.8.7[-head] # security released on head [ruby-]1.9.1[-p431] [ruby-]1.9.2[-p330] [ruby-]1.9.3[-p551] [ruby-]2.0.0[-p647] [ruby-]2.1[.7] [ruby-]2.2[.3] [ruby-]2.2-head ruby-head
  3. # MagLev maglev[-head] maglev-1.0.0 # Mac OS X Snow Leopard

    Or Newer macruby-0.10 macruby-0.11 macruby[-0.12] macruby-nightly macruby-head # IronRuby ironruby[-1.1.3] ironruby-head
  4. $ > ~/.rubies/2.2.1/bin/ruby -r stuff ./app.rb # a real app.rb

    require 'thing' require 'other_thing' require 'nokogiri' # for some reason require 'custom-fork-of-sidekiq' require 'file-in-a-local-git-repo' require 'nokogiri/lib/specific_file'
  5. $ > irb irb(main):001:0> require 'nokogiri' LoadError: cannot load such

    file -- nokogiri from /usr/ruby20/lib64/ruby/2.0.0/rubygems/core_ext kernel_require.rb:55:in `require' from /usr/ruby20/lib64/ruby/2.0.0/rubygems/core_ext kernel_require.rb:55:in `require' from (irb):1 from /usr/ruby20/bin/irb:16:in `<main>'
  6. How highly-paid engineers solve problems with Ruby dependencies: 1. $

    > rake 2. $ > bundle exec rake 3. $ > rvm use some-ruby && bundle exec rake 4. Close your terminal and open it again 5. Ask a coworker 6. $ > rvm implode && (curl https://get.rvm.io | bash) 7. re-run the setup script that your team uses 8. reboot your machine 9. buy a new macbook 10. become a farmer
  7. ENV Variables: A global hash of strings that your program

    inherits from it’s parent program (i.e. your shell session).
  8. Where did it go? $ > echo $ohdear uhoh $

    > ohdear=uhoh $ > env | grep ohdear
  9. $ > ohdear=uhoh && env | grep ohdear $ >

    echo $ohdear uhoh $ > ohdear=uhoh $ > export ohdear=uhoh $ > env | grep ohdear
  10. Your OS (pid 1) Your shell $ export happy=yes $

    food=pizza export happy=yes ohdear=uhoh export happy=yes `env`
  11. Your OS (pid 1) Your shell $ export happy=yes $

    food=pizza export happy=yes export ohdear=uhoh export happy=yes export ohdear=uhoh `env`
  12. $ > echo $PATH | tr : "\n" /usr/lib64/qt-3.3/bin /usr/pgsql-9.1/bin

    /usr/local/go/bin /usr/local/bin /bin /usr/bin /usr/local/sbin /usr/sbin /sbin $PATH
  13. $ > echo $PATH | tr : "\n" /usr/lib64/qt-3.3/bin /usr/pgsql-9.1/bin

    /usr/local/go/bin /usr/local/bin /bin /usr/bin /usr/local/sbin $PATH
  14. $ > strace sh -c 'missingcommand' execve("/bin/sh", ["sh", "-c", "missingcommand"],

    [/* 37 vars */]) = 0 stat("/usr/lib64/qt-3.3/bin/missingcommand") = -1 ENOENT stat("/usr/pgsql-9.1/bin/missingcommand") = -1 ENOENT stat("/usr/local/go/bin/missingcommand") = -1 ENOENT stat("/usr/local/bin/missingcommand") = -1 ENOENT stat("/bin/missingcommand") = -1 ENOENT stat("/usr/bin/missingcommand") = -1 ENOENT stat("/usr/local/sbin/missingcommand") = -1 ENOENT stat("/usr/sbin/missingcommand") = -1 ENOENT stat("/sbin/missingcommand") = -1 ENOENT write(2, "sh: missingcommand: command not "..., 38) = 38 (ENOENT = "No such file or directory”) $PATH
  15. $ > strace sh -c 'missingcommand' execve("/bin/sh", ["sh", "-c", "missingcommand"],

    [ stat("/usr/lib64/qt-3.3/bin/missingcommand") = -1 E stat("/usr/pgsql-9.1/bin/missingcommand") = -1 ENOE stat("/usr/local/go/bin/missingcommand") = -1 ENOEN stat("/usr/local/bin/missingcommand") = -1 ENOENT stat("/bin/missingcommand") = -1 ENOENT stat("/usr/bin/missingcommand") = -1 ENOENT stat("/usr/local/sbin/missingcommand") = -1 ENOENT stat("/usr/sbin/missingcommand") = -1 ENOENT stat("/sbin/missingcommand") = -1 ENOENT write(2, "sh: missingcommand: command not "..., 38) $ > echo $PATH | tr : "\n" /usr/lib64/qt-3.3/bin /usr/pgsql-9.1/bin /usr/local/go/bin /usr/local/bin /bin /usr/bin /usr/local/sbin /usr/sbin /sbin $PATH
  16. $ > strace sh -c 'missingcommand' execve("/bin/sh", ["sh", "-c", "missingcommand"],

    [ stat("/usr/lib64/qt-3.3/bin/missingcommand") = -1 E stat("/usr/pgsql-9.1/bin/missingcommand") = -1 ENOE stat("/usr/local/go/bin/missingcommand") = -1 ENOEN stat("/usr/local/bin/missingcommand") = -1 ENOENT stat("/bin/missingcommand") = -1 ENOENT stat("/usr/bin/missingcommand") = -1 ENOENT stat("/usr/local/sbin/missingcommand") = -1 ENOENT stat("/usr/sbin/missingcommand") = -1 ENOENT stat("/sbin/missingcommand") = -1 ENOENT write(2, "sh: missingcommand: command not "..., 38) $ > echo $PATH | tr : “\n” /usr/lib64/qt-3.3/bin /usr/pgsql-9.1/bin /usr/local/go/bin /usr/local/bin /bin /usr/bin /usr/local/sbin /usr/sbin /sbin $PATH
  17. $ > strace sh -c 'missingcommand' execve("/bin/sh", ["sh", "-c", "missingcommand"],

    [ stat("/usr/lib64/qt-3.3/bin/missingcommand") = -1 E stat("/usr/pgsql-9.1/bin/missingcommand") = -1 ENOE stat("/usr/local/go/bin/missingcommand") = -1 ENOEN stat("/usr/local/bin/missingcommand") = -1 ENOENT stat("/bin/missingcommand") = -1 ENOENT stat("/usr/bin/missingcommand") = -1 ENOENT stat("/usr/local/sbin/missingcommand") = -1 ENOENT stat("/usr/sbin/missingcommand") = -1 ENOENT stat("/sbin/missingcommand") = -1 ENOENT write(2, "sh: missingcommand: command not "..., 38) $ > echo $PATH | tr : “\n” /usr/lib64/qt-3.3/bin /usr/pgsql-9.1/bin /usr/local/go/bin /usr/local/bin /bin /usr/bin /usr/local/sbin /usr/sbin /sbin $PATH
  18. $ > strace sh -c 'missingcommand' execve("/bin/sh", ["sh", "-c", "missingcommand"],

    [ stat("/usr/lib64/qt-3.3/bin/missingcommand") = -1 E stat("/usr/pgsql-9.1/bin/missingcommand") = -1 ENOE stat("/usr/local/go/bin/missingcommand") = -1 ENOEN stat("/usr/local/bin/missingcommand") = -1 ENOENT stat("/bin/missingcommand") = -1 ENOENT stat("/usr/bin/missingcommand") = -1 ENOENT stat("/usr/local/sbin/missingcommand") = -1 ENOENT stat("/usr/sbin/missingcommand") = -1 ENOENT stat("/sbin/missingcommand") = -1 ENOENT write(2, "sh: missingcommand: command not "..., 38) $ > echo $PATH | tr : “\n” /usr/lib64/qt-3.3/bin /usr/pgsql-9.1/bin /usr/local/go/bin /usr/local/bin /bin /usr/bin /usr/local/sbin /usr/sbin /sbin $PATH
  19. $ > strace sh -c 'missingcommand' execve("/bin/sh", ["sh", "-c", "missingcommand"],

    [ stat("/usr/lib64/qt-3.3/bin/missingcommand") = -1 E stat("/usr/pgsql-9.1/bin/missingcommand") = -1 ENOE stat("/usr/local/go/bin/missingcommand") = -1 ENOEN stat("/usr/local/bin/missingcommand") = -1 ENOENT stat("/bin/missingcommand") = -1 ENOENT stat("/usr/bin/missingcommand") = -1 ENOENT stat("/usr/local/sbin/missingcommand") = -1 ENOENT stat("/usr/sbin/missingcommand") = -1 ENOENT stat("/sbin/missingcommand") = -1 ENOENT write(2, "sh: missingcommand: command not "..., 38) $ > echo $PATH | tr : “\n” /usr/lib64/qt-3.3/bin /usr/pgsql-9.1/bin /usr/local/go/bin /usr/local/bin /bin /usr/bin /usr/local/sbin /usr/sbin /sbin $PATH
  20. $ > echo $GEM_PATH | tr : "\n" /Users/jackdanger/.gem/ruby/2.2.2 /Users/jackdanger/.rubies/ruby-2.2.2/lib/ruby/gems/2.2.0

    $ > ruby -e 'p Gem.default_path.split(":")' /Users/jackdanger/.gem/ruby/2.2.2 /Users/jackdanger/.rubies/ruby-2.2.2/lib/ruby/gems/2.2.0 $GEM_PATH
  21. $ > echo $GEM_PATH | tr : "\n" /Users/jackdanger/.gem/ruby/2.2.2 /Users/jackdanger/.rubies/ruby-2.2.2/lib/ruby/gems/2.2.0

    $ > export GEM_HOME=/tmp/lolwut $ > export GEM_PATH=/tmp/lolwut:$GEM_PATH $ > gem install eallydumb $ > gem list # now includes ‘eallydumb’ $ > ls /tmp/lolwut # behold it is there $GEM_PATH
  22. $ > echo $GEM_PATH | tr : "\n" /Users/jackdanger/.gem/ruby/2.2.2 /Users/jackdanger/.rubies/ruby-2.2.2/lib/ruby/gems/2.2.0

    $ > export GEM_HOME=/tmp/lolwut $ > export GEM_PATH=/tmp/lolwut:$GEM_PATH $ > gem install eallydumb $ > gem list # now includes ‘eallydumb’ $ > ls /tmp/lolwut # behold it is there $GEM_PATH
  23. $GEM_PATH $PATH Colon-separated list of directories in which to find

    an executable Where `gem install` puts stuff $GEM_HOME $GEM_PATH Colon-separated list of directories in which to find a gem
  24. $ > ruby -r pp -e 'pp $LOAD_PATH' ["/usr/lib/ruby/site_ruby/1.8", "/usr/lib64/ruby/site_ruby/1.8",

    "/usr/lib/ruby/site_ruby", "/usr/lib64/ruby/site_ruby", "/usr/lib64/site_ruby/1.8", "/usr/lib64/site_ruby/1.8/x86_64-linux", "/usr/lib64/site_ruby", "/usr/lib/ruby/1.8", "/usr/lib64/ruby/1.8", "/usr/lib64/ruby/1.8/x86_64-linux"]] $LOAD_PATH
  25. $ > strace ruby -e 'require "missingfile"' execve("/usr/bin/ruby", ["ruby", "-e",

    "require \"missingfile\""], [/* 38 vars */]) = 0 stat("/usr/lib/ruby/site_ruby/1.8/missingfile.rb") = -1 ENOENT stat("/usr/lib/ruby/site_ruby/1.8/missingfile.so") = -1 ENOENT stat("/usr/lib64/ruby/site_ruby/1.8/missingfile.rb") = -1 ENOENT stat("/usr/lib64/ruby/site_ruby/1.8/missingfile.so") = -1 ENOENT stat("/usr/lib/ruby/site_ruby/missingfile.rb") = -1 ENOENT stat("/usr/lib/ruby/site_ruby/missingfile.so") = -1 ENOENT stat("/usr/lib64/ruby/site_ruby/missingfile.rb") = -1 ENOENT stat("/usr/lib64/ruby/site_ruby/missingfile.so") = -1 ENOENT stat("/usr/lib64/site_ruby/1.8/missingfile.rb") = -1 ENOENT stat("/usr/lib64/site_ruby/1.8/missingfile.so") = -1 ENOENT stat("/usr/lib64/site_ruby/missingfile.rb", 0x7ffffeeca290) = -1 ENOENT stat("/usr/lib64/site_ruby/missingfile.so", 0x7ffffeeca290) = -1 ENOENT stat("/usr/lib/ruby/1.8/missingfile.rb", 0x7ffffeeca290) = -1 ENOENT $LOAD_PATH
  26. $LOAD_PATH $ > ruby -r pp -e 'pp $LOAD_PATH' [“/usr/lib/ruby/site_ruby/1.8",

    "/usr/lib64/ruby/site_ruby/1.8", "/usr/lib/ruby/site_ruby", "/usr/lib64/ruby/site_ruby", "/usr/lib64/site_ruby/1.8", "/usr/lib64/site_ruby", "/usr/lib/ruby/1.8", "/usr/lib64/ruby/1.8"]] $ > strace ruby -e 'require "missingfile"' execve("/usr/bin/ruby", ["ruby", "-e", "require \"mis stat("/usr/lib/ruby/site_ruby/1.8/missingfile.rb") = stat("/usr/lib/ruby/site_ruby/1.8/missingfile.so") = stat("/usr/lib64/ruby/site_ruby/1.8/missingfile.rb") stat("/usr/lib64/ruby/site_ruby/1.8/missingfile.so") stat("/usr/lib/ruby/site_ruby/missingfile.rb") = -1 E stat("/usr/lib/ruby/site_ruby/missingfile.so") = -1 E stat("/usr/lib64/ruby/site_ruby/missingfile.rb") = -1 stat("/usr/lib64/ruby/site_ruby/missingfile.so") = -1 stat("/usr/lib64/site_ruby/1.8/missingfile.rb") = -1 stat("/usr/lib64/site_ruby/1.8/missingfile.so") = -1 stat("/usr/lib64/site_ruby/missingfile.rb", 0x7ffffee stat("/usr/lib64/site_ruby/missingfile.so", 0x7ffffee stat("/usr/lib/ruby/1.8/missingfile.rb", 0x7ffffeeca2 stat("/usr/lib/ruby/1.8/missingfile.so", 0x7ffffeeca2 stat("/usr/lib64/ruby/1.8/missingfile.rb", 0x7ffffeec stat("/usr/lib64/ruby/1.8/missingfile.so", 0x7ffffeec
  27. $LOAD_PATH $ > ruby -r pp -e 'pp $LOAD_PATH' [“/usr/lib/ruby/site_ruby/1.8",

    "/usr/lib64/ruby/site_ruby/1.8", "/usr/lib/ruby/site_ruby", "/usr/lib64/ruby/site_ruby", "/usr/lib64/site_ruby/1.8", "/usr/lib64/site_ruby", "/usr/lib/ruby/1.8", "/usr/lib64/ruby/1.8"]] $ > strace ruby -e 'require "missingfile"' execve("/usr/bin/ruby", ["ruby", "-e", "require \"mis stat("/usr/lib/ruby/site_ruby/1.8/missingfile.rb") = stat("/usr/lib/ruby/site_ruby/1.8/missingfile.so") = stat("/usr/lib64/ruby/site_ruby/1.8/missingfile.rb") stat("/usr/lib64/ruby/site_ruby/1.8/missingfile.so") stat("/usr/lib/ruby/site_ruby/missingfile.rb") = -1 E stat("/usr/lib/ruby/site_ruby/missingfile.so") = -1 E stat("/usr/lib64/ruby/site_ruby/missingfile.rb") = -1 stat("/usr/lib64/ruby/site_ruby/missingfile.so") = -1 stat("/usr/lib64/site_ruby/1.8/missingfile.rb") = -1 stat("/usr/lib64/site_ruby/1.8/missingfile.so") = -1 stat("/usr/lib64/site_ruby/missingfile.rb", 0x7ffffee stat("/usr/lib64/site_ruby/missingfile.so", 0x7ffffee stat("/usr/lib/ruby/1.8/missingfile.rb", 0x7ffffeeca2 stat("/usr/lib/ruby/1.8/missingfile.so", 0x7ffffeeca2 stat("/usr/lib64/ruby/1.8/missingfile.rb", 0x7ffffeec stat("/usr/lib64/ruby/1.8/missingfile.so", 0x7ffffeec /usr/lib/ruby/site_ruby/1.8 /usr/lib/ruby/site_ruby/1.8/missingfile.rb
  28. $LOAD_PATH $ > ruby -r pp -e 'pp $LOAD_PATH' [“/usr/lib/ruby/site_ruby/1.8",

    "/usr/lib64/ruby/site_ruby/1.8", "/usr/lib/ruby/site_ruby", "/usr/lib64/ruby/site_ruby", "/usr/lib64/site_ruby/1.8", "/usr/lib64/site_ruby", "/usr/lib/ruby/1.8", "/usr/lib64/ruby/1.8"]] $ > strace ruby -e 'require "missingfile"' execve("/usr/bin/ruby", ["ruby", "-e", "require \"mis stat("/usr/lib/ruby/site_ruby/1.8/missingfile.rb") = stat("/usr/lib/ruby/site_ruby/1.8/missingfile.so") = stat("/usr/lib64/ruby/site_ruby/1.8/missingfile.rb") stat("/usr/lib64/ruby/site_ruby/1.8/missingfile.so") stat("/usr/lib/ruby/site_ruby/missingfile.rb") = -1 E stat("/usr/lib/ruby/site_ruby/missingfile.so") = -1 E stat("/usr/lib64/ruby/site_ruby/missingfile.rb") = -1 stat("/usr/lib64/ruby/site_ruby/missingfile.so") = -1 stat("/usr/lib64/site_ruby/1.8/missingfile.rb") = -1 stat("/usr/lib64/site_ruby/1.8/missingfile.so") = -1 stat("/usr/lib64/site_ruby/missingfile.rb", 0x7ffffee stat("/usr/lib64/site_ruby/missingfile.so", 0x7ffffee stat("/usr/lib/ruby/1.8/missingfile.rb", 0x7ffffeeca2 stat("/usr/lib/ruby/1.8/missingfile.so", 0x7ffffeeca2 stat("/usr/lib64/ruby/1.8/missingfile.rb", 0x7ffffeec stat("/usr/lib64/ruby/1.8/missingfile.so", 0x7ffffeec /usr/lib/ruby/site_ruby/1.8 /usr/lib/ruby/site_ruby/1.8/missingfile.rb
  29. $LOAD_PATH $ > echo 'puts :hi' > myfile.rb $ >

    ruby -e 'require "myfile"' /usr/ruby/lib64/ruby/2.0.0/rubygems/core_ext/ kernel_require.rb:55:in `require': cannot load such file -- myfile (LoadError) from /usr/ruby/lib64/ruby/2.0.0/rubygems/core_ext/ kernel_require.rb:55:in `require' from -e:1:in `<main>'
  30. $LOAD_PATH $ > echo 'puts :hi' > myfile.rb $ >

    ruby -e '$LOAD_PATH << "."; require "myfile"' hi
  31. $LOAD_PATH $ > echo 'puts :hi' > myfile.rb $ >

    ruby -I . -e 'require "myfile"' hi
  32. How Bundler works irb:0> $LOAD_PATH << "~/.gems/2.2.0/active_record-4.1.0/lib/" irb:1> $LOAD_PATH <<

    "~/.gems/2.2.0/actionpack-4.1.0/lib/" irb:2> $LOAD_PATH << "~/.gems/2.2.0/rake-2.3.4/lib" $ > export RUBYOPT="-rbundler/setup"
  33. ENV vars Flags $ > export RUBYLIB=. $ > ruby

    -I . (ruby -e “$LOAD_PATH << ‘.’”)
  34. ENV vars $ > export RUBYLIB=. Flags $ > ruby

    -I . $ > export RUBYOPT=“-r rails” $ > ruby -r rails (ruby -e “$LOAD_PATH << ‘.’”)
  35. ENV vars $ > export RUBYLIB=. Flags $ > ruby

    -I . $ > export RUBYOPT=“-r rails” $ > ruby -r rails (ruby -e “$LOAD_PATH << ‘.’”) $ > export RUBYOPT="-I /fakedir -I . -r rails” $ > ruby -e ‘p Rails’ Rails
  36. • Rubygems • Rip • RVM • Bundler • rbenv

    • chruby 2003 (!!) 2009 2009 2009 2011 2012
  37. What Ruby cares about $LOAD_PATH Array of directories in which

    to find a file that’s been require()’d Flags to pass to ruby every time it’s run $RUBYOPT $RUBYLIB A colon-separated list of directories to add to the $LOAD_PATH
  38. What RVM* Cares about $PATH Array of directories in which

    to find an executable ‘ruby’, ‘rake’, etc. $GEM_PATH Colon-separated list of directories in which to find a gem Where to install gems $GEM_HOME * and rbenv, chruby, …
  39. What Rubygems cares about $GEM_PATH Colon-separated list of directories in

    which to find a gem Where to install gems $GEM_HOME
  40. What I recommend: Go through the exercises in these slides

    yourself Try replacing RVM and rbenv with chruby https://github.com/postmodern/chruby
  41. Q&A