POSIX não especifica exatamente como o shebang deve ser interpretado. Citando a exec
família de funções RACIONAL :
One common historical implementation is that the execl(), execv(),
execle(), and execve() functions return an [ENOEXEC] error for any file not recognizable as executable, including a shell script. When
the execlp() and execvp() functions encounter such a file, they
assume the file to be a shell script and invoke a known command
interpreter to interpret such files. This is now required by
POSIX.1-2008. These implementations of execvp() and execlp() only
give the [ENOEXEC] error in the rare case of a problem with the
command interpreter's executable file. Because of these
implementations, the [ENOEXEC] error is not mentioned for execlp()
or execvp(), although implementations can still give it.
Another way that some historical implementations handle shell scripts
is by recognizing the first two bytes of the file as the character
string "#!" and using the remainder of the first line of the file as
the name of the command interpreter to execute.
One potential source of confusion noted by the standard developers is
over how the contents of a process image file affect the behavior of
the exec family of functions. The following is a description of the
actions taken:
If the process image file is a valid executable (in a format that is executable and valid and having appropriate privileges) for this
system, then the system executes the file.
If the process image file has appropriate privileges and is in a format that is executable but not valid for this system (such as a
recognized binary for another architecture), then this is an error and
errno is set to [EINVAL] (see later RATIONALE on [EINVAL]).
-
If the process image file has appropriate privileges but is not otherwise recognized:
If this is a call to execlp() or execvp(), then they invoke a command interpreter assuming that the process image file is a shell
script.
If this is not a call to execlp() or execvp(), then an error occurs and errno is set to [ENOEXEC].
E, mais cedo, na DESCRIPTION , diz que execlp
e execvp
devem executar scripts com sh
:
In the cases where the other members of the exec family of functions
would fail and set errno to [ENOEXEC], the execlp() and execvp()
functions shall execute a command interpreter and the environment of
the executed command shall be as if the process invoked the sh
utility using execl() as follows:
execl(<shell path>, arg0, file, arg1, ..., (char *)0);
where <shell path> is an unspecified pathname for the sh
utility, file is the process image file, and for execvp(), where
arg0, arg1, and so on correspond to the values passed to execvp() in argv[0], argv2, and so on.
Portanto, essas funções executam o equivalente a sh file ...
. E quando o script é executado a partir de um shell POSIX, os efeitos do shebang não são especificados. Veja 2.1, Introdução à Shell :
- The shell reads its input from a file (see sh), from the -c option or from the system() and popen() functions defined in the System Interfaces volume of POSIX.1-2008. If the first
line of a file of shell commands starts with the characters "
#!
",
the results are unspecified.
Zsh não se importa, o bash faz:
$ cat foo.sh
#! env perl
echo $0
$ zsh -c ./foo.sh
Can't locate object method "echo" via package "./foo.sh" (perhaps you forgot to load "./foo.sh"?) at ./foo.sh line 2.
$ bash -c ./foo.sh
bash: ./foo.sh: env: bad interpreter: No such file or directory
Não confie em não especificar PATH
lookups no shebang. (Eu sei que eu corri zsh -c ./foo.sh
em vez de zsh foo.sh
, no entanto, a intenção aqui era mostrar o que os shells fazem na execução de comandos podem diferir.)