The POSIX shell and the three sorts of Unixes

March 2, 2011

Avery Pennarun recently wrote Insufficiently known POSIX shell features, where he talked about a number of nice shell things that are not Bash but are instead POSIX shell features. Although he footnoted this in his entry, I want to draw your attention to how there are three sorts of Unix machines (or, well, Unixes):

  1. machines on which /bin/sh is Bash.
  2. machines on which /bin/sh is POSIX-compatible but is not Bash.
  3. machines which have a POSIX-compatible shell, but it is not /bin/sh.

Every so often some well intentioned person attempts to transition the first sort of Unix into the second sort. Busy sysadmins usually immediately reverse the transition because we have better things to do with our time than debug Bashisms that have crept into administrative scripts or, worse, explain to users why their shell scripts just broke and how no we are not going to do anything about it although we could because it is good for them, honest.

(Rewriting shell scripts to pointlessly avoid Bashisms is the very opposite of productive work. It's even less productive than browsing Slashdot, because there is some vague chance that you could learn something from Slashdot.)

The third sort of Unix is a pain in the rear for everyone. In many respects it might as well not have a POSIX shell, because you can't easily use it in portable scripts. If you are a big project like redo you can work around the difference and find yourself the right shell, but if you are an ordinary person writing cross-machine shell scripts, ones that you want to run without an installer step, well, you lose. Your scripts all start with '#!/bin/sh' because that's the only reliable cross-Unix name for a Bourne shell, so you can't count on POSIX features.

Fortunately the third sort of Unix is mostly dying out. The largest holdout in our environment is Solaris, which we don't let users log on to and barely run anything on. Even then, the differences sometimes get to us.

Honestly, I suggest that you ignore the third sort of Unix unless you can't because you have one. And if you want to write portable POSIX shell scripts, make sure that you use the second sort of Unix right from the start. (Or that someone involved in the project does.)

Comments on this page:

From at 2011-03-03 02:39:24:

The GNU solution to this is what one can expect... They have a ridiculously tricky script in gnulib, called, which "portable" scripts are supposed to source. Then, searches for a POSIX shell, and if it finds one, re-executes the sourcing script. They claim to find a way to portably determine the path to the sourcing script so that it can be executed etc. The tradeoff is that is incomprehensive to anyone except possibly Jim M., but the portable caller only needs to use !#/bin/sh, then add one line of " ." and proceed full POSIX from that line down with all the crazy encapsulated away.

From at 2011-03-03 17:28:46:

If you have bash-isms, and don't want/have time to fix the script, then changing the shebang to "/usr/bin/env bash" is a quick win.

The following utility may also be of some use of you want to do a large-scale migration:

Debian (and Ubuntu) have started use dash as /bin/sh I believe, and that caused a bit of breakage. Hopefully more Linux distros will do this--each one ideally using a different sh-equivlant--so that it keeps everyone honest in their coding practices.

Written on 02 March 2011.
« Filtering, email, and differences from Usenet
Why I call FastCGI complex and SCGI much simpler »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Mar 2 23:10:20 2011
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.