如何在旧版本的 Bash 上测试我的 Bash 脚本?

How can I test my Bash script on older versions of Bash?

我正在开发一个 Bash 库,并希望确保我支持尽可能多的环境——包括 Bash 的旧安装。我的开发环境是 Bash 4.3,但我的一些用户很可能使用 运行 更旧的版本,目前我无法确认或否认我的库是否适用于他们。特别是我想与 OSX 兼容(它仍然与 Bash 3.2,AFAIK 一起提供)。

我知道 Bash 可以 运行 在 POSIX 兼容模式下;是否有类似的设置来禁用现代功能?或者在某种兼容模式下 运行 Bash 的方法?除了实际查找和启动旧操作系统并在那里测试我的库之外,我正在寻找任何技术。

更新

例如,我避免使用 associative arrays,因为它们是在 Bash 4 中引入的,但如果不进行测试,很难确定我没有不小心使用其他 [=23] =] 4+ 功能。

终于回到这个问题,编译(无需安装)您感兴趣的 bash version(s) 非常容易。这是我测试 Bash 3.2.57 的方式:

$ mkdir ~/bash
$ cd ~/bash
$ wget http://ftp.gnu.org/gnu/bash/bash-3.2.57.tar.gz
$ tar xvzf bash-3.2.57.tar.gz
$ cd bash-3.2.57
$ ./configure
$ make
# if `make` fails due to yacc, run `sudo apt-get install byacc`
# No need to run `make install`
$ ./bash -version
GNU bash, version 3.2.57(1)-release (armv7l-unknown-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.

现在您有一个 bash 3.2.57 二进制文件,您可以 运行,而无需实际“安装”它或修改您的正常环境。

给运行一个针对这个版本的shell脚本:

$ ./bash your_script.sh

输入clean interactive prompt:

$ env -i PATH="$PWD:$PATH" ./bash --noprofile --norc
bash-3.2$ bash -version
GNU bash, version 3.2.57(1)-release (armv7l-unknown-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
bash-3.2$ 

使用 env -i 而不是直接调用 ./bash 会给您留下一个几乎是空的环境(运行 env 从 shell 内部查看什么仍然设置)。更新 PATH 允许调用 bash(例如 bash -version)来调用本地 bash shell,而不是系统范围的安装(但请注意,这会引入你的整个路径)。添加 --noprofile --norc 可避免加载您的 .bashrc 和相关脚本。

如果您不想获取任何 PATH 修改,只需在 subshell 中执行一次 export PATH="$PWD:$PATH" 而不是作为 env 命令的一部分.


我有一个 Docker image (repo) 使用这些安装步骤,如果这对人们参考有帮助的话。我不一定建议直接使用此图像,但欢迎您从 Dockerfile/install 脚本中复制。 MIT 许可。

看看shenv:https://github.com/shenv/shenv。就像 rbenv、pyenv、goenv 等,但对于 shell,它允许您安装不同版本的 Bash 等(zsh、fish、yash 等)。

(免责声明:我是将 pyenv 分叉到 shenv 的人!)

您可以使用 Bash 自己的工具来模拟旧版本的 Bash。在 shopt.

上查找 "compat" 选项

请注意,虽然它确实改变了手册页中每个 compatNN 条目下描述的行为,但它不会删除当前版本中存在的其他功能。例如,这不会导致任何错误:

shopt -s compat31
shopt -s globstar

尽管 globstar 仅在 Bash 4.0 上引入。

尽管很高兴知道可以在本地编译 bash 的任意版本(如我在 ), these days there's a much simpler option - the official Docker bash images.

中所讨论的)

针对多个 bash 版本测试脚本通常很简单:

for v in 3 4 5; do # or whatever versions you're interested in
  docker run -v "$PWD:/mnt" "bash:$v" \
    bash /mnt/your_script.sh
done