Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Rails runner shebang not work on Debian but work on OS X?

I have a Rails script that I run on both OS X Lion and Debian GNU/Linux 7.0 (wheezy). It's down to a simple script:

#!/usr/bin/env /opt/thermyos.com/server/script/rails runner
ENV.each do |k, v|
  puts "#{k} = #{v}"
end

The issue is the /usr/bin/env. This script as shown will not run on Debian, producing the error /usr/bin/env: /opt/thermyos.com/server/script/rails runner: No such file or directory. On OS X it works fine, writing the Rails environment. But if I remove the /usr/bin/env so the shebang is #!/opt/thermyos.com/server/script/rails runner then it works fine on Debian but not on OS X (Rails is not loaded and so every line fails). It doesn't matter where I launch the script from or whether I use a relative or absolute path. The printed environments are nearly identical. Why the failure on Debian, as it's exactly the shebang output by just running rails runner? FWIW, /opt/thermyos.com/ is exported from Debian and NFS-mounted on OS X.

like image 276
RussK Avatar asked May 22 '13 18:05

RussK


2 Answers

This is happening because the shebang operation on Linux doesn't split arguments.

As a result, env is looking for a file with spaces in the name i.e. trying to execute /opt/thermyos.com/server/script/rails runner with no arguments.

On OS X, the situation differs. The shebang in OS X does split arguments and therefore env executes the file at /opt/thermyos.com/server/script/rails with the argument runner.

One workaround is to use a wrapper script e.g. the form

#!/bin/sh
exec /path/to/script/rails runner /path/to/your_script.rb

should work on either OS. (whether the paths are hard-coded, computed, relative, or locally configured depends on your circumstances)

like image 66
inopinatus Avatar answered Oct 11 '22 01:10

inopinatus


You can do this in one file without using a wrapper.

Make a ruby script and put this at the top:

exec("/path/to/script/rails","runner",$0,*ARGV) unless defined?(Rails)

Or:

exec("/usr/bin/env","rails","runner",$0,*ARGV) unless defined?(Rails)

More info and a more ridiculous solution available at:

http://solutions.davesource.com/20161216.Shebang-That-Calls-Ruby-Rails-Script-With-Arguments.html

like image 23
David Ljung Madison Stellar Avatar answered Oct 11 '22 01:10

David Ljung Madison Stellar