我想创建一个命令包装器,分别记录 stderr 和 stdout 的日志,而不更改命令的输出。不更改输出的一方面是确保 stderr 与 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)
_|||||||_______|_|||____|||__|_|__|||__|_||___|||___||_|___||||___|||__||___||_
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
________________________________________
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
我的问题是:是否有任何可行的方法可以做到这一点并保留原始流的交错?
另外,为什么终端没有出现同样的问题?我能想象的任何实现都会有同样的问题。
最佳答案
不,你不能那样做。这不是因为缓冲,这会产生相同的随机结果:
python -u outputter.py > >(cat -u >&2) 2> >(cat -u >&2)
问题是您的 shell 需要写入两个管道,并且它使用 select(2)
来选择要写入的管道。由于不存在填充任何管道缓冲区的危险,因此两个管道“同样可”写入,这会在两个 cat
之间创建竞争条件:第一个完成写入字符的管道获胜。比赛的结果取决于调度程序以及系统中此时发生的情况。因此具有随机性。
附带说明:如果问题与缓冲有关,那么每次都会以相同的方式得到结果乱码。
关于python - 独立地执行 stdout 和 stderr,不增加抖动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30796006/