【发布时间】:2019-01-21 12:51:36
【问题描述】:
我在 SO 中挖掘了大约 20 个问题,以寻找解决此问题的方法,但没有运气。这似乎是一项常见的任务。
我对 bash 脚本有以下要求:
- 将
stdout发送到log.out,而不是发送到控制台 - 将
stderr发送到log.outAND 到控制台 - 向控制台(和
log.out?)发送任意状态消息
目前我正在尝试以下方法来实现这一目标:
#!/bin/bash
> log.out
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>log.out 2>&1
# Test
echo "status goes to console" >&3
echo "stderr goes to file + console" >&2
echo "stdout goes to file"
我对这段代码的理解大致是……
- 将 stdout 备份到 FD 3,将 stderr 备份到 FD 4
- 脚本退出时重置它们(可能没有必要?)
- 将 stdout 发送到 log.out,并将 stderr 也发送到那里
除了错误不会显示到控制台之外,这一切正常。
所以,我想,我将在单独的 bg 进程中将 /dev/stderr 转换为 &3,并在第二个 exec 下添加这一行:
cat /dev/stderr >&3 &
我不明白为什么,但是,这也会将标准输出发送到 &3,所以我的控制台显示:
echoes goes to console
stderr goes to file + console
stdout goes to file
我已经尝试了大约 50 种组合,但均未成功。经过大量阅读后,我倾向于需要一个(自定义?)C 程序或类似程序来实现这一点,这对我来说似乎有点疯狂。
非常感谢任何帮助。
谢谢!
嘿,感谢@charles-duffy 的 cmets 和答案,我能够对现有脚本进行非常小的修改,从而实现了我正在寻找的总体思路:
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>log.out 2> >(tee /dev/tty >&1)
缺点是消息在日志文件中确实出现乱序。
【问题讨论】:
-
您将失去写入之间的同步。
-
就像写入控制台一样?只要
log.out文件的顺序正确,异步就可以了。 -
事情就是这样——当你这样做时,你就失去了保证秩序的能力。我们有一些很好的副本,并深入解释了原因;寻找他们。
-
...基本上,操作系统只保证写入两个 FD 的顺序将导致当它们都是
fdup()s 时追加按该顺序。如果两个 FD 指向不同的目的地,则它们不能相互重复。 -
顺便说一句,
> log.out然后exec >>log.out而不是单独的exec >log.out有什么意义?无论哪种方式,您都在截断文件,然后在整个过程中附加到它。
标签: bash shell stdout stderr io-redirection