Ashok Gautham Jadatharan

Ruby shebang behavior

Ruby has a surprising hack in its interpreter. If the file starts with a shebang line, ruby will skip all lines until it encounters a shebang line which contains the string "ruby" in it.

This lets you start out as a shell script and then after some setup switch over to ruby

#!/bin/bash

rvm use 3.3.4

exec ruby $0 "$@"

echo "I am a bash line too but I will never run"

#!/usr/bin/env ruby
puts "I run in ruby"

There is some ugliness to this hack though. The interpreter only looks for the word "ruby" so the shebang line could be whatever including.

#!/bin/bash

rvm use 3.3.4

exec ruby $0 "$@"

echo "I am a bash line too but I will never run"

#!/I/am/a/rubyist
puts "I run in ruby"

will work but

#!/bin/bash

rvm use 3.3.4

exec ruby $0 "$@"

echo "I am a bash line too but I will never run"

#!/bin/rb
puts "I run in ruby"

will result in a print of "no Ruby script found in input"

Source: ruby.c#L2681


I am not a fan of such hacks in a language. Python lets you do something similar too - but it takes advantage of the fact that triple-quoted strings are side-effect free in Python and """": is the same as just a : which is two empty strings followed by a true in bash.

#!/bin/bash
'''':
source /path/to/venv/bin/activate.sh

exec python $0 "$@"

echo "I am a bash line too but I will never run"
'''

print("I am in python")