Bash Script – Execute via Filename with and Without Shebang

bashshebangshell-script

From bash manual:

3.7.2 Command Search and Execution

After a command has been split into words, if it results in a simple
command and an optional list of arguments, the following actions are
taken.

  1. If the name is neither a shell function nor a builtin, and contains no slashes, Bash searches each element of $PATH for a directory
    containing an executable file by that name.

  2. If the search is successful, or if the command name contains one or more slashes, the shell executes the named program in a separate
    execution environment. Argument 0 is set to the name given, and the
    remaining arguments to the command are set to the arguments supplied,
    if any.

  3. If this execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a shell
    script
    and the shell executes it as described in Section 3.8 [Shell
    Scripts], page 39.

  1. Suppose a bash script myscript doesn't contain a shebang.

    • Does the quote mean that if the script is executed in bash via command myscript, then

      • bash will first assume it is an ELF and calls execve() on it, and because it is a bash script not ELF, execve() call will fail,

      • bash will next execute bash myscript?

    • Compared to running a bash script via bash myscript in bash, running the script via myscript in bash will additionally have a
      failure call to execve() on the script directly?

    • If yes, is myscript slower than bash myscript? Why does "A Practical Guide to Linux Commands, Editors, and Shell Programming By
      Mark G. Sobell
      " say the opposite?

      Although you can use bash to execute a shell script, this technique causes the script to run more slowly than giving yourself
      execute permission and directly invoking the script.

  2. If a bash script myscript contains a shebang #! /bin/bash, when
    it is executed in bash via command myscript,

    • is it executed in the same way as it is executed in bash via command bash myscript?

    • is it executed in the same way as the shebang were removed from the script and then the script were executed via command myscript
      ?

Thanks.

My post is inspired by How is running a script like an executable different from running it by a shell explicitly? and Which shell interpreter runs a script with no shebang?

Best Answer

    • Does the quote mean that if the script is executed in bash via command myscript, then

      • bash will first assume it is an ELF and calls execve() on it, and because it is a bash script not ELF, execve() call will fail,

      If Bash finds an executable file, it will first assume that it is in some format the operating system can execute and call execve on it. In the event that that succeeds, this still might not be an ELF or other native executable file. For example, Linux's binfmt_misc feature allows many other executable formats to run. In this particular case, the execve call will most likely fail.

      • bash will next execute bash myscript?

      Bash will use its existing subprocess to execute the script within it, reinitialising the shell environment as necessary. There is not an additional process launched or exec call.

    • Compared to running a bash script via bash myscript in bash, running the script via myscript in bash will additionally have a failure call to execve() on the script directly?

      Yes, I suppose so, if you mean "a failed call".

    • If yes, is myscript slower than bash myscript? Why does "A Practical Guide to Linux Commands, Editors, and Shell Programming By Mark G. Sobell" say the opposite?

      Although you can use bash to execute a shell script, this technique causes the script to run more slowly than giving yourself execute permission and directly invoking the script.

      Mindful of prevailing libel laws, I won't comment on the second part of that question, but even several failed library & system calls are not going to make a measurable difference compared to the launch of an entire bash process and then interpreting a script. I can't access the page in question to find any context you might have missed out. It almost certainly isn't discussing the shebangless case, however.

  1. If a bash script myscript contains a shebang #! /bin/bash, when it is executed in bash via command myscript,

    • is it executed in the same way as it is executed in bash via command bash myscript?

    Yes; in one case, bash myscript is execed directly by the subprocess, and in the other the system execs /bin/bash myscript once it finds the shebang line.

    • is it executed in the same way as the shebang were removed from the script and then the script were executed via command myscript ?

    In so far as you can reasonably detect, yes. None of this matters. Strictly, the main() function of bash doesn't run again in this case, because the subprocess just reinitialises itself internally, and it does run in the other situation. You could construct a scenario where this matters if you were really keen, but it isn't worth the effort.

Note that this is a Bash functionality, and other shells execute shebangless scripts with sh or some other shell, rather than either bash or themselves, as noted in the other question you linked. We're also assuming that your interactive shell is the same bash as the one in your shebang lines.

Related Question