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

dim*_*414 8 linux versioning bash integration-testing

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

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

更新

例如,我已经避免使用关联数组,因为它们是在Bash 4中引入的,但是如果没有测试我很难确定我不会意外地使用其他一些Bash 4+功能.

dim*_*414 8

最后回到这个问题,很容易编译(不安装)你感兴趣的bash版本.这就是我测试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.
Run Code Online (Sandbox Code Playgroud)

现在你有一个bash 3.2.57二进制文件,你可以运行,而不是实际"安装"它或修改你的正常环境.

要针对此版本运行shell脚本:

$ ./bash your_script.sh
Run Code Online (Sandbox Code Playgroud)

要输入干净的交互式提示:

$ 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$ 
Run Code Online (Sandbox Code Playgroud)

使用env -i而不是直接调用./bash会使您处于大多数空的环境中(env从shell内部运行以查看仍然设置的内容).更新PATH允许调用bash(例如bash -version)调用本地bash shell,而不是系统范围的安装(但请注意这会拉入整个PATH).添加--noprofile --norc可以避免加载您的.bashrc和相关的脚本.

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


这些安装步骤现在是Docker镜像的一部分,如果这有助于人们参考.我不一定建议直接使用此图像,但欢迎您从Dockerfile复制.MIT许可.


dim*_*414 5

虽然很高兴知道可以在本地编译任意版本的 bash(如我的其他答案中所述),但现在有一个更简单的选择 -官方 Dockerbash镜像

针对多个 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
Run Code Online (Sandbox Code Playgroud)