我试图在Bash命令中使用多个进程替换,但我似乎误解了它们相互解析和重定向的顺序。
系统
Ubuntu 18.04
Bash版本-GNU bash,版本4.4.20(1)-Release(x86_64-PC-Linux-GNU)
问题所在
我正在尝试将命令的输出重定向到tee
,将其重定向到ts
(添加时间戳),然后将其重定向到split
(将输出拆分成单独的文件)。我可以让输出重定向到tee
和ts
,但在重定向到split
时遇到了问题。
我的尝试
command >(tee -a >(ts '[%Y-%m-%d %H:%M:%S]' > tempfile.txt))
-这会将输出重定向到tee
的进程替换,然后重定向到进程替换ts
,并添加时间戳,然后重定向到tempfile.txt这是我所期望的command >(tee -a >(ts '[%Y-%m-%d %H:%M:%S]' >(split -d -b 10 -)))
-这没有任何作用,即使我希望结果会是一堆在不同行上带有时间戳的10字节文件。
为了继续测试,我尝试使用echo
,而不是查看command >(tee -a >(ts '[%Y-%m-%d %H:%M:%S]' >(echo)))
会发生什么情况--打印来自初始tee
的打印(理应如此),但echo
打印一个空行,这显然与我得到的新结果无关-请参见底部的编辑command >(tee -a >(ts '[%Y-%m-%d %H:%M:%S]') >(split -d -b 10 -))
-这会打印带有时间戳的命令(就像tee
和ts
应该的那样),此外还会创建带有命令输出的10个字节的文件(没有时间戳)。-这是我所期望的,也是有意义的,因为TEE被分别重定向到两个进程替换,这主要是一次理智的检查
我认为正在发生的事情
据我所知,>(ts '[%Y-%m-%d %H:%M:%S]' >(split -d -b 10 -))
首先作为一个完整的、独立的命令进行解析。因此,split
(和echo
)正在接收来自ts
的空输出,而ts
本身没有输出。只有在此之后,实际命令才会解析并将其输出发送到其替换tee
。
这不能解释为什么command >(tee -a >(ts '[%Y-%m-%d %H:%M:%S]' > tempfile.txt))
可以工作,因为根据这个理论,tee
本身没有输出,所以ts
应该接收而不是输入,并且还应该输出空白。
所有这些都是说,我真的不确定正在发生什么。
我想要什么
基本上,我只是想了解如何让command >(tee -a >(ts '[%Y-%m-%d %H:%M:%S]' >(split -d -b 10 -)))
以它看起来应该的方式工作。我需要命令输出将自身发送到进程替代tee
,它将把它发送到进程替代ts
,并添加时间戳,这将把它发送到split
,并将输出拆分成几个小文件。
我尝试了command > >(echo)
,但看到输出为空,这与我预期的不同(我希望echo
接收并输出命令输出)。我想我只是在很大程度上误解了进程替换在这一点上是如何工作的。
3条答案
按热度按时间dxxyhpgq1#
如果需要,您可以将命令中的错误流发送到与输出不同的管道中:
这会将
cmd
的输出发送到第一个管道,而来自cmd
的错误流则进入第二个管道。引入文件描述符3是为了将来自ts
和split
的错误流分开,但这可能并不可取。引入fd4是为了防止split
的输出被第二个流水线消耗,这可能是不必要的(例如,如果split
不产生任何输出)。kqhtkvqz2#
如果您真的想让一个命令将stdin/stderr重定向到单独的
ts|tee|split
,您可以做的一件事是但缺点是,只有在打印提示符之后才会打印T恤。可能有一种方法可以通过复制文件描述符来避免这种情况,但这是我能想到的最好的方法。
pdkcd3nj3#
这一点:
在
ts
的命令行上展开由进程替换生成的文件名,因此运行的内容类似于ts '[%Y-%m-%d %H:%M:%S]' /dev/fd/63
。然后,ts
尝试打开转到split
的fd
,以从那里读取输入,而不是从原始标准输入读取。这可能不是您想要的,在我的机器上,我在测试时有一些
ts
和split
的副本卡在后台。可能彼此成功连接,这可能解释了没有错误消息的原因。你可能是想写
并重定向到进程替换。
也就是说,您只需在
ts
和split
之间使用管道即可。