Bash Shebang for dummies?

37

13

I have some bash scripts I have setup that mostly use

#!/bin/bash

but I regularly come across some that look like

#!/bin/bash -e
#!/bin/bash -x
#!/bin/bash -ex

and so on.

Can someone explain the meaning and benefits of these shebang options and whether they apply to other shebangs?

coneybeare

Posted 2010-10-04T21:09:09.907

Reputation: 515

Those options are specific to Bash (or other interpreter). They may be the same for other shells (dash and ksh, for example), but they would be different for other interpreters such as AWK and Python. You can use many of the options that the interpreter accepts. The options are interpreter-specific while the shebang is a kernel feature. – Paused until further notice. – 2010-10-04T21:26:13.000

Answers

42

If a script /path/to/foo begins with #!/bin/bash, then executing /path/to/foo arg1 arg2 is equivalent to executing /bin/bash /path/too/foo arg1 arg2. If the shebang line is #!/bin/bash -ex, it is equivalent to executing /bin/bash -ex /path/too/foo arg1 arg2. This feature is managed by the kernel.

Note that you can portably have only one argument on the shebang line: some unices (such as Linux) only accept one argument, so that #!/bin/bash -e -x would lead to bash receiving the single five-character argument -e -x (a syntax error) rather than two arguments -e and -x.

For the Bourne shell sh and derived shells such as POSIX sh, bash, ksh, and zsh:

  • -e means that if any command fails (which it indicates by returning a nonzero status), the script will terminate immediately.
  • -x causes the shell to print an execution trace.

Other programs may understand these options but with different meanings.

Gilles 'SO- stop being evil'

Posted 2010-10-04T21:09:09.907

Reputation: 58 319

24

They are options passed to bash see help set for more info, in this case:

-x  Print commands and their arguments as they are executed.
-e  Exit immediately if a command exits with a non-zero status.

cYrus

Posted 2010-10-04T21:09:09.907

Reputation: 18 102

3+1 And -ex does both – Nifle – 2010-10-04T21:24:43.897

It's confusing because they look like command-line options passed into Bash. – Caoilte – 2012-09-19T16:39:16.913

2

@Caoilte: And indeed they are (from man bash): In addition to the single-character shell options documented in the description of the set builtin command, bash interprets the following options when it is invoked: [...].

– cYrus – 2012-09-19T17:15:01.830

1arrgh! blink and you miss it! :). – Caoilte – 2012-09-19T18:25:18.807

0

I'd just like to mention an even better – as in more portable – alternative:

#!/usr/bin/env bash

The example above uses env to find the bash executable, which isn't always at /bin/bash. Ye olde #!/bin/bash scripts don't work on NixOS, for example.

If you use env as demonstrated above, you can't supply an argument such as -e to bash (as far as I know). But you can do this instead:

#!/usr/bin/env bash
set -e

Simon Alling

Posted 2010-10-04T21:09:09.907

Reputation: 101

2I do this all the time, but I wouldn't say it's “more portable” — in fact, the risk of having the user run something completely different (from what you can assume a system ships with) is much greater. For example, Ubuntu still ships Bash 4, while a user may choose to run Bash 5. – slhck – 2019-04-02T09:39:18.983

Yea the env usage is not good especially for scripts that run python because you simply do not know if the default python is version 2 or 3 and that makes a world of difference for scripts that need a specific version. Better to be explicit than crafty – smac89 – 2019-07-14T22:26:42.320