Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use a Shebang with Bash scripts?

I am using Bash

$ echo $SHELL /bin/bash 

and starting about a year ago I stopped using Shebangs with my Bash scripts. Can I benefit from using #!/bin/sh or #!/bin/bash?

Update: In certain situations a file is only treated as a script with the Shebang, example

$ cat foo.sh ls  $ cat bar.sh #!/bin/sh ls  $ file foo.sh bar.sh foo.sh: ASCII text bar.sh: POSIX shell script, ASCII text executable 
like image 501
Zombo Avatar asked Aug 06 '14 16:08

Zombo


People also ask

Do bash scripts need shebang?

It's not required and has no effect if you for example write bash ./script.sh or source the script. Shebang is only for executables, not sourced scripts.

Is #!/ Bin bash necessary?

An executable can be a binary program, any one of a million script types and other things as well. Hence the need for #!/bin/bash .

Which is the correct shebang line for a bash script?

What is bash shebang? The #! syntax is used in scripts to indicate an interpreter for execution under UNIX / Linux operating systems. The directive must be the first line in the Linux shell script and must start with shebang #! .

What is the purpose of a shebang in a script file?

What is the shebang? The shebang is a special character sequence in a script file that specifies which program should be called to run the script. The shebang is always on the first line of the file, and is composed of the characters #! followed by the path to the interpreter program.


2 Answers

On UNIX-like systems, you should always start scripts with a shebang line. The system call execve (which is responsible for starting programs) relies on an executable having either an executable header or a shebang line.

From FreeBSD's execve manual page:

 The execve() system call transforms the calling process into a new  process.  The new process is constructed from an ordinary file, whose  name is pointed to by path, called the new process file.  [...]   This file is  either an executable object file, or a file of data for an interpreter.   [...]   An interpreter file begins with a line of the form:         #! interpreter [arg]   When an interpreter file is execve'd, the system actually execve's the  specified interpreter.  If the optional arg is specified, it becomes the  first argument to the interpreter, and the name of the originally  execve'd file becomes the second argument 

Similarly from the Linux manual page:

execve() executes the program pointed to by filename. filename must be either a binary executable, or a script starting with a line of the form:

#! interpreter [optional-arg] 

In fact, if a file doesn't have the right "magic number" in it's header, (like an ELF header or #!), execve will fail with the ENOEXEC error (again from FreeBSD's execve manpage):

[ENOEXEC] The new process file has the appropriate access permission, but has an invalid magic number in its header.


If the file has executable permissions, but no shebang line but does seem to be a text file, the behaviour depends on the shell that you're running in.

Most shells seem to start a new instance of themselves and feed it the file, see below.

Since there is no guarantee that the script was actually written for that shell, this can work or fail spectacularly.

From tcsh(1):

   On  systems which do not understand the `#!' script interpreter conven‐    tion the shell may be compiled to emulate it;  see  the  version  shell    variable.  If so, the shell checks the first line of the file to see if    it is of the form `#!interpreter arg ...'.  If it is, the shell  starts    interpreter  with  the  given args and feeds the file to it on standard    input. 

From FreeBSD's sh(1):

If the program is not a normal executable file (i.e., if it      does not begin with the “magic number” whose ASCII representation is      “#!”, resulting in an ENOEXEC return value from execve(2)) but appears to      be a text file, the shell will run a new instance of sh to interpret it. 

From bash(1):

   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, a    file containing shell commands.  A subshell is spawned to  execute  it. 

You cannot always depend on the location of a non-standard program like bash. I've seen bash in /usr/bin, /usr/local/bin, /opt/fsf/bin and /opt/gnu/bin to name a few.

So it is generally a good idea to use env;

#!/usr/bin/env bash 

If you want your script to be portable, use sh instead of bash.

#!/bin/sh 

While standards like POSIX do not guarantee the absolute paths of standard utilities, most UNIX-like systems seem to have sh in /bin and env in /usr/bin.

like image 176
Roland Smith Avatar answered Oct 05 '22 07:10

Roland Smith


Scripts should always begin with a shebang line. If a script doesn't start with this, then it may be executed by the current shell. But that means that if someone who uses your script is running a different shell than you do, the script may behave differently. Also, it means the script can't be run directly from a program (e.g. the C exec() system call, or find -exec), it has to be run from a shell.

like image 40
Barmar Avatar answered Oct 05 '22 06:10

Barmar