我正在用 bash 编写一个测试框架脚本并遇到了一个奇怪的情况。
为了说明目的,我在这篇文章中做了几件事:
echo
在脚本中添加行;这些不是测试套件的一部分。- 在宽度超过 80 个字符的终端窗口上运行所有脚本
- 通过例如,从它们所在的目录运行所有脚本
./test1
。
首先,有一个setup
脚本。它source
由各种测试脚本本身组成(它不能在子 shell 中运行,因为它需要设置环境变量)。第一个脚本如下所示。
# Make output consistent regardless of width of terminal running the script.
export COLUMNS=80
echo setup: $COLUMNS
脚本test1
如下。
#!/bin/bash
# Send output to both the screen and a file.
exec > >(tee logfile)
echo before: $COLUMNS
. ./setup
echo after: $COLUMNS
执行test1
得到预期结果。
before:
setup: 80
after: 80
但是,添加一行会使setup
这一切变得混乱。
# Make output consistent regardless of width of terminal running the script.
export COLUMNS=80
echo setup: $COLUMNS
date
echo setup 2: $COLUMNS
现在运行的输出test1
是:
before:
setup: 80
Tue Jul 2 13:36:43 CDT 2024
setup 2: 232
after: 232
bash 选项解释了这一点checkwinsize
。正如手册页中记录的此选项:“如果设置,bash 会在每个外部(非内置)命令之后检查窗口大小,并在必要时更新 LINES 和 COLUMNS 的值。默认情况下启用此选项。” export
和echo
不是外部命令,但是date
是,这就是为什么调用它会否决明确设置的$COLUMNS
值。
test2
当另一个测试脚本有不同的日志记录要求并将 stdout 和 stderr 都发送到 时,就会出现下一个怪异现象logfile
。
$ diff test1 test2
3c3
< exec > >(tee logfile)
---
> exec > >(tee logfile) 2>&1
运行test2
结果如下:
before:
setup: 80
Tue Jul 2 13:46:20 CDT 2024
setup 2: 80
after: 80
为什么这会推翻该checkwinsize
选择?
取消setup
设置checkwinsize
解决了我的实际问题,即让所有测试脚本都遵守明确设置的$COLUMNS
值。但我仍然不明白为什么添加会2>&1
改变行为。这是预期的结果吗?
我在 bash 版本 5.0.18(1) 下看到了这个问题。我知道这个版本有点旧了,我想知道在较新的 bash 下行为是否相同。
在我能访问的更旧的版本(版本 3.2.57(1))下,情况就不date
一样了——奇怪的是,这里的区别在于调用不会重置$COLUMNS
为终端宽度,尽管此版本的手册页记录checkwinsize
基本相同。因此,此版本确实似乎存在错误,因为它的行为与其文档不符。