写入标准错误

写入标准错误

我在用着斯德雷德将流到 stderr 的所有输出着色为红色。运行良好。但是,当我编写自己的 bash 脚本并抛出错误时echo 'error' 1>&2,它不会将输出着色为红色。我认为这是因为该命令只是将输出重定向到 stderr 文件描述符指向的位置,但没有正确地将消息标记为属于 stderr。是这样吗?如何在 bash 中正确写入 stderr?

答案1

看来该程序正在重写各种 write() 函数来检测您是否正在打印到文件描述符 2,然后添加相关的转义码以使终端输出为红色。

不幸的是,在 shell 中,当你做类似的事情时

echo "foo" 1>&2 

该函数仍将在文件描述符 1 上调用 write(或其他类似的系统调用)。输出出现在 fd 2 上,因为文件描述符 1 已被 shell 复制到文件描述符 2。

不幸的是,我不知道如何在 shell 中将 /directly/ 写入 fd 2,但您可以使用 awk。像这样的函数会将参数直接写入文件描述符 2。

error() {
  awk " BEGIN { print \"$@\" > \"/dev/fd/2\" }"
}

我相信这是 GNU awk 的一个功能,不是 POSIX 的一部分,但它也适用于 OS X 上提供的 awk。

答案2

该软件挂钩write()似乎在文件描述符 2(称为stderr.

它是一个共享库(因此不需要重新编译内核)。正如安装手册中所述,它使用环境变量LD_PRELOAD。动态链接器可能会在程序执行期间修改其行为。这些变量通过在备用位置搜索共享库来调整运行时链接过程。

可执行文件/bin/bash本身不支持此类变量,因此bash它本身使用系统调用的原始调色板,而不是修改后的调色板。您在问题中提到的重定向发生在bash.不在 的可执行文件中echo。如果echo可以自己写入错误描述符(而不是通过 bash),则输出将为红色。

Python 可以写入stderr.请参阅证明(应显示为红色):

python -c 'import os; os.write(2, "error")'

答案3

创建一个辅助函数:

echoerr() { printf "\033[0;31m%s\n\033[0m" "$*" >&2; }

并在任何地方使用它:

echoerr "something went wrong here"

这结合了写入 stderr ( >&2) 和更改颜色(解决方案取自此处https://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux)。

答案4

根据指示https://github.com/sickill/stderred你应该添加到你的脚本中

export LD_PRELOAD="/path/to/stderred/\$LIB/libstderred.so${LD_PRELOAD:+:$LD_PRELOAD}"

其中$LIB可能应该手动替换到您的架构上

相关内容