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
#!/bin/sh if [[ $HOSTNAME == test ]]; then echo fail &> foo fi
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.
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,
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!
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.