What is the function of bash shebang?

  • The function of shebang is:

Interpreter directives allow scripts and data files to be used as commands, hiding the details of their implementation from users and other programs, by removing the need to prefix scripts with their interpreter on the command line.

  • What is the different between executing a file using ./file or sh file?

A Bourne shell script that is identified by the path some/path/to/foo, has the initial line,

    #!/bin/sh -x

and is executed with parameters bar and baz as

    some/path/to/foo bar baz

provides a similar result as having actually executed the following command line instead:

    /bin/sh -x some/path/to/foo bar baz

Note: On 1980 Dennis Ritchie introduced kernel support for interpreter directives:

The system has been changed so that if a file being executed
begins with the magic characters #! , the rest of the line is understood
to be the name of an interpreter for the executed file.
Previously (and in fact still) the shell did much of this job;
it automatically executed itself on a text file with executable mode
when the text file's name was typed as a command.
Putting the facility into the system gives the following
benefits.

1) It makes shell scripts more like real executable files,
because they can be the subject of 'exec.'

2) If you do a 'ps' while such a command is running, its real
name appears instead of 'sh'.
Likewise, accounting is done on the basis of the real name.

3) Shell scripts can be set-user-ID.

Note: Linux ignores the setuid bit on all interpreted executables (i.e. executables starting with a #! line).

4) It is simpler to have alternate shells available;
e.g. if you like the Berkeley csh there is no question about
which shell is to interpret a file.

5) It will allow other interpreters to fit in more smoothly.

More info :

  • Wikipedia Shebang
  • The #! magic, details about the shebang/hash-bang

The function of the hashbang is to tell the kernel what program to run as the script interpreter when the file is executed.

Running ./program does exactly that, and requires execute permission on the file, but is agnostic to what type of a program it is. It might be a bash script, an sh script, or a Perl, Python, awk, or expect script, or an actual binary executable. Running sh program would force it to be run under sh, instead of anything else.

Note that sh is different from bash! The latter has a number of advanced features not known by the standard shell. Depending on the system, sh might be another program, or Bash in compatibility mode, but the result is usually the same: any advanced features are inaccessible.

Bash in itself doesn't understand the hashbang line, but relies on the kernel to read it. On the other hand, the Perl interpreter does also read the hashbang line by itself regardless of how it was started: it does this to pick any command line options set on the hashbang line. Bash doesn't do this.

For example, the following script has different behaviour depending on if it is started as ./script (through exec and the hashbang line), or with bash script (running the bash interpreter manually):

#!/bin/bash -u
echo $1

bash itself does not attach any meaning to the shebang line, it only sees it as a comment. When the shell reads a command line, and the command is an external program (not an internal command like cd), it executes the command using the execve system call. The kernel then examines what kind of executable the file passed to execve is by checking the magic number at the start of the file. If the magic number consists of the two bytes 0x23 0x21 (ASCII characters #!), the kernel assumes they are followed by the absolute path the the interpreter of the script. The kernel then starts the interpreter, passing the script to it.