用于调试和管道输出(日志记录、指标等)的附加文件描述符

用于调试和管道输出(日志记录、指标等)的附加文件描述符

对于 bash 脚本项目,我将人类可读的日志信息写入 stdout/stderr。此外,我想将格式化的指标写入第三个流,默认情况下该流将被丢弃,但可以重定向以进行管道处理。是否建议使用附加文件描述符来执行此操作?

exec 3> /dev/null
echo "This is stdout"
echo "This is stderr" >&2
echo "This is fd3" >&3

我同意第三行在正常情况下不显示。但是,当在某个工具链中使用时,我想通过管道传输这些消息。简单的例子:

$ bash example.sh 3>&1
This is stdout
This is stderr

第三行不显示为控制台输出。

我究竟做错了什么?有针对这个的解决方法吗?是否建议采用另一种方法?

答案1

Fd 3 绑定/dev/null在第一行,因此第三个 Echo 不可避免地将其标准输出重定向到/dev/null

相反,通过检查 的存在来验证 Fd 3 是否已被分配/proc/self/fd/3。如果没有,则将其绑定到/dev/null。如果是,请不要管它。

[ -e /proc/self/fd/3 ] || exec 3> /dev/null
echo "This is stdout"
echo "This is stderr" >&2
echo "This is fd3" >&3
$ ./example.sh 3>&1
This is stdout
This is stderr
This is fd3
$ ./example.sh
This is stdout
This is stderr

如果第三个 Echo 实际上是一个写入大量输出的命令,则更有效的替代方案是仅在 Fd 3 打开时才触发该命令。

echo "This is stdout"
echo "This is stderr" >&2
[ -e /proc/self/fd/3 ] && echo "This is fd3" >&3

另一种可能性是始终通过 Fd 3 重定向到文件或 FIFO,并且仅在调用过程中需要时才读取它,但这也意味着如果不使用该输出,则会产生不必要的时间损失。

相关内容