我想创建一个命令包装器,分别记录stderr和stdout的日志,而不更改命令的输出。不改变输出的一个方面是确保stderr vs stdout上的输出顺序没有改变。
我创建了一个合成的最坏情况:(python -u
将解释器置于完全无缓冲模式)
$ cat outputter.py
from sys import stdout, stderr
for line in range(10):
from itertools import izip, cycle
for column, char, file in izip(
range(79),
cycle(('_', '|')),
cycle((stdout, stderr)),
):
file.write(char)
stdout.write('\n')
$ python -u outputter.py
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_
我可以保留两个流的记录,并通过一点点bash轻松地将它们重定向回原始目的地,但是交错会被破坏:
$ python -u outputter.py > >(tee stdout.txt) 2> >(tee stderr.txt >&2)
|||_____________||||||||||_||___||_|__|||___||_|_||__||___||_||___||_|_|__||__|
__||__||_|__||_||___||_|_|_|__||__||__||_|__||_||___||__||_|_|__||_||__|__||_|_
__||__||_|__||_||___||__||_|_|_|__||_||__||___||_|__||__||__||__||_|_|___|||_|_
__|_||__||_||___||__||__||_|__||_|__||__||_||___||_|_||___||_|__||_|__||_|__||_
__|__|||_||___||_|__||_|_|__||__||_|__||_|_|___||||___||_|__||__||_||___|||___|
_|___||||___|||___||_|__|||__|_||___|||__|_||___|||___||_|__|||__||__|__||__||_
_|_||__|__|||__|_||___|||___|||___|||__|_|||____|||___||||___|_|||____|||___||_
_|__|||__|__|||__|__|||__|__|||___|||___||_|__|||__|__||_|__||_|_||___||_|__||_
_||___|||___||||___|_||___||_|__|||__||__||__|_||__||__|_|||___||___||_||__||__
_|__||_||___|||___|||__|_||__|||___||___|||___|||___||_|__||__|||___|||__|_||__
结果实际上变化很大:
$ python -u outputter.py > >(tee stdout.txt) 2> >(tee stderr.txt >&2)
_______________|||||||||||||||||||||||||||||||||_______________________||||||__
__||||____|||____|||||_____||||____|||||____|||||______||||____||||_____|||||__
_||||||||__________|||||_____||||____|||||____|||___||||_____|||||_____|||||___
_|||_____||||____||||||______|||||_____||||||_____||||_____|||||_____|||||____
|_______|||||||||____||||_____||||____|||||______|||||____|||||_____|||||____||_
||_____||||____|||||_____|||||_____||||____||||____||||___||||____||||____|||__
___|||||____|||||_____||||____|||____|||||_____|||||_____|||||_____||||____|||_
__||||_____||||____|||||_____|||||____||||_____|||||_____||||____||||____||||__
__|||____||||____||||____|||||____|||||_____||||_____||||||_____||||_____||||__
_||____|||||_____||||____|||||____||||____||||_____|||||_____||||____|||||____
|
$ python -u outputter.py > >(tee stdout.txt) 2> >(tee stderr.txt >&2)
_|||||||_______|_|||____|||__|_|__|||__|_||___|||___||_|___||||___|||__||___||_
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
我的问题是:有没有可行的方法来做到这一点并保留原始流的交错?
另外,为什么终端没有同样的问题呢?我能想象的任何实现都会遇到同样的问题。
答案 0 :(得分:2)
不,你不能这样做。并且不是因为缓冲,这将产生相同的随机结果:
python -u outputter.py > >(cat -u >&2) 2> >(cat -u >&2)
问题是你的shell需要写入两个管道,它使用select(2)
来选择要写入的管道。由于没有填充任何管道缓冲区的危险,因此两个管道都“同等可用”进行写入,这会在两个cat
之间创建一个竞争条件:完成第一次写字符的胜利。比赛的结果取决于调度程序以及系统中当前正在发生的事情。因此随机性。
旁注:如果问题与缓冲有关,那么每次都会以相同的方式使结果出现乱码。