Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shebang pointing to script (also having shebang) is effectively ignored

Tags:

bash

shell

macos

Consider following code:

#!/usr/bin/env python

import sys

print "Hello! I've got %r as input." % sys.stdin.read()

This is chmod +xed script in /usr/local/bin/my_interpreter. And this:

#!/usr/local/bin/my_interpreter

This is intended to be passed "as is" to python script.

Is chmod +xed script that tries to make use of it. If I echo something | /usr/local/bin/my_interpreter, it works fine, but once I try to execute script above, it fails with

/Users/modchan/test_interpreter/foo.bar: line 3: This: command not found

Seems that foo.bar is silently redirected to bash instead of my script. What am I doing wrong? How to make this work?

like image 225
toriningen Avatar asked Apr 03 '12 06:04

toriningen


2 Answers

Looks like Mac OS X requires interpreter to be binary, not another script. To make it work, change the second script's interpreter to

#!/usr/bin/env /usr/local/bin/my_interpreter

But you've got a second problem here: the contents of the second script will not go to stdin of its interpreter, but the script pathname will be passed as command line argument, i.e.

/usr/bin/env /usr/local/bin/my_interpreter /Users/modchan/test_interpreter/foo.bar

You shall read the file by name sys.argv[1] rather than from sys.stdin.

like image 180
hamstergene Avatar answered Nov 01 '22 06:11

hamstergene


This depends on the program loader of the operating system you're running, which I take to be OS X from your tags. Many UNIX-like operating systems require the shebang interpreter to be a compiled executable binary, not another script with another shebang.

http://en.wikipedia.org/wiki/Shebang_(Unix)

Linux has supported this since 2.6.27.9, but the author of this article suggests that there probably aren't any Berkeley-derived Unixen (which would probably include OS X) that do:

http://www.in-ulm.de/~mascheck/various/shebang/#interpreter-script

One way to accomplish what you want would be something like this:

$!/bin/sh
exec /usr/local/bin/my_interpreter <<EOM

... content to be executed ...
EOM

Another way would be something like this:

$!/usr/bin/env /usr/local/bin/my_interpreter
... content to be executed ...
like image 6
A B Avatar answered Nov 01 '22 08:11

A B