如何在 shell 管道中使用不同的文件描述符?
How to use a different file-descriptor in a shell pipeline?
我正在处理一个脚本,它首先调用一个嘈杂的程序(stdout
和 stderr
上有很多诊断)程序,然后用其他工具处理它的输出。
该程序的冗长使得无法简单地将其标准输出发送到管道,因此目前我们使用临时文件——我想结束这种做法。
而不是/tmp/foo
,我们可以要求程序将数据写入/dev/fd/N
——它会的,没问题(它不需要seek
文件,例如)。
它目前向stdout
和stderr
发送什么噪音,可以继续去那里--操作员已经习惯看到它,并且如果它消失就会报警...
但是我如何安排描述符 N
存在并被发送到下一个程序的 stdin
?
noisy -o /dev/fd/N ?????| filter -i /dev/stdin
如果这需要 bash
,那就这样吧,但我当然更喜欢适合整个 sh 系列的解决方案。
如果我对你的问题的理解正确,你有一个程序可以将噪声写入标准输出和标准错误,并将有用数据写入由 -o
选项指定的文件。您希望标准输出和标准错误保持原样,但将有用的数据通过管道传输到过滤程序中,而不是将其写入文件。
使用 Bash 最简单的方法是使用进程替换(参见 ProcessSubstitution - Greg's Wiki):
noisy -o >(filter -i /dev/stdin)
请注意,进程替换在某些 sh 系列 shell 中不可用,在某些(不常见的)平台上 Bash 不可用,并且无法获取已创建进程的退出状态在 4.4.
版本之前用 Bash 进行进程替换
另一种可能的方式来做你想做的(我认为)是:
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 一起使用。
我正在处理一个脚本,它首先调用一个嘈杂的程序(stdout
和 stderr
上有很多诊断)程序,然后用其他工具处理它的输出。
该程序的冗长使得无法简单地将其标准输出发送到管道,因此目前我们使用临时文件——我想结束这种做法。
而不是/tmp/foo
,我们可以要求程序将数据写入/dev/fd/N
——它会的,没问题(它不需要seek
文件,例如)。
它目前向stdout
和stderr
发送什么噪音,可以继续去那里--操作员已经习惯看到它,并且如果它消失就会报警...
但是我如何安排描述符 N
存在并被发送到下一个程序的 stdin
?
noisy -o /dev/fd/N ?????| filter -i /dev/stdin
如果这需要 bash
,那就这样吧,但我当然更喜欢适合整个 sh 系列的解决方案。
如果我对你的问题的理解正确,你有一个程序可以将噪声写入标准输出和标准错误,并将有用数据写入由 -o
选项指定的文件。您希望标准输出和标准错误保持原样,但将有用的数据通过管道传输到过滤程序中,而不是将其写入文件。
使用 Bash 最简单的方法是使用进程替换(参见 ProcessSubstitution - Greg's Wiki):
noisy -o >(filter -i /dev/stdin)
请注意,进程替换在某些 sh 系列 shell 中不可用,在某些(不常见的)平台上 Bash 不可用,并且无法获取已创建进程的退出状态在 4.4.
版本之前用 Bash 进行进程替换另一种可能的方式来做你想做的(我认为)是:
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 一起使用。