unix 如何在shell管道中使用不同的文件描述符?

icomxhvb  于 2023-05-17  发布在  Unix
关注(0)|答案(2)|浏览(246)

我正在处理一个脚本,它首先调用一个嘈杂的(stdoutstderr上有很多诊断)程序,然后用其他工具处理它的输出。
程序的冗长使得不可能简单地将其标准输出发送到管道,因此目前我们使用 * 临时文件 * --我想结束这种做法。
我们可以要求程序将数据写入/dev/fd/N,而不是/tmp/foo--它会这样做,没有问题(例如,它不需要seek文件)。
它目前发送到stdoutstderr的噪音,可以继续去那里--操作人员习惯于看到它,并会报警,如果它消失了...
但是如何安排描述符N的存在并将其发送到下一个程序的stdin中?

noisy -o /dev/fd/N ?????| filter -i /dev/stdin

如果这需要bash,那就这样吧,但我当然更喜欢适合整个sh家族的解决方案。

9jyewag0

9jyewag01#

如果我对你的问题理解正确的话,你有一个程序,它将噪声写入标准输出和标准错误,并将有用的数据写入一个用-o选项指定的文件。您希望标准输出和标准错误保持原样,但将有用的数据通过管道传输到过滤器程序中,而不是将其写入文件。
使用Bash最简单的方法是使用进程替换(参见ProcessSubstitution - Greg's Wiki):

noisy -o >(filter -i /dev/stdin)

请注意,进程替换在某些sh系列shell中不可用,在某些(不常见)平台上的Bash中不可用,并且在版本4.4之前,无法获得使用进程替换创建的进程的退出状态。
另一种可能的方法来做你想做的(我认为)是:

exec 3>&1
{ exec 4>&1; noisy -o /dev/fd/4 >&3 ; } | filter -i /dev/stdin
  • exec 3>&1使文件描述符3引用“真实的”标准输出。
  • exec 4>&1(因为它在作为流水线的第一级的进程中运行)使文件描述符4引用流水线中下一级的输入。
  • noisy ... >&3强制noisy的标准输出转到“真实的”标准输出。
  • 写入/dev/fd/4(至少在Linux上)将写入管道中的下一个阶段。

我只在Bash上测试过它,但我认为它应该能在其他sh系列shell上工作。

agxfikkp

agxfikkp2#

以下是一种可能的方法:

( \
  /my/noisy/script \
    2> >(tee /tmp/stderr.log) \
    1> >(tee /tmp/stdout.log) \
) 2>&1 | tee /tmp/both.log

用您喜欢的任何过滤器替换tee调用。

相关问题