Pregunta

he tenido la impresión de que los procesos en el sistema operativo tienen tres flujos estándares: stdin, stdout, and stderr. También he pensado que los editores de texto, como el trabajo vim tomando entrada sobre stdin y el envío de caracteres de escape ANSI sobre stdout. Sin embargo, mi opinión de cómo intérpretes de línea de comandos no se mantiene en este caso uno:

Cuando ejecuto el comando C:\cygwin\bin\bash.exe, me incitan con:

Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\masson>C:\cygwin\bin\bash.exe
bash-3.2$ 

... pero cuando lo ejecuto en Java con el siguiente fragmento, el flujo de entrada estándar está vacía:

ProcessBuilder pb = new ProcessBuilder("C:\\cygwin\\bin\\bash.exe");
pb.redirectErrorStream(true);
Process proc = pb.start();
final InputStream in = proc.getInputStream();

new Thread(new Runnable() {
  public void run() {
    // Blocks forever...
    in.read(new byte[1024]);
  }
}).start();

¿Qué está pasando aquí? Me han dicho que bash.exe se está ejecutando en modo interactivo. ¿Quiere decir esto que no se están utilizando los flujos estándares? ¿Cómo puedo seguir trabajando con estos programas de trabajo, y en última instancia, ¿cómo podría aplicar mi propia versión de cmd.exe? Creo que no soy la comprensión algo fundamental acerca de cómo intérpretes de línea de comandos funcionan ...

(Todos los enlaces a artículos que tratan temas relacionados sería muy apreciado. No he tenido mucho buscar suerte. Ah, y una última pregunta, son tratados de forma diferente flujos estándares en Windows que en la mayoría de los sistemas operativos basados ??en Unix? )

¿Fue útil?

Solución

Al estar en modo interactivo no significa que no se están utilizando los flujos estándares. Pero en este caso, Bash es más probable que se ejecuta en no Modo -interactive (es detectar que no está hablando directamente a la aplicación de terminal, por lo que se supone que está siendo utilizado mediante programación, y por lo tanto no se imprime el bienvenida banner). En este caso, los flujos estándares se siguen utilizando, es sólo que no se está de salida.

Como ergosys a cabo en punta, realmente no se puede confiar en in.read(new byte[1024]) regresar antes de que haya leído los 1024 bytes completos, aunque es probablemente correcto asumir que va a - sin embargo, que sin duda no va a volver antes de que sea leído por lo menos una bytes, y creo que ese es el problema aquí - usted no está consiguiendo incluso un byte de salida

.

Trate de pasar "-i" a bash para conseguir que se ejecute en modo interactivo.

Otros consejos

Cualquier programa que utiliza la biblioteca estándar de C puede decir si está hablando con un dispositivo TTY (a.k.a línea de comandos), utilizando la función isatty (). Bash probablemente detecta que está hablando con un tubo en lugar de un teléfono de texto y no emitirá un aviso.

Soy más un tipo de Python que un tipo de Java (por lo que todo lo que les digo es conjeturas rápidas de JavaDoc), pero parece que se está configurando un punto muerto multi-proceso.

in.read(new byte[1024]); no regresará hasta que a leer 1024 bytes de datos y bash.exe no emitirá su conjunto 1024 bytes antes de detenerse para esperar la entrada. (Para ello, el uso proc.getOutputStream() y alimentar algunos comandos para responder a.)

Como resultado, se obtiene Java espera de fiesta para responder y bash espera de Java para responder y ambos perfectamente dispuesto a esperar hasta que la muerte del universo sin aburrirse o cansado.

Mi consejo es usar in.available() antes de cada llamada a in.read() para evitar el bloqueo. De esta manera, se puede alternar entre la alimentación de datos dentro y tirando de él sin atascarse.

De hecho, probablemente sería mucho más simple y más sano a poco se envuelve en un BufferedReader .

Actualización del comentario: Además, cuando las herramientas como fiesta detectan que la entrada estándar no es un terminal (véase la llamada al sistema isatty), se amortiguan en gran (4K o más) trozos en el supuesto de que la entrada no es interactivo. No estoy seguro si va a ayudar, pero trate de iniciar fiesta con la bandera -i.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top