Make a Ruby Script Executable
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:
- Shebang: start the script by instructing the shell what executable to use to run the script:
#!/usr/bin/env {executable}
- Verify that the script is being called directly
- 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
- Shebang: https://en.wikipedia.org/wiki/Shebang_(Unix)
- GNU
env
: https://man7.org/linux/man-pages/man1/env.1.html - FreeBSD
env
: https://www.freebsd.org/cgi/man.cgi?query=env&sektion=1 - Ruby pre-defined globals: https://ruby-doc.org/core-3.0.1/doc/globals_rdoc.html
- GNU
chmod
: https://www.gnu.org/software/coreutils/manual/html_node/chmod-invocation.html - FreeBSD
chmod
: https://www.freebsd.org/cgi/man.cgi?chmod