Unix 脚本命令在取消缓冲时中断终端

Unix script command breaks terminal when unbuffering

抱歉标题不靠谱,也许有人可以改进它。

我在 Python 子进程中使用 script 命令来解除命令输出的缓冲。然后我从该过程中读取了一行,最后我打印了一些文本。这是我的代码(此文件名为 script.py):

import subprocess
import time

proc = subprocess.Popen(["script", "-q", "-c", "cat script.py", "/dev/null"],
                        stdout=subprocess.PIPE, stderr=subprocess.PIPE)

# proc = subprocess.Popen(["stdbuf", "-oL", "-eL", "cat", "script.py"],
#                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)

proc.stdout.readline()

print("printing before...")
print("printing before...")
print("printing before...")

time.sleep(2)

print("printing after...")
print("printing after...")
print("printing after...")

我得到了这种绝对奇怪的行为,这样当子进程写入标准输出时,后续的 python 打印语句在每行之后包含几个空格,直到进程终止。这是它的屏幕截图:

据我所知,它在每一行之后打印的空格数与终端中的列数相同。我认为这可能与马车returns有关,但我真的不知道。我不明白为什么这会影响 python 的输出,因为我在执行 Popen.[=19= 时抑制了 stdoutstderr ]

我 运行 在 arch linux、python 版本 3.8.6 和 uname -a 输出:

Linux carbon 5.9.10-arch1-1 #1 SMP PREEMPT Sun, 22 Nov 2020 14:16:59 +0000 x86_64 GNU/Linux

如果我能提供任何其他信息,请告诉我。

因为您的子进程 stdin 仍然是一个 TTY,script 已经到达并改变了它处理 CR 和 LF 的模式。您的前 3 张照片是在 script 仍在 运行ning 的背景下完成的。在休眠期间,script 固定终端并退出。如果您等待子流程完成,问题就会消失……通常。信号有可能会阻止 script 自行清理并破坏您的会话的其余部分。可能更好的选择是重定向标准输入。

proc = subprocess.Popen(["script", "-q", "-c", "cat script.py", "/dev/null"],
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

这都是相当冒险的。如果执行的程序写入足够的数据来填充其标准输出管道,它将挂起。如果您只想在 TTY 下使用 运行 的程序的第一行,您可以使用 pty.spawn 来完成这项工作。有趣的是,它的文档有一个 EXAMPLE script implementation.