exec system call of the Linux kernel understands shebangs (
When you do on bash:
on Linux, this calls the
exec system call with the path
This line of the kernel gets called on the file passed to
if ((bprm->buf != '#') || (bprm->buf != '!'))
This reads the very first bytes of the file, and compares them to
If that is true, then the rest of the line is parsed by the Linux kernel, which makes another
exec call with path
/usr/bin/env python and the current file as the first argument:
/usr/bin/env python /path/to/script.py
and this works for any scripting language that uses
# as a comment character.
And yes, you can make an infinite loop with:
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
Bash recognizes the error:
-bash: /a: /a: bad interpreter: Too many levels of symbolic links
#! just happens to be human readable, but that is not required.
If the file started with different bytes, then the
exec system call would use a different handler. The other most important built-in handler is for ELF executable files: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 which checks for bytes
7f 45 4c 46 (which also happen to be human readable for
.ELF). This reads the ELF file, puts it into memory correctly, and starts it running. See also: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861
Finally, you can add your own shebang handlers with the
binfmt_misc mechanism. For example, you can add a custom handler for
.jar files. This mechanism even supports handlers by file extension. Another application is to transparently run executables of a different architecture with QEMU.
I don't think POSIX specifies shebangs, however: https://unix.stackexchange.com/a/346214/32558, although it does mention it in rationale sections, and in the form "if executable scripts are supported by the system something may happen".