2012-07-17 25 views
5

Hola de acuerdo con this post, unbuffer se conecta a un comando a través de un pseudo-terminal (pty), lo que hace que el sistema lo trate como un proceso interactivo, por lo tanto, no utiliza ningún búfer stdout.¿Cuál es el equivalente del programa de desvinculación en Windows?

Me gustaría utilizar esta función en Windows. ¿Puedo saber qué es el equivalente del programa unbuffer en Windows? Gracias.

+0

No hay equivalente. Windows no tiene pseudo-terminales. –

+0

@HarryJohnston Hola Harry, me gustaría usar Java para ejecutar comandos externos y leer la salida stdout 'en tiempo real'. Algunos programas .exe me están dando problemas debido al almacenamiento en búfer stdout. No pude obtener ningún resultado de stdout cuando el programa aún se está ejecutando. Cuando finaliza el programa, de repente obtengo una gran salida estándar. (Este programa puede generar salida stdout en tiempo real cuando lo ejecuto manualmente en la ventana del símbolo del sistema). ¿Cómo puedo resolver este problema si no hay un pseudo terminal en Windows? – userpal

+0

No es el sistema operativo que hace el almacenamiento en búfer, es la aplicación. Necesitará reparar los programas .exe en cuestión para que no almacenen en búfer su salida. –

Respuesta

2

El comportamiento que está describiendo es típico de las aplicaciones que utilizan bibliotecas de tiempo de ejecución para E/S. De forma predeterminada, la mayoría de las bibliotecas de tiempo de ejecución comprueban si el identificador es un dispositivo en modo de caracteres, como una consola, y si es así, no hacen ningún almacenamiento en búfer. (Idealmente, la biblioteca de tiempo de ejecución trataría una tubería de la misma manera que una consola, pero parece que la mayoría no).

No conozco ninguna forma sensata de engañar a una aplicación para que piense está escribiendo en una consola cuando en realidad está escribiendo en una tubería.

En principio, si conoce la cantidad de datos que se espera, puede usar el console API functions para crear una consola para la aplicación a la cual escribir y luego leer la salida de la consola. Pero no puedes hacer eso desde Java, necesitarías escribir una aplicación C para que lo haga por ti.

De manera similar, en principio debería presumiblemente ser posible escribir un controlador de dispositivo equivalente a un pseudo-terminal Unix, que actúe como un conducto pero que se considere un dispositivo en modo de caracteres. Pero escribir controladores de dispositivos requiere experiencia específica, y tienen que estar firmados digitalmente, por lo tanto, a menos que exista un producto existente, no es probable que este enfoque sea factible.

+0

Una opción existente puede ser el emulador [com0com] (http://com0com.sourceforge.net/) null-modem.(Si no recuerdo mal, los puertos serie generalmente se tratan como no almacenados). –

4

Pasé un tiempo en esto y lo logré. Encontré este blog durante la investigación, y decidí regresar y proporcionar mi solución para salvar al siguiente tipo en algún momento. Respondo como un invitado con un correo electrónico falso, por lo que no interactuaré, pero no se requerirá más información.

El 18 de julio a las 19:41 '12 Harry Johnston escribió:

"En principio, si se sabe la cantidad de datos que puede esperar, podría utilizar las funciones API de consola para crear una consola para la aplicación escriba y luego lea el resultado de la consola. Pero no puede hacer eso desde Java, necesitaría escribir una aplicación C para que lo haga por usted ".

La cosa es, ya existe una utilidad que hace esto. Está escrito para un uso ligeramente diferente, pero puede ser coherente para proporcionar el resultado deseado. Su propósito es permitir que una aplicación de consola de Windows interactúe con un terminal tty de estilo Linux. Lo hace ejecutando una consola oculta y accede directamente al búfer de la consola. Si intentaste usarlo, fallarías. Tuve suerte y descubrí que hay conmutadores no documentados para esta utilidad que le permitirán proporcionar una salida sin búfer simple. Sin los interruptores falla con el error - la salida no es una tty - cuando se trata de canalizar la salida.

La utilidad se llama winpty. Se puede conseguir aquí: se mencionan aquí

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

Los interruptores indocumentados:

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

estoy usando la versión MSYS2. Necesitarás el msys-2.0.dll para usarlo.

simplemente ejecute:

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

-Xallow-non-tty, permitirá la producción de tuberías

-Xplain, se eliminarán los códigos de escape añadido Linux (o como se llamen)

archivos requeridos son:

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

winpt y-debugserver.exe - No es necesario

+0

Sí, funciona, ayudó a resolver eso: https://stackoverflow.com/questions/46443544/python-popen-sdtout-doesnt-get-all- the-output-when-exe-failed –

0

Descargo de responsabilidad: Mi respuesta solo se refiere a los ejecutables compilados utilizando MSVC.

La política de almacenamiento en búfer está codificada dentro de la biblioteca Microsoft C Runtime (CRT). Puede conocer los detalles here. Este artículo sugiere utilizar controles de consola y manipular búferes de consola para recibir resultados sin búfer.

Sin embargo, hay una característica no documentada dentro de Microsoft C Runtime para heredar identificadores de archivo con algunos indicadores internos directamente de su proceso padre usando lpReserved2 y cbReserved2 campos de STARTUPINFO estructura. Puede encontrar los detalles en el código fuente de crt provisto por Microsoft Visual Studio. O busque algo como posfhnd en GitHub.

Podemos explotar esta característica no documentada para proporcionar un identificador FOPEN | FDEV para el proceso secundario, para engañar al proceso secundario que trate el asa de tubería de la misma forma que un identificador FILE_TYPE_CHAR.

Tengo un Python3 script trabajando para demostrar este método.

Cuestiones relacionadas