When we write scripts, we often want to run them from the shell. There is a pattern common to most scripting languages for making a script executable:

  1. Shebang: start the script by instructing the shell what executable to use to run the script: #!/usr/bin/env {executable}
  2. Verify that the script is being called directly
  3. Make the script executable with chmod +x

Here is how that pattern can be applied to Ruby scripts.

#!Shebang

To tell the shell what program to run when the shell invokes the Ruby script, start the script with a “shebang”* line:

#!/usr/bin/env ruby

Using /usr/bin/env loads the first ruby that is found in our PATH. This allows us to avoid hard-coding the full path to ruby– handy when multiple rubies are installed or are installed in different locations on different systems, e.g. /usr/bin/ruby, /usr/local/bin/ruby, /opt/local/bin/ruby.

* Pronounced shuh-bang, sorry, Ricky Martin fans.

Verify that script is being executed

To avoid running the script when it is included from elsewhere as a file, verify that the script is the file that is being run:

if $PROGRAM_NAME==__FILE__
  puts :hello_world!
end

This is especially important when running the script results in changes or results in destructive actions, such as performing updates, moving files or deleting data or files.

I often start writing functionality by developing it in isolation in a dedicated script, and subsequently move that script’s functionality into the application’s library. Verifying that the script is being executed is a failsafe in case I forget to remove the executing code from the script, so that the functionality isn’t accidentally run when the new library is required or included from elsewhere in the application.

Make script executable

To make the script executable, in the shell run chmod +x on the script. Eg. for a file named named hello-world:

chmod +x hello-world

The script can then be invoked from the local directory by running:

./hello-world

Namespace All The Things

Using namespaces, eg. modules and classes, can help with organization. For example, a HelloWorld module with a run() method can be used to organize the hello-world functionality:

module HelloWorld
  def self.run
    puts :hello_world!
  end
end

Which would be called by running:

HelloWorld::run()

Putting it all together

Add the following code to the file hello-world:

#!/usr/bin/env ruby
module HelloWorld
  def self.run
    puts :hello_world!
  end
end

if $PROGRAM_NAME==__FILE__
  HelloWorld::run()
end

Make the script executable by running:

chmod +x hello-world

Run the script:

./hello-world

Which generates the output:

hello_world!

References