80

I am wondering what the point of sh being symbolic linked to dash is? I understand that dash is supposed to be faster than bash, but I am uncertain why the original sh shell isn't present in sh.

Or if anything why isn't sh linked to bash?

4 Answers 4

132

The short answer to “why the original sh shell isn't present in sh” is that there's no original sh.

Well, ok, there is: it's the Thompson shell. Version 1 had some of the features we know today, in particular redirection and pipes (read Dennis Ritchie's paper on early Unix history). Later versions added features such as background execution with &, globbing (implemented with an external program), and some forms of quoting, but it didn't have variables or nested control structures. Conditionals and loops were provided via external programs if (which took one condition and one command as arguments) and goto (which worked by changing the file position of its parent in the script file).

In 1979, in Unix V7, the Thompson shell was replaced as /bin/sh by the Bourne shell. The first release already had many of the features that are present in dash today, and subsequent versions introduced many more. A few years later, the Korn shell came onto the scene, with a growing feature set; many Unix variants installed it under the name ksh.

In 1992, POSIX codified a minimum set of sh features that was basically Bourne plus a few things. Any system that called itself “Unix” had to implement at least these features. Commercial Unix systems usually used ksh as the POSIX sh, but a few (e.g. OSF/1) had their own.

Neither the Bourne shell nor the Korn shell were open source until fairly recently, so when the Linux world started to form in the mid-1990s, they weren't available. /bin/sh had to be something else. Most Linux distributions went for bash, a shell from the GNU project that tended to be between Bourne and Korn in terms of scripting features, and much better than either for interactive use). The only viable alternative was pdksh (“public domain Korn shell”), a free (now discontinued, but living on as mksh, which is actively developed), but I don't remember a Linux distribution using pdksh as /bin/sh, I don't know why, I guess because Linux distributions were always GNU/Linux distributions, basically shipping GNU versions of any tool for which a GNU version did exist.

There were also several open source implementations of sh called “ash”, most notably the Almquist shell, but they were very incomplete, lacking some POSIX features that people wanted to use. A programmer who was a Debian maintainer, Herbert Xu, extended ash to make it POSIX compliant. Eventually his version was renamed to dash, and there was some push to make it /bin/sh in Debian instead of bash. Ubuntu started out before Debian started to systematically treat bashisms (the use of bash-specific functionality in #!/bin/sh scripts) as bugs. Both switched a later (Ubuntu 6.10, Debian only in 2009 (it was a goal for lenny but the switch was only made after the lenny release, i.e. in squeeze)).

A major reason for using dash as rather than bash as /bin/sh is that it's significantly faster. This was especially important for Ubuntu, which has striven to keep boot times short since the beginning. Dash also tends to use less memory than bash, which is somewhat important for wrapper scripts that stay around just to do a bit of cleanup when the underlying program exits. Another benefit of dash is that it only relies on libc (the core system library) whereas bash also relies on terminal support libraries (it can't start without them, even to run a script); this means that dash has a better chance to keep working on a broken system.

At some point during the 21st century, the Korn shell went open source, and open source versions of the Bourne shell appeared (old versions, because development had ceased years before). But dash and bash were too firmly entrenched in the Linux world for them to gain any acceptance, especially the Bourne shell since its value today is only historical. Dash displaced bash because it had clear benefits, but none of the other contenders have any decisive advantage as /bin/sh.

2
  • 1
    I'd argue that there are good reasons to use ksh93 as /bin/sh -- it's one of the highest-performance POSIX shells available. Agreed that dash's ubiquity is a matter of timing. Nov 16, 2017 at 16:08
  • 3
    @CharlesDuffy Ksh93 is faster at doing complex stuff, but dash beats it for startup time, and for simple scripts (such as all the calls to system(3) that applications make) that's the dominant factor. Nov 16, 2017 at 16:38
30

Speed and POSIX compliance ( in other words, portability) are the main factors. Remember that /bin/sh is meant for system scripts, which may or may not have come from older versions of Ubuntu and/or other systems.

Sure, shiny features of bash are cool to use for us users, but when it comes to running thing in environment where you have to manage several different servers/systems - having POSIX compliant shell makes whole lot of difference. Especially, if you're a new sysadmin and inherited environment with many scripts.

As for why original Bourne shell isn't present, it is simple - it is a proprietary product originally owned by AT&T Bell Labs.

Also, there's actually an explicit explanation on Ubuntu wiki about that:

Why was this change made? The major reason to switch the default shell was efficiency. bash is an excellent full-featured shell appropriate for interactive use; indeed, it is still the default login shell. However, it is rather large and slow to start up and operate by comparison with dash. A large number of shell instances are started as part of the Ubuntu boot process. Rather than change each of them individually to run explicitly under /bin/dash, a change which would require significant ongoing maintenance and which would be liable to regress if not paid close attention, the Ubuntu core development team felt that it was best simply to change the default shell. The boot speed improvements in Ubuntu 6.10 were often incorrectly attributed to Upstart, which is a fine platform for future development of the init system but in Ubuntu 6.10 was primarily running in System V compatibility mode with only small behavioural changes. These improvements were in fact largely due to the changed /bin/sh.

And here's a note about portability:

The Debian policy manual has long mandated that "shell scripts specifying '/bin/sh' as interpreter must only use POSIX features"; in fact, this requirement has been in place since well before the inception of the Ubuntu project. Furthermore, any shell scripts that expected to be portable to other Unix systems, such as the BSDs or Solaris, already honoured this requirement. Thus, we felt that the compatibility impact of this change would be minimal.

See https://wiki.ubuntu.com/DashAsBinSh

2
  • Doesn't dash support features that aren't required by POSIX? Nov 15, 2017 at 14:10
  • @NerdOfLinux It doesn't really matter what /bin/sh supports in addition to POSIX (as long as those additions don't break POSIX scripts); the important thing is it supports everything POSIX (and is as fast as possible). As long as dash fulfills these requirements, /bin/sh can link to it. Nov 15, 2017 at 18:47
14

In GNU/Linux distributions, the "original /bin/sh" is actually Bash.

GNU wanted a Bourne-like shell that was under the GPL, so that's why they chose Bash for their /bin/sh, instead of Bourne, which was not GPL-licensed. Modern Linux distros inherited this decision to the point that it became a defacto standard for /bin/sh to be Bash. The original Bourne shell ("sh") has been used in other non-Linux Unixes, even as recently as Solaris 10, but it's never been a mainstay in Linux distributions.

Switching /bin/sh from bash to dash was a Debian decision (inherited by Ubuntu) motivated largely by speed - it came at a time when they put a huge effort into improving boot speed, and a large part of the boot CPU time at the time consistent of running init scripts.

Bash continues to be used as the default interactive/login shell for users, but Dash is the one at /bin/sh and the one which is executed for system scripts such as init scripts.

Dash is very fast, but also is very closely POSIX-compatible - a standard that is aligned closely with the Bourne shell. So in a way, by switching from Bash to Dash we are moving back to a shell more closely aligned with Bourne.

2
  • "Dash is very fast, but also is very closely POSIX-compatible - a standard that is aligned closely with the Bourne shell. " Yes, although POSIX is more closely related to ksh, I'd say. I don't recall Bourne shell having arithmetic expansion ` $(())`, which is POSIX. Nov 14, 2017 at 23:48
  • 1
    Also, in Bourne, ^ is a pipe character -- so echo foo ^ cat will emit foo ^ cat in POSIX sh, but foo in Bourne; this specific test is how Autoconf tells the two apart. Nov 16, 2017 at 16:10
4

/bin/sh is linked to /bin/dash for what I believe is compatibility reasons. Many scripts simply start with

#!/bin/sh

so by moving to dash and not making a symbolic link, a lot of scripts would fail to run properly(or at all) if /bin/sh didn't exist at all.

The change was made from bash to dash because according to https://wiki.ubuntu.com/DashAsBinSh:

The major reason to switch the default shell was efficiency. bash is an excellent full-featured shell appropriate for interactive use; indeed, it is still the default login shell. However, it is rather large and slow to start up and operate by comparison with dash. A large number of shell instances are started as part of the Ubuntu boot process. Rather than change each of them individually to run explicitly under /bin/dash, a change which would require significant ongoing maintenance and which would be liable to regress if not paid close attention, the Ubuntu core development team felt that it was best simply to change the default shell.

sh is not linked to bash, because

The Debian policy manual has long mandated that "shell scripts specifying '/bin/sh' as interpreter must only use POSIX features"

If you want to use bash as /bin/sh:

If the problems are more widespread and you want to change the default system shell back, then you can instruct the package management system to stop installing dash as /bin/sh:

sudo dpkg-reconfigure dash

There are some features that dash provides that bash does not, as:

there is even an outside chance that there are a few scripts that now depend on some feature of dash that bash does not provide!

8
  • I already understood compatibility may be a a factor but I was looking for a not so obvious and more in depth answer...
    – NerdOfCode
    Nov 14, 2017 at 22:26
  • 2
    So if I were to install the original bourne shell sh to /bin/sh, would this screw up those boot scripts?
    – dessert
    Nov 14, 2017 at 22:30
  • 2
    You should leave /bin/sh as the shell provided by the distribution as that's what they've targeted with their boot scripts and the like. But if you did replace it with Bourne, it would be mostly compatible. I would imagine there would be breakages though, only due to minute differences vs the sheer amount of code. Of course you're free to use whichever shell in your own scripts with a custom hashbang. Nov 14, 2017 at 23:36
  • 1
    @mckenzm Which shell /bin/sh links to is separate from which one any particular user has set as their initial login shell. The target of /bin/sh does not depend on which user is looking, and you do need to use sudo--or some other means of acting as the root user--to change it. Also, in general and for any package, dpkg-reconfigure must be run as root. In contrast, users are usually permitted to change their own initial login shell and can do so with the chsh command. The name of one's initial login shell also goes in $SHELL and is used for some interactive non-login shells too. Nov 15, 2017 at 14:51
  • 1
    @Eliah Kagan Apologies, I did indeed confuse the logon default shell with the sh alias.
    – mckenzm
    Nov 15, 2017 at 21:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .