Is there any reason to have a shebang pointing at /bin/sh rather than /bin/bash?

In most shell scripts I’ve seen (besides ones I haven’t written myself), I noticed that the shebang is set to #!/bin/sh. This doesn’t really surprise me on older scripts, but it’s there on fairly new scripts, too.

Is there any reason for preferring /bin/sh over /bin/bash, since bash is pretty much ubiquitous, and often default, on many Linux and BSD machines going back well over a decade?

Asked By: Jules

||
  1. There are systems not shipping bash by default (e.g. FreeBSD).
  2. Even if bash is installed, it might not be located in /bin.
  3. Most simple scripts don’t require bash.
  4. Using the POSIX shell is more portable and the scripts will run on a greater variety of systems.
Answered By: Marco

Most system scripts in (Debian related: Ubuntu, Mint, etc.) Linux are written to run in the faster dash, which is the default /bin/sh in those systems. The reason is twofold:

  • Speed of the system. A smaller code of dash loads faster and also run faster. With some (small?) additional effort (cost) to programmers of shell scripts.

  • Security. Having diversity of shells helps resilience to bugs. Debian systems were mostly not vulnerable to shellshock because the default shell did not have such vulnerability.

Bash is indeed the default shell for users, as is more powerful and has much more elements to make coding easier. It is also the default sh in Mac OS (the one linked from /bin/sh). However, calling bash with the link name of sh makes it start as a posix compliant shell.

Answered By: user79743

The only remaining reason to write a shell script, instead of a script in a more powerful and ergonomic language, is if portability to legacy systems with an unknown set of installed software is more important than any other factor.

/bin/sh is the one and only script interpreter that’s available on everything that calls itself Unix. But on an awful lot of legacy systems, /bin/sh and the associated utilities are not even compliant with the POSIX.1-1996 “shell and utilities” spec, let alone anything more modern. Standard-compliant tools are an optional add-on, installed in /usr/xpg4 or some such non-obvious location.1 Scripting to the portable-subset shell language is even more tedious and error-prone than scripting to the POSIX shell language. (Read through an Autoconf-generated configure script sometime if you don’t believe me. Just the setup should be enough to convince you.)

But if you can assume any other script interpreter is installed (e.g. Bash) then you can assume an interpreter for a better scripting language is installed. Perl, for instance, is more likely to be available than Bash is.

Therefore, you should never write a #! /bin/bash script, because if that’s an option, a better language is also an option.

1 For instance, Solaris 10 and older shipped the original Bourne shell as /bin/sh. I am informed that Solaris 11 updated it to ksh93.

Answered By: zwol

Others have pointed out that the premises of the question, that the Bourne Again shell is default and ubiquitous, are downright wrong.

In addition to that, there are indeed good reasons for using something other than the Bourne Again shell for interpreting shell scripts. These reasons motivated Ubuntu’s and Debian’s big project, over a number of years, to remove bashisms and to make as many of the shell scripts run by system initialization (which was a lot of shell scripts with System 5 rc) and package installation/removal use the Debian Almquist shell instead of the Bourne Again shell.

Simply put: The Bourne Again shell, chock full of interactive features as it is, is not the fastest shell interpreter for a POSIX-conformant shell script. So if one can make one’s shell scripts POSIX-conformant, interpreting them with a more lightweight program, like the Debian Almquist shell, one’s system will perform better. (In the end, Debian had to make slight adjustments to the Almquist shell, to add support for a couple of non-POSIX shell constructs that were simply too deeply and widely embedded and too useful to get rid of.)

The result of it all was a major gain in bootstrap performance.

So there are two distinct classes of shell to consider, here:

  • The shells with all of the flashy interactive features, which are configured as the interactive login shells for users in the accounts database.
  • The shells that interpret lots of scripts quickly, which are used as the script interpreters by shell script programs.

Note that talking about this as “preferring /bin/sh” is oversimplifying. Debian actually had at least two goals:

  1. In the face of administrators using the Debian Almquist shell, the Z Shell (in POSIX mode), the Bourne Again shell (in POSIX mode), the MirBSD Korn shell, and others as /bin/sh, there was either …

    1. … making the scripts as portable as possible, so that switching what /bin/sh mapped to didn’t break things; or

    2. … making non-portable scripts explicitly target the correct interpreter program, instead of simply expecting that /bin/sh map to it.

  2. There was making the Debian Almquist shell the default mapping for /bin/sh instead of the Bourne Shell, so that those scripts that were POSIX-conformant (or, more properly, Debian Policy Manual conformant) ran more quickly.

And of course once one gets into this, one can take it a lot further; such as considering the efficiency tradeoffs of the likes of /bin/true and /usr/bin/clear being shell scripts or compiled programs. But that’s beyond the scope of this answer, fortunately. ☺

None of this is very new, nor even Unix-specific, of course. Back before the turn of the century, I wrote and published a command-line interpreter that came in both “interactive” and “non-interactive” flavours, explaining this very division in its doco and noting the difference between the COMSPEC and OS2_SHELL environment variables. Similarly, discussion of removing bashisms in Debian’s System V rc and package installation/removal scripts dates back to the 1990s.

Further reading

Answered By: JdeBP

Is there any reason to have a shebang pointing at /bin/sh rather than /bin/bash?

Yes. @Marco’s excellent answer outlines this well.

What should I use in my shebang?

When writing your own scripts, you should point the shebang to the most general thing that you have tested against.

On my system (Centos 6.6), sh is symlinked to bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

This means that I always use #!/bin/bash in my shebang unless I have verified that I don’t have bashims in my script.

By setting the shebang to #!/bin/sh you are promising that the script will work with all implementations of sh.

This is a much bigger promise than saying the script will work with bash.

Here is an example of a script that will behave incorrectly depending on what sh implementation the system is using:

#!/bin/sh
n=1
a=$((++n))
echo $n

When using bash the script will print:

2

When using dash the script will print:

1

If I want to use #!/bin/sh what do I need to do?

  • Check the script with checkbashisms – Note that this will not find all bashims. It didn’t find the bashism in my script above
  • Test the script using another sh implementation. I typically test with dash, however I expect that some bashisms or dashims can still slip through.

The DashAsBinSh page on the Ubuntu wiki has lots of interesting info.

Answered By: sixtyfootersdude

You should actually be using either

#! /bin/env sh

or

#! /bin/env bash

that way you invoke either shell by the way they’re install on that system.

To be super safe (eg in cases of single-user reboots) use sh otherwise use bash.

Answered By: Paul Evans
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.