← Back

blagblogblag.com

A small island in the vast internet ocean

The Unix shebang (#!)

2013-06-20

The Unix shebang is the first line in a typical executable Unix script. For example a an executable Python script called ‘hello’ can be run by writing ./hello on the command line, instead of writing out the full command python hello, given that the first line in the script is

#!/usr/bin/python

This line tells that the script should be run by using the Python interpreter located at /usr/bin/python. E.g.

> cat hello 
#!/usr/bin/python
print 'Hello World!'
> ./hello
Hello World!

One would think that the shell, e.g. bash or zsh interprets this line and executes the proper script interpreter. But it’s not the shell – it’s actually the kernel that interprets this line.
(For further reference check out https://www.in-ulm.de/~mascheck/various/shebang/)

I found this out when trying to use Python virtualenv which creates .venv/bin/pip. The pip file is a Python script with a shebang in the beginning – in this case something along the lines of

#!"/Users/Malthe/python project/.venv/bin/python"

Here virtualenv has quoted the path because it has a space in it. But this doesn’t work on OS X 10.7 (I haven’t tested on other systems).

I haven’t found a solution yet (working on it). The XNU (Mac OS X) kernel code parsing the shebang can be found here beginning at line 432.

So I wrote a file test to check out the behaviour:

#!/bin/exec-space arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 arg11 arg12

With exec-space being:

#!/bin/sh
echo $0
echo $1
echo $2
echo $3
echo $4

Running ./test in fish gives the following error

> ./test
Failed to execute process './test'. Reason:
exec: Exec format error
The file './test' is marked as an executable but could not be run by the operating system.

bash does nothing

> ./test
>

zsh does something

> ./test
/bin/exec-space
arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 a
./test

The result from zsh show that all arguments are concatenated intro $1 but truncated after some number of characters. The morale of the story is then to not use virtualenv in neither paths containing spaces nor long paths. I guess computer software still lives in 1300 BC…

A guy called Steve Smith found out the same thing a couple of years ago: https://stevesmithbytes.blogspot.com/2011/02/handling-spaces-in-shebang-line-in-mac.html