Шебанг, указывающий на script (также имеющий shebang), фактически игнорируется

Рассмотрим следующий код:

#!/usr/bin/env python

import sys

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

Это chmod +x ed script в /usr/local/bin/my_interpreter. И это:

#!/usr/local/bin/my_interpreter

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

Является chmod +x ed script, который пытается его использовать. Если я echo something | /usr/local/bin/my_interpreter, он работает нормально, но как только я попытаюсь выполнить script выше, он терпит неудачу с

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

Кажется, что foo.bar тихо перенаправляется на bash вместо моего script. Что я делаю не так? Как это сделать?

Ответы

Ответ 1

Похоже, что для Mac OS X требуется, чтобы интерпретатор был двоичным, а не другим script. Чтобы заставить его работать, измените второй интерпретатор script на

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

Но у вас есть вторая проблема: содержимое второго script будет не переходить к stdin его интерпретатора, но путь script будет передан как команда line, т.е.

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

Вы должны прочитать файл по имени sys.argv[1], а не от sys.stdin.

Ответ 2

Это зависит от программного загрузчика операционной системы, в которой вы работаете, и я использую OS X из ваших тегов. Многие UNIX-подобные операционные системы требуют, чтобы интерпретатор shebang был скомпилированным исполняемым двоичным кодом, а не другим script с другим shebang.

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

Linux поддерживал это с 2.6.27.9, но автор этой статьи предполагает, что, вероятно, не существует никакого Berkeley-Unixen (который, вероятно, будет включать OS X):

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

Один из способов выполнить то, что вы хотите, будет примерно таким:

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

... content to be executed ...
EOM

Другим способом было бы что-то вроде этого:

$!/usr/bin/env /usr/local/bin/my_interpreter
... content to be executed ...