Stderr 重定向也意外地重定向了一些 BASH 内置命令

Stderr 重定向也意外地重定向了一些 BASH 内置命令

我试图对运行交互式 BASH 脚本的用户隐藏所有 stderr,但将错误保留在日志文件中。然而,简单的 stderr 重定向出乎意料地隐藏了一些应该转到的 BASH 输出标准输出反而。在两个系统上尝试过这一点并得到相同的结果(一个有GNU bash,版本 4.1.2(1)-发布 (x86_64-redhat-linux-gnu)另一个是在 MacOS X 上)。

我一直怀疑这可能是由于exec更换外壳引起的......但是另一个内置的(times ) 按预期工作并输出到标准输出

一个例子:

#!/bin/bash

exec 2>>file_log

echo This will be printed to stdout, as expected

ls ThereIsNoSuchFileOnEarth # this will go to “file_log”, as expected

read –p 'User would never see this prompt and it would go to file_log. Totally unexpected.' –r -e test

species=”Daleks Raxacoricofallapatorians Judoon”

select enemy in $species;
do
     # …code omitted as the user would never see the list. It would go into file_log again!
done

答案1

提示来自readselect 应该是转到标准错误,因为它们可能是用户交互的提示,而不是实际的提示输出。这允许您运行tool.sh > tool.out并仍然使用read并向select用户收集信息,而不会“污染”实际输出。

标准输出是一个程序的典型输出,理想情况下它可以通过管道传输到另一个程序的标准输入,既不麻烦,也不混乱。

这也是为什么curl,例如,在标准错误而不是标准输出上显示其下载进度;您可以并且仅显示curl http://www.example.com/path/to/file > file的内容(因此重定向到,而信息数据使用标准错误显示。filefile

答案2

如果您使用exec重定向整个 shell 的 stderr,这会影响整个 shell。

您要么不能使用exec重定向整个 stderr,要么需要调用类似以下内容的内容:

read .... 2> /dev/tty

让相关的内置函数为 stderr 创建可读的输出。

相关内容