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

时间:2016-01-15 06:19:38

标签: linux bash integration-testing versioning

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

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

更新

例如,我已经避免使用associative arrays,因为它们是在Bash 4中引入的,但如果不进行测试我很难确定我不会意外地使用其他一些Bash 4+功能。

4 个答案:

答案 0 :(得分:5)

最后回到这个问题,编译(不安装)您感兴趣的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二进制文件,你可以运行,而不是实际上#34;安装"它或修改你的正常环境。

针对此版本运行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会让您处于一个大部分空白的环境中(从shell内部运行env以查看仍然设置的内容)。更新PATH允许调用bash(例如bash -version)来调用本地bash shell,而不是系统范围的安装(但请注意这会引入整个PATH)。添加--noprofile --norc可以避免加载.bashrc及相关脚本。

如果您不想接受任何PATH修改,只需在子shell内执行export PATH="$PWD:$PATH",而不是env命令的一部分。

这些安装步骤现在是Docker image的一部分,如果这对人们参考有帮助的话。我不一定建议直接使用此图像,但欢迎您从Dockerfile复制。麻省理工学院许可。

答案 1 :(得分:1)

看看shenv:https://github.com/shenv/shenv。就像rbenv,pyenv,goenv和其他人一样,但对于shell,它可以让你在其他版本中安装不同版本的Bash(zsh,fish,yash等)。

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

答案 2 :(得分:0)

您可以使用Bash自己的工具来模拟旧版本的Bash。查找" compat" shopt上的选项。

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

shopt -s compat31
shopt -s globstar

即使{4}仅在Bash 4.0上引入globstar

答案 3 :(得分:0)

虽然很高兴知道可以在本地编译bash的任意版本(正如我在other answer中所讨论的),但是现在有一个更简单的选择-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