Digging Into A Ruby Installation, Require vs Load And Other Stuff

RubyWhenever I learn a new language I always want to know how the language does its work at more than just a superficial level. I admit that if you want to just be a casual user of a language (or library for that matter), this is not really necessary, but if you want to take a step towards mastering a language this is required knowledge. For my latest dive into Ruby, I decided to look at the the ruby installation and how we load the various libraries that we use.

The Ruby Installation

If you want to know where things live in your Ruby installation, there is an easy way to find out. Ruby stores a lot of information about itself in a big hash (just like environment variables):

Update: As per the comments below, Config is an object provided by the RubyGems library, so you will likely need to require ‘rubygems’ before you will be able to use it.

Config::CONFIG

If you get a list of keys from this hash, you can find out about all sorts of interesting info that Ruby knows about itself, but the most interesting bits are probably the following:

Config::CONFIG['bindir']
Config::CONFIG['rubylibdir']
Config::CONFIG['sitedir']/Config::CONFIG['vendordir']
Config::CONFIG['archdir']

Feel free to explore the others though there are interesting things to find there.

  • bindir – this is where the ruby installation will have it’s executables, such as the interpreter – ruby, irb, ri, rdoc etc. (in my case C:/ruby1.8/bin)
  • rubylibdir – this is where most of the Ruby standard libraries live (in my case C:/ruby1.8/lib/ruby/1.8). I say most because most Ruby libraries are written in Ruby as you would expect, however some are written in C and are therefore specific to the installation of Ruby (i.e. what platform you’re on), these don’t live here but instead reside in ‘_archdir_’.
  • archdir – this is the brother of ‘rubylibdir’ for all native libraries that are written in C (in my case C:/ruby1.8/lib/ruby/1.8/i386-mswin32). You’ll mostly find a bunch of C header files (.h) here as well as .so (in my case) or potentially some others (.dll maybe?).
  • sitedir/vendordir – these are actually two separate directories, but ‘vendordir’ is only applicable to Ruby 1.9. Essentially any extensions you develop yourself (or find lying around I guess :)) that are not gems will find a home here. These will be similar in structure to ‘rubylibdir’ Ruby native stuff will go directly here but there will also be an ‘archdir’ equivalent for your architecture specific stuff. My ‘sitedir’ was C:/ruby1.8/lib/ruby/site_ruby.

But what about gems? Well, that brings us to how we use the various libraries in our ruby programs.

Require vs Load

Normally when we want to use a feature in our Ruby program (be it gem or standard library), we would include it in our file using the require keyword, (we are all aware that load exists, but require is what all the big boys use). So what is the difference?

Load

To load a file we use the load method:

load ‘blah.rb’

Note that we must supply the extension when we use it. When Ruby encounters a load, it will read in the contents of the file you’re trying to load. It will do this every time. No matter how many times you load the same feature, Ruby will read the file in every time it encounters a load. You’re not limited to just supplying a name and extension though, you can navigate directories e.g.:

load ‘../../blah.rb’

or even give an absolute path:

load ‘/a/b/c/blah.rb’

But how will Ruby find these files?

How Ruby Finds Stuff

By default Ruby has a list of directories that it searches to find features you want to load – the load path. This is stored in a special variable:

$:

By default the load path will include the ‘rubylibdir’, ‘archdir’, ‘sitedir’, ‘vendordir’ etc. The last thing on the load path will always be the current working directory (i.e. . – ‘dot’), which is the directory from which you launched your application (unless you jump directories as your program is executing). The load path will not by default include anything to do with ruby gems. So how does Ruby find anything to do with gems? Lets talk about require before dealing with gems.

Require

No matter how many times you require the same feature in your program, only the first time is significant. Ruby will not re-read a file a second time, this is the first fundamental difference from how load works. The other obvious difference is the fact that you don’t need to supply an extension when you require a feature:

require ‘blah’

This allows us to treat features written in Ruby in exactly the same way as extensions written in C, Ruby is smart enough to work it out. These are basically the two major differences between require and load. Obviously as I mentioned, require is what most people will use day-to-day, but as long as we are aware of the differences, load can be useful too. And by the way, just like load, you can supply a relative or absolute path to require (as long as you leave the extension off).


How Ruby Finds Gem Stuff

As I mentioned the load path does not contain anything to do with gems by default. This is due to the fact that you can have multiple versions of the same gem installed on your system (and can actually use any of the versions you have installed), and so the load path is appended to (actually it is prepended to rather than appended to) dynamically as the program executes when you want to include a feature provided by a gem.

By default when you install gems they will go into the same place where ruby is installed, one level back from where ‘rubylibdir ’ is, in my case (C:\ruby1.8\lib\ruby\gems). Ruby will know about this when it needs to dynamically modify the load path, this is where it will look for gems. Ruby will not by default know that it needs to look for gems, so you will need to tell it to do so. There are several ways of doing this:

  • use require ‘rubygems’ in your code, before you include any features from gems. This is fine for your own code, but programs that you download that did not do this, will not work.
  • use –rubygems command like option when you launch your Ruby program.
  • use the RUBYOPT environment variable (e.g. RUBYOPT=rubygems). This is probably the easiest and most painless way.

If you have this set up then when you require something from a gem, Ruby will know to search the place where your gems are and will modify the load path dynamically to include the location of the gem you want (if there are multiple versions of the same gem, by default Ruby will use the latest version). For example:

>> puts $:
C:/ruby1.8/lib/ruby/site_ruby/1.8
C:/ruby1.8/lib/ruby/site_ruby/1.8/i386-msvcrt
C:/ruby1.8/lib/ruby/site_ruby
C:/ruby1.8/lib/ruby/1.8
C:/ruby1.8/lib/ruby/1.8/i386-mswin32
.

>> require 'hpricot'

>> puts $:
C:/ruby1.8/lib/ruby/gems/1.8/gems/hpricot-0.8.1-x86-mswin32/bin
C:/ruby1.8/lib/ruby/gems/1.8/gems/hpricot-0.8.1-x86-mswin32/lib
C:/ruby1.8/lib/ruby/site_ruby/1.8
C:/ruby1.8/lib/ruby/site_ruby/1.8/i386-msvcrt
C:/ruby1.8/lib/ruby/site_ruby
C:/ruby1.8/lib/ruby/1.8
C:/ruby1.8/lib/ruby/1.8/i386-mswin32
.

One final caveat to be aware of is this. If you can’t install gems into the default location, you will need to tell Ruby where the gems will go (and where to find them subsequently). You do this using the GEM_HOME environment variable. As long as you have it set, everything will still function as expected.

Image by jaja_1985

How People Can Get You To Do What They Want

AuthorityAs a software developer I love to code, but over the last year I have been gaining more and more of an appreciation for marketing (it’s what makes the world go ‘round, that and money, if you can believe the song) and therefore I follow quite a few blogs that deal with the subject. One of the best blogs about online marketing right now is Brian Clark’s Copyblogger, so when Brian recently released a free report titled “Authority Rules” I had to have a read. Imagine my surprise when the report kicked off by describing the Milgram experiment. The reason I was so surprised was that I had an interesting discussion on the Milgram experiment just few days ago in a Lean workshop me and some of my colleagues did with Jason Yip. There are several important lessons that The Milgram experiment can teach us and so I believe it is well worth sharing, as the more people know about it the better.

The Milgram Experiment

I am quoting most of this from Brian’s report:

Let’s say you see a newspaper ad saying the psychology department at Yale is running a little “experiment on memory.” Paid volunteers are needed for the hour-long study, so you figure why not? Upon arrival at the lab, you meet two men — a research scientist in a lab coat, and another volunteer just like yourself. The researcher proceeds to explain the study to you both. He tells you the study is about the effects of punishment on memory. The task of the other volunteer will be to learn a series of word pairings (he’s called the “Learner”). Your job as the “Teacher” will be to test the Learner’s memory of the word pairs, and administer electric shocks for each wrong answer. And for every new wrong answer, the voltage goes up.You’re not sure about this whole thing, but it must be okay, right?

The testing begins, and when the other volunteer misses a question, you pull a lever that delivers a mild shock. Over time, though, the shock levels increase, and the Learner is grunting audibly. At 120 volts, he tells you the shocks are really starting to hurt. At 150 volts, he tries to quit. The researcher tells you to keep going, and that the shocks will cause “no permanent tissue damage” to the Learner. You continue questioning and delivering punishment for incorrect answers. At 165 volts, the Learner screams. At 300 volts, the Learner refuses to respond any longer, as the shocks are impairing his mental capacities. The researcher tells you to treat non-responses as incorrect answers.The Learner is screeching, kicking, and pleading for mercy with every subsequent shock, all the way up to 450 volts when the researcher finally stops you.

Scary story.

This couldn’t possibly have really happened, right? Well, actually, it did, in 1963 at Yale, during a series of experiments by Stanley Milgram. But here’s the real scoop about the Milgram experiment:

  • there were no actual electric shocks
  • the Learner was an actor
  • the study had nothing to do with memory

What Milgram wanted to know was how far the Teachers would go when told to continue to deliver those shocks, since they thought they really were. About two-thirds (65%) of the subjects administered every shock up to 450 volts, no matter how much the Learner begged for mercy. However, without the researcher’s encouragement to continue, the study found that the test subjects would have stopped giving punishment quite early on.

What Lessons Can We Learn From This

This experiment has been used before to explain how during war-time some people can commit horrendous atrocities and their peers wouldn’t try to stop them, but would infact go along with it to the point of becoming directly involved in committing the atrocities themselves (e.g. the holocaust during World War 2). One of the lessons we can learn from this is the fact that people would tend to go along with someone they consider to have authority even if by doing so they go against their better judgment. There are numerous ways we can justify our actions afterwards (only following orders, didn’t know any better etc.), but at the end of the day it comes down to the fact that when we believe that someone knows more than us about a subject, they can get us to do what they want most of the time (or 65% of the time if you can believe the experiment).

The thing is though, even though we do it, it will often be with strong reservations, which means our own mind and judgment are still very much in play. So, why do we, so often let our moral compass be overridden by external factors? And this, I believe leads us to the second and most important lesson we can glean from the Milgram experiment. Trust your instincts, ask questions, challenge those around you no matter how expert you think they are (if their position is strong they will be able to defend it with cool logical argument, without misdirection). This is true for any software project (but is also true for life in general), it is every developers’ responsibility to question processes, patterns and yes, even code, that you believe can lead to trouble. If everyone on a team has this kind of attitude, then you will never be an outcast for doing this, but rather the whole team will either fill you in on what you’re missing or will work together with you to fix or mitigate the issues that were brought up. This, in my opinion, is the crux of the Agile spirit (it would also be a great example of leadership regardless of whether you hold a leadership role or not). I for one would never want to be one of the 65% of people who would shock another human being to the point of insensibility. And so I’ll leave you with this question, what are you doing to make sure that if you find yourself in a ‘Milgram experiment’ type of situation, you’re not one of the 65% either?

Image by takomabibelot

Bash Shell Awesomeness – Mass Killing Processes (On Ubuntu)

I am not a Linux newbie, but neither am I an expert. So, I sometimes tend to come across some really cool stuff and I just have to share.

Here is the story. We use this application at work (I won’t point any fingers :)) which tends to run as a whole lot of processes when it starts up, and these processes don’t all have the same parent process either. Once in a while this application can get into a bad state where you have to manually kill all the processes to restart everything. Now as you might imagine this can be a bit of a pain since there are quite a few processes even if you only count the parents.

Here is where some bash magic comes to the rescue. Luckily for us, this application runs as a separate Linux user so all the processes have the same user id and we’re able to use the following command to kill everything in one fell swoop.

ps -ef | grep ^1002 | cut -c 5-15 | sudo xargs kill<br />

Here is a quick rundown of what it does:

  • the ps command is obvious, we get the processes that are currently active
  • we pipe the output to grep in order to find all the lines that begin with a particular id (this is the id of the user that runs the application)
  • we then pipe the output of that to the cut command to pull out characters 5 to 15 of every line (i.e. the process id will live in that character range)
  • we then pipe the output of that to xargs which lets us use each line of that output as an argument to the_ kill_ command, thereby killing all those processes (the sudo bit is really optional and you would use it only if your current user didn’t have permission to kill the processes)

Update: As Sam pointed out in the comments below kill -9 should only ever be used as a last resort as it will create ‘orphaned shared memory segments’ and is therefore best avoided if possible

I don’t know about you, but I thought that was pretty cool :). The only side-effect is that all processes owned by that particular user will get killed (i.e. if you have a shell opened as that user).

I wonder if there is an easier way of doing this with bash? And it would also be great if we didn’t have to kill all processes owned by a user, but rather could mass-kill a bunch of processes based on some other criteria. If anyone is a bash expert, feel free to supply some tips :).

Update: Apparently, according to the comments, there are a number of way of doing this, using either a shorter pipeline or even just one command that would even let you pick particular processes based on criteria _(e.g. pkill)_. Have a look through the comments for details. Thanks to all the commenters for the great feedback!