How does the so-called shebang or (hash-bang) work
When the OS is asked to load a program with the exec()
system call,
the OS needs to know something about the program it's loading. Ordinarily
it's a compiled executable (in the so-called ELF format) like what you
get when you invoke the compiler.
However, Unix has also traditionally provided a method to specify instead
a custom interpreter. If the first 2 bytes of an executable are #!
, then
Unix will interpret whatever follows this as the name of a program that
it will invoke instead. The name of the program - really a command line -
ends with a newline. To this command it adds the name of the program.
So if you say #!/usr/bin/env python3
at the beginning of your script
script.py
, you're really saying that if someone tries to exec() this
executable (it must have the +x bit, or executable bit, for that),
the OS should instead run /usr/bin/env python3 script.py
.
Now you need to learn what /usr/bin/env
does - it's a command that
allows you to manipulate the environment and then starts another program.
Here, we're not asking it to manipulate the environment at all (that would
be env VARIABLE=value ...
) - but just to start the python3
program.
The reason people recommend #!/usr/bin/env python3
over
#!/usr/bin/python3
is that the former will use the execvp
system call that respects the user's PATH. See also: How do
environment variables work in Unix, and how does PATH
work in
particular?