Shebang line limitations
Here at Zenoss, we had a need to run Python in a modified environment. A script was written (by a third party) wrapping the python
binary, and became `which python`
:
#!/bin/sh
. /path/to/setenv.sh
/path/to/.python.bin "$@"
This replaced the binary as the path to the interpreter.
Then we tested it. Most of the scripts in $ZENHOME/bin are shell scripts that call Python scripts elsewhere, but a few, including most of the ones laid down by Zope during the mkzopeinstance
installation step, are straight up Python scripts with the shebang #!/usr/local/zenoss/bin/python
($ZENHOME
in this case is /usr/local/zenoss
; distutils does a string replace of shebang lines during the install-scripts
step). When we tried to execute these scripts with the new Python wrapper in place, we got things like:
runtests: line 3: import: command not found<br />from: can't read /var/mail/subprocess<br />runtests: line 5: import: command not found<br />runtests: line 6: import: command not found<br />runtests: line 8: ZENHOME: command not found<br />runtests: line 9: syntax error near unexpected token `('<br />runtests: line 9: `ZOPEHOME = os.environ.get('ZOPEHOME', ZENHOME)'
/bin/sh
was trying to interpret the script. When we executed the shebang on the command line, we were thrown into the interpreter, so it wasn't a simple path problem. When we asked around, one of our more experienced developers knew the cause immediately: the shebang line has to point to a binary.
We figured we were pretty much sunk; among other things, the setenv.sh
script set the LD_LIBRARY_PATH
against which that Python binary had been compiled (the idea was that the binary could be portable that way), so we couldn't call it directly and set environment variables via Python, for example. Eventually we came up with a hacky but totally workable solution:
#!/usr/bin/env /path/to/my/wrapper/python
env
is a command meant to interact with environment variables and run other commands in modified environments. If you don't give it a modified environment, it'll use the current one, which makes it basically a pass-through; on the command line, env python
and python
are synonymous. /usr/bin/env
is, needless to say, a binary file.
I don't know why the shebang line has this limitation; presumably it's some security issue. But there's the solution, if you absolutely have to circumvent it: call your shell script through env.
December 5, 2008 at 3:20 PM
Thanks a lot, exactly what i was looking for!
god knows why they don't allow for calling scripts in a script directly...
Karsten