【问题标题】:Redirect stdout to file and tee stderr to the same file将标准输出重定向到文件并将标准错误重定向到同一个文件
【发布时间】:2020-09-03 07:29:47
【问题描述】:

我正在运行一个命令,该命令(很可能)将文本输出到 stderr 和 stdout。我想将 stderr 和 stdout 保存到同一个文件,但我只想将 stderr 打印到终端。

我怎样才能让它工作?我试过mycommand 1>&2 | tee file.txt >/dev/null,但不会在终端上打印任何东西。

【问题讨论】:

  • 这方面的棘手之处在于保持准确的排序。只做重定向本身很容易,我很确定我们已经涵盖了它。
  • (...和“棘手”,我的意思是,如果您需要完美的排序,您需要使用系统调用级别的跟踪来重建写入 会发生的顺序如果它们没有通过没有同步保证的不同长度的管道被重定向)。
  • @CharlesDuffy 是否可以使用whileread 逐行读取输入并确定哪些应该打印,哪些不应该打印?
  • 每个read 操作仅从一个文件描述符中读取。即使您使用以不同语言编写的代码和 select() 调用或其他方式同时收听多个 FD,但您仍然无法保证您的 select() 调用会收到相同的内容命令底层程序编写它。
  • (同理,每个write() syscall 只写一个文件描述符,这就是问题的根源。当stdout和stderr是同一个文件的两个不同副本时描述符,写入之间存在绝对顺序;但是一旦您希望它们单独处理,它们就不能再是同一个内核空间对象的副本,并且顺序变得未定义。

标签: bash io-redirection tee


【解决方案1】:

如果您不需要完美订购

使用tee 的两个单独副本,都以附加模式写入同一个文件,但随后只有其中一个将内容转发到/dev/null,将把你带到你需要的地方:

mycommand \
  2> >(tee -a file.txt >&2) \
   > >(tee -a file.txt >/dev/null)

如果您确实需要完美订购

Separately redirecting and recombining stderr/stdout without losing ordering

【讨论】:

  • 很遗憾,至少可以这么说。我确实需要订购。感谢您的帮助。
  • 如果你运行的底层程序是用 Java 编写的,log4j 是你的朋友;如果它在 Python、logging 标准库模块等中-B 在配置为复制到同一个文件时写入同一个文件描述符(除了任何备用接收器的其他文件描述符之外)。
  • ...但是,是的,这的耻辱;意味着简单/干净的 UNIX 模型通常是不够的。
  • 我正在编写(好吧,刚刚完成)一个 bash 脚本,所以我想我从一开始就注定要在不知不觉中失败:P
  • 如果它是你的脚本,你可以控制它如何记录日志。让你所有的信息日志都通过一个可以配置的函数(可能带有环境变量,但你对细节的调用)对不同的目的地进行两次单独的写入,你很好。
猜你喜欢
  • 2012-08-15
  • 2015-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多