嗨根据this post,unbuffer
通过伪终端(pty)连接到命令,这使得系统将其视为交互式进程,因此不使用任何stdout缓冲。
我想在Windows上使用此功能。我可以知道Windows上unbuffer
程序的等价物吗?感谢。
答案 0 :(得分:7)
我花了一些时间在这上面并且成功了。我在研究期间找到了这个博客,并决定返回并提供我的解决方案,以便在一段时间内保存下一个人。我以虚假电子邮件作为客人回复,因此我不会进行互动,但不需要进一步的信息。
7月18日&12; 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 - 不需要
答案 1 :(得分:3)
您描述的行为是使用I / O运行时库的典型应用程序。默认情况下,大多数运行时库会检查句柄是否是字符模式设备(如控制台),如果是,则不执行任何缓冲。 (理想情况下,运行时库会以与控制台相同的方式处理管道,但似乎大多数都没有。)
我不知道有什么明智的方法可以让这样的应用程序认为它在写入管道时正在写入控制台。
附录:七年后,Windows 终于支持pseudoconsoles。如果您在Windows 10 v1809或更高版本上运行,则此新API可以解决您的问题。
在旧版本的Windows上,如果您知道需要多少数据,原则上可以使用console API functions为应用程序创建一个控制台来写入,然后从控制台读取输出。但是你不能用Java做到这一点,你需要编写一个C应用程序来为你做这件事。
类似地,原则上应该可以编写一个等同于Unix伪终端的设备驱动程序,一个像管道一样工作但是报告自己是一个字符模式设备。但是编写设备驱动程序需要特定的专业知识,并且必须进行数字签名,因此除非现有产品存在,否则这种方法可能不可行。
答案 2 :(得分:2)
免责声明:我的回答仅涉及使用MSVC编译的可执行文件。
缓冲策略在Microsoft C运行时(CRT)库中编码。您可以了解详情here。本文建议使用控制台句柄和操作控制台缓冲区来接收无缓冲的输出。
但是,Microsoft C运行时内部有一个未记录的功能,使用lpReserved2
和cbReserved2
结构的STARTUPINFO
字段直接从其父进程继承一些内部标记的文件句柄。您可以在Microsoft Visual Studio提供的crt源代码中找到详细信息。或者在GitHub上搜索posfhnd
之类的内容。
我们可以利用这个未记录的功能来提供管道句柄并为子进程指定FOPEN | FDEV
标志,以欺骗子进程处理该管道处理方式与FILE_TYPE_CHAR
句柄相同。
我有一个工作Python3 script来演示这种方法。