11

嗨,根据这篇文章unbuffer通过伪终端(pty)连接到命令,这使得系统将其视为交互式进程,因此不使用任何标准输出缓冲。

我想在 Windows 上使用这个功能。我可以知道什么是unbufferWindows 上的程序等价物吗?谢谢。

4

3 回答 3

10

我花了一些时间在这上面并成功了。我在研究期间发现了这个博客,并决定返回并提供我的解决方案以节省下一个人的时间。我作为客人回复了一封虚假的电子邮件,因此我不会进行互动,但不需要进一步的信息。

2012 年 7 月 18 日 19:41,Harry Johnston 写道:

“原则上,如果你知道需要多少数据,你可以使用控制台 API 函数创建一个控制台供应用程序写入,然后从控制台读取输出。但你不能从 Java 中做到这一点,你需要编写一个 C 应用程序来为你做这件事。”

事情是,已经有一个实用程序可以做到这一点。它是为稍微不同的用途而编写的,但可以强迫它提供所需的结果。其预期目的是使 Windows 控制台应用程序能够与 Linux 风格的 tty 终端交互。它通过运行隐藏的控制台并直接访问控制台缓冲区来做到这一点。如果你试图使用它——你会失败。我很幸运,发现这个实用程序有一些未记录的开关,这将允许它提供简单的无缓冲输出。如果没有开关,它会在尝试管道输出时失败并​​出现错误——输出不是 tty。

该实用程序称为 winpty。你可以在这里得到它:

https://github.com/rprichard/winpty/releases

这里提到了未记录的开关:

https://github.com/rprichard/winpty/issues/103

我正在使用 MSYS2 版本。您需要 msys-2.0.dll 才能使用它。

只需运行:

winpty.exe -Xallow-non-tty -Xplain your_program.exe | receive_unbuffered_output.exe

-Xallow-non-tty, 将允许管道输出

-Xplain, 将删除添加的 Linux 终端转义码(或其他名称)

所需文件是:

winpty.exe
winpty-agent.exe
winpty.dll
msys-2.0.dll

winpty-debugserver.exe – 不需要

于 2017-06-13T21:27:06.520 回答
5

您所描述的行为是使用运行时库进行 I/O 的应用程序的典型行为。默认情况下,大多数运行时库会检查句柄是否是字符模式设备,例如控制台,如果是,它们不会进行任何缓冲。(理想情况下,运行时库会以与控制台相同的方式处理管道,但似乎大多数都没有。)

我不知道有任何明智的方法可以欺骗这样的应用程序,使其在实际写入管道时认为它正在写入控制台。

附录:七年后,Windows终于支持伪控制台。如果您在 Windows 10 v1809 或更高版本上运行,这个新 API 应该可以解决您的问题。

在旧版本的 Windows 上,如果您知道需要多少数据,原则上您可以使用控制台 API 函数创建一个控制台供应用程序写入,然后从控制台读取输出。但是你不能从 Java 中做到这一点,你需要编写一个 C 应用程序来为你做这件事。

类似地,原则上应该可以编写一个等效于 Unix 伪终端的设备驱动程序,它的作用类似于管道,但报告自己是字符模式设备。但是编写设备驱动程序需要特定的专业知识,并且必须进行数字签名,因此除非有现成的产品,否则这种方法不太可能可行。

于 2012-07-18T19:41:40.290 回答
2

免责声明:我的回答仅涉及使用 MSVC 编译的可执行文件。

缓冲策略在 Microsoft C 运行时 (CRT) 库中编码。您可以在此处了解详细信息。本文建议使用控制台句柄和操作控制台缓冲区来接收无缓冲的输出。

但是,Microsoft C 运行时中有一个未记录的功能,可以直接从其父进程使用lpReserved2和结构cbReserved2字段继承带有一些内部标志的文件句柄STARTUPINFO。您可以在 Microsoft Visual Studio 提供的 crt 源代码中找到详细信息。posfhnd或者在 GitHub 上搜索类似的东西。

我们可以利用这个未记录的特性来提供管道句柄并FOPEN | FDEV为子进程指定标志,以欺骗子进程将管道句柄视为FILE_TYPE_CHAR句柄。

我有一个工作Python3 脚本来演示这种方法。

于 2018-03-05T13:07:14.797 回答