How can I test for POSIX compliance of shell scripts?
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!
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.
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.