111

Considering that POSIX is the closest thing to a common standard among all unices, I'm interested in knowing if there's a shell that supports it exclusively. While most modern shells provide support for POSIX (and will run POSIX compliant scripts without any problem), they don't do a good job at pointing out non-compliant features.

Is there any shell that implements POSIX and POSIX only, in such a way that it'd throw an error for any non compliant feature?

EDIT I want to clarify that I'm not asking for general tips for writing portable shell scripts. The related question mentioned in the comments already covered this. I thought of this question when I found out that bash has a --posix option but only to discover that it only affects some intialization behaviors which is not exactly what I'm looking for.

4
  • 6
  • @Gilles: Maybe I should mention that I did come across this question but only one answer suggested testing with dash. I mentionned portability as a general context for my question but that was not its true intent.
    – rahmu
    Sep 21, 2012 at 13:22
  • Sure, I wanted the two questions to be linked because they are likely to be of interest to the same people. They aren't duplicates by any means. By the way, posh is a better test for POSIX compliance than dash. Sep 21, 2012 at 14:05
  • 3
    busybox is pretty close to POSIX and POSIX only. One thing that can trip you up is if you also install other packages (like diffutils) then it might add features. Checkout alpine linux's livecd which starts you out with a pure busybox environment. Alpine uses the musl C library so you don't get GNU extensions that can add features like extended regular expressions. Jul 4, 2015 at 15:41

4 Answers 4

68

You can use ShellCheck (GitHub) as a linter for your shell scripts. There is also an online version.

To detect POSIX compatibility issues (e.g. SC2039), the shebang line of your shell script should be #!/bin/sh. You can also pass --shell=sh to shellcheck.

Example (test.sh):

#!/bin/sh
if [[ $HOSTNAME == test ]]; then
    echo fail &> foo
fi

Result (shellcheck test.sh):

In test.sh line 2:
if [[ $HOSTNAME == test ]]; then
   ^-- SC2039: In POSIX sh, [[ ]] is undefined.
      ^-- SC2039: In POSIX sh, HOSTNAME is undefined.    

In test.sh line 3:
    echo fail &> foo
              ^-- SC2039: In POSIX sh, &> is undefined.
2
  • 8
    All these years and I never heard of ShellCheck...thanks for the link! Oct 3, 2018 at 16:50
  • 2
    Best tool ever! Especially having an online version of it is awesome to quickly check a piece of code!
    – Mecki
    Apr 30, 2019 at 13:48
55

Unfortunately, 'portable' is usually a stronger requirement than 'POSIX-compliant' for shell scripts. That is, writing something that runs on any POSIX shell isn't too hard, but getting it to run on any real-world shell is harder.

You can start by installing every shell in your package manager, in particular debian's posh sounds like what you want (Policy-compliant Ordinary SHell). Debian's policy is POSIX with a few exceptions (echo -n specified, local...).

Beyond that though, testing has to cover a few shells (/bin/sh especially) on a range of platforms. I test on Solaris (/bin/sh and xpg4/sh), and BSD. AIX and HP-UX are very compliant and don't cause problems. bash is a little world of its own.

I'd recommend the Autoconf guide to portable shell, which is absolutely brilliant and saves a lot of time. Large chunks of it are obsolete, but that's OK; just skip TruUnix and Ultrix and so on if you don't care!

9
  • posh does indeed sound like what I'm asking for. I'll do some tests as soon as I can.
    – rahmu
    Sep 21, 2012 at 13:29
  • 1
    I answered before spotting the related question! posh is a debian thing, so won't be packaged on every system. Also, the shell isn't necessarily the thing to be most worried about; sed incompatibilities are a big problem, for example. Sep 21, 2012 at 13:47
  • 1
    I wouldn't bother porting to Solaris /bin/sh aka Bourne shell (which is not POSIX). Solaris like all modern unices has a POSIX shell, it just happens not to be in the usual location (/usr/xpg4/bin/sh) Sep 21, 2012 at 14:31
  • 1
    The Bourne shell is not a POSIX conformant shell, ksh88 is. The Bourne shell used to be Unix's sh in the pre-POSIX days, but it's a museum piece now, just like the Thomson shell was before it. Sep 21, 2012 at 16:38
  • 2
    The reason I treat /bin/sh as important is because it's invoked from the shebang in so many scripts. "/usr/bin/env sh" is hardly an improvement. If you're going to put any effort into making something work on non-POSIX shells, I feel I may as well prioritise each system's /bin/sh. It won't be long before some customer runs your script with the default shell, which is not all that unreasonable. Sep 21, 2012 at 17:07
15

Bash will run in POSIX-compliant mode if the POSIXLY_CORRECT environment variable is set. From the manpage:

   POSIXLY_CORRECT
          If  this  variable  is  in the environment when bash starts, the
          shell enters posix mode before reading the startup files, as  if
          the  --posix  invocation option had been supplied.  If it is set
          while the shell is running, bash enables posix mode, as  if  the
          command set -o posix had been executed.

Many other GNU utilities will also honor POSIXLY_CORRECT, so if you're on a system with predominantly GNU tools (e.g. most Linux systems), this is a good start if your goal is POSIX conformance.

3
  • 37
    Even in POSIX mode, bash will still allow some non-POSIX features such as [[.
    – jordanm
    Sep 21, 2012 at 23:59
  • 16
    Fun fact: This variable was originally called POSIX_ME_HARDER Apr 1, 2020 at 21:34
  • This does nothing to test for POSIX compliance Sep 7, 2023 at 4:03
2

Is there any shell that implements POSIX and POSIX only, in such a way that it'd throw an error for any non compliant feature?

Dash fits the bill here.

DASH is a POSIX-compliant implementation of /bin/sh that aims to be as small as possible. It does this without sacrificing speed where possible. In fact, it is significantly faster than bash (the GNU Bourne-Again SHell) for most tasks.

When writing shell scripts that should conform to the POSIX Shell Command Language, I use Dash as the interpreter when testing my scripts as it implements only POSIX shell features and throws an error if it encounters any Bashisms such as array variables or process substitution.

Dash is a port of the Almquist shell (hence its name, Debian Almquist shell) and on Debian-based systems, /bin/sh is a symbolic link to /bin/dash. For more information, see Almquist shell - Wikipedia.

2
  • 1
    I added this answer because none of the other (excellent) answers mention Dash. It's only mentioned in the question comments but users (including those who find this question via a search engine) shouldn't have to check through comments to see all the valid answers. Jul 19, 2021 at 17:10
  • 7
    The design of dash priortizes practicality over strict conformance. I would not trust it to identify all deviations from POSIX the way posh specifically does.
    – tripleee
    Apr 15, 2022 at 8:34

You must log in to answer this question.

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