微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Bash 多进程替换重定向命令

如何解决Bash 多进程替换重定向命令

我试图在 BASH 命令中使用多个进程替换,但我似乎误解了它们解析和重定向到彼此的顺序。

系统

Ubuntu 18.04
BASH 版本 - GNU bash,版本 4.4.20(1)-release (x86_64-pc-linux-gnu)

问题

我正在尝试将命令的输出重定向tee,将其重定向ts添加时间戳),然后将该重定向split(将输出拆分为单独的文件)。我可以让输出重定向teets,但是在重定向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 -)) - 这会打印带有时间戳的命令(如 teets 应该),此外还会创建带有命令输出的 10 字节文件(它们上没有时间戳)。 - 这是我的预期并且是有道理的,因为 tee 被分别重定向到两个进程替换,这主要是一个健全性检查

我认为正在发生的事情

据我所知,>(ts '[%Y-%m-%d %H:%M:%s]' >(split -d -b 10 -)) (以及 >(ts '[%Y-%m-%d %H:%M:%s]' >(echo)) 就此而言) 首先将解析为一个完整且独立的命令。因此 split(和 echo)从 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 接收然后输出命令输出)。我想我只是非常误解了流程替换在这一点上是如何工作的

解决方法

如果你真的想让一个命令将 stdin/stderr 重定向到一个单独的 ts|tee|split,你可以做的一件事是

command 1> >(ts '[%Y-%m-%d %H:%M:%S]' | tee -a >(split -d -b 10 -)) 2> >(ts '[%Y-%m-%d %H:%M:%S]' | tee -a >(split -d -b 10 -))

但缺点是 tee 仅在提示打印后才打印。可能有一种方法可以通过复制文件描述符来避免这种情况,但这是我能想到的最好的方法。

,

如果需要,您可以将命令中的错误流发送到与输出不同的管道中:

{ { cmd 2>&3 | ts ... | split; } 3>&1 >&4 | ts ... | split; } 4>&1

这会将 cmd 的输出发送到第一个管道,而来自 cmd 的错误流进入第二个管道。引入文件描述符 3 是为了将 tssplit 的错误流分开,但这可能是不可取的。引入 fd 4 是为了防止 split 的输出被第二个管道消耗,这可能是不必要的(例如,如果 split 不产生任何输出。)

,

这个:

ts '[%Y-%m-%d %H:%M:%S]' >(split -d -b 10 -)

ts 的命令行上扩展进程替换生成的文件名,因此运行的内容类似于 ts '[%Y-%m-%d %H:%M:%S]' /dev/fd/63ts 然后尝试打开转到 fdsplit 以从那里读取输入,而不是从原始标准输入读取。

这可能不是您想要的,在我的机器上,我在测试时在后台获得了一些 tssplit 的副本。可能已经成功连接到对方,这可以解释为什么没有错误信息。

你可能打算写

ts '[%Y-%m-%d %H:%M:%S]' > >(split -d -b 10 -)
                         ^

重定向到进程替换。

也就是说,您可以在 tssplit 之间使用管道。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?