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

The Ruby Environment Variable API

The Ruby Environment Variable API

Avatar for Jack Danger Canty

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