I'm working on a Bash library and want to ensure I'm supporting as many environments as possible - including old installations of Bash. My development environment is Bash 4.3, but some of my users may well be running much older versions and presently I have no way to confirm or deny that my library will work for them. In particular I'd like to be compatible with OSX (which still ships with Bash 3.2, AFAIK).
I know Bash can run in POSIX-compliant mode; is there a similar setting to disable modern functionality? Or a way to run Bash in some sort of compatibility mode? I'm looking for any technique short of actually finding and booting up old operating systems and testing my library there.
Update
For example, I've avoided using associative arrays since they were introduced in Bash 4, but it's hard to be sure without testing that I'm not accidentally using some other Bash 4+ feature.
You can use Bash own facilities to emulate older version of Bash. Look up "compat" options on
shopt
.Mind you, while it does change behavior as described under each
compatNN
entry in the man page, it does not remove features that are otherwise present on the current version. For example, this doesn't cause any errors:Even though
globstar
was only introduced on Bash 4.0.Have a look at shenv: https://github.com/shenv/shenv. Just like rbenv, pyenv, goenv and others, but for shells, it lets you install different versions of Bash among others (zsh, fish, yash, etc.).
(Disclaimer: I'm the one who forked pyenv into shenv!)
Finally coming back to this question, it's pretty easy to just compile (without installing) the bash version(s) you're interested in. Here's how I'm testing Bash 3.2.57:
Now you have a bash 3.2.57 binary you can run, without actually "installing" it or modifying your normal environment.
To run a shell script against this version:
To enter a clean interactive prompt:
Using
env -i
rather than just calling./bash
directly leaves you with a mostly-empty environment (runenv
from inside the shell to see what's still set). Updating thePATH
allows calls tobash
(e.g.bash -version
) to invoke the local bash shell, not the system-wide installation (but note this pulls in your whole PATH). Adding--noprofile --norc
avoids loading your.bashrc
and associated scripts.If you don't want to pick up any
PATH
modifications, just executeexport PATH="$PWD:$PATH"
once inside the subshell instead of as part of theenv
command.These installation steps are now part of a Docker image, if that's helpful for folks to reference. I wouldn't necessarily suggest using this image directly, but you're welcome to copy from the Dockerfile. MIT licensed.