Supongamos que tengo dos programas llamados ProgramA
y ProgramB
. Quiero ejecutarlos simultáneamente en el intérprete cmd de Windows. Pero quiero lo StdOut
de ProgramA
enganchado a lo StdIn
de ProgramB
y lo StdOut
de ProgramB
enganchado a lo StdIn
de ProgramA
.
Algo como esto
________________ ________________ El | El | El | El | El | StdIn (== ← === ← == (StdOut | El | Programa A | El | Programa B | El | El | El | El | El | StdOut) == → === → ==) StdIn | | ________________ | | ________________ |
¿Hay algún comando para hacer esto? ¿Alguna forma de lograr esta funcionalidad desde cmd?
windows
batch-file
redirection
stdout
stdin
DarthRubik
fuente
fuente
Respuestas:
¡No solo se puede hacer, se puede hacer con nada más que un archivo por lotes! :-)
El problema se puede resolver mediante el uso de un archivo temporal como "tubería". La comunicación bidireccional requiere dos archivos "pipe".
El proceso A lee stdin de "pipe1" y escribe stdout en "pipe2" El
proceso B lee stdin de "pipe2" y escribe stdout en "pipe1"
Es importante que ambos archivos existan antes de iniciar cualquiera de los procesos. Los archivos deben estar vacíos al inicio.
Si un archivo por lotes intenta leer de un archivo que se encuentra en el extremo actual, simplemente no devuelve nada y el archivo permanece abierto. Entonces, mi rutina readLine se lee continuamente hasta que obtiene un valor no vacío.
Quiero poder leer y escribir una cadena vacía, por lo que mi rutina writeLine agrega un carácter adicional que readLine elimina.
Mi proceso A controla el flujo. Inicia cosas escribiendo 1 (mensaje a B), y luego ingresa a un ciclo con 10 iteraciones donde lee un valor (mensaje de B), agrega 1 y luego escribe el resultado (mensaje a B). Finalmente, espera el último mensaje de B, y luego escribe un mensaje de "salir" a B y sale.
Mi proceso B está en un bucle condicionalmente interminable que lee un valor (mensaje de A), agrega 10 y luego escribe el resultado (mensaje en A). Si B alguna vez lee un mensaje de "salir", entonces termina inmediatamente.
Quería demostrar que la comunicación es totalmente sincrónica, por lo que introduzco un retraso en los bucles de proceso A y B.
Tenga en cuenta que el procedimiento readLine está en un circuito cerrado que abusa continuamente de la CPU y del sistema de archivos mientras espera la entrada. Se podría agregar un retraso PING al bucle, pero luego los procesos no serán tan receptivos.
Utilizo una tubería verdadera como una conveniencia para iniciar los procesos A y B. Pero la tubería no funciona porque no pasa comunicación por ella. Toda la comunicación es a través de mis archivos temporales "pipe".
También podría haber usado START / B para iniciar los procesos, pero luego tengo que detectar cuándo ambos terminan para saber cuándo eliminar los archivos temporales "pipe". Es mucho más simple usar la tubería.
Elegí poner todo el código en un solo archivo: el script maestro que inicia A y B, así como el código para A y B. Podría haber usado un archivo de script separado para cada proceso.
test.bat
--SALIDA--
La vida es un poco más fácil con un lenguaje de nivel superior. A continuación se muestra un ejemplo que usa VBScript para los procesos A y B. Todavía uso el lote para iniciar los procesos. Utilizo un método muy bueno descrito en ¿Es posible incrustar y ejecutar VBScript dentro de un archivo por lotes sin usar un archivo temporal? para incrustar múltiples scripts de VBS dentro de un solo script por lotes.
Con un lenguaje superior como VBS, podemos usar una tubería normal para pasar información de A a B. Solo necesitamos un único archivo "tubería" temporal para pasar información de B de nuevo a A. Como ahora tenemos una tubería funcional, la A el proceso no necesita enviar un mensaje de "salir" a B. El proceso B simplemente se repite hasta que llega al final del archivo.
Seguro que es bueno tener acceso a una función de suspensión adecuada en VBS. Esto me permite introducir fácilmente un pequeño retraso en la función readLine para dar un descanso a la CPU.
Sin embargo, hay una arruga dentro de readLIne. Al principio estaba teniendo fallas intermitentes hasta que me di cuenta de que a veces readLine detectaría que la información está disponible en stdin, e inmediatamente trataría de leer la línea antes de que B tuviera la oportunidad de terminar de escribirla. Resolví el problema introduciendo un pequeño retraso entre la prueba de fin de archivo y la lectura. Un retraso de 5 ms pareció hacerme el truco, pero lo dupliqué a 10 ms para estar seguro. Es muy interesante que el lote no sufra este problema. Discutimos esto brevemente (5 publicaciones cortas) en http://www.dostips.com/forum/viewtopic.php?f=3&t=7078#p47432 .
La salida es la misma que con la solución de lote puro, excepto que las líneas finales de "dejar de fumar" no están allí.
fuente
Nota: en retrospectiva, al leer la pregunta nuevamente, esto no hace lo que se le pide. Dado que, si bien vincula dos procesos juntos (¡de una manera interesante que incluso funcionaría en una red!), No lo hace en ambos sentidos.
Espero que obtengas algunas respuestas a esto.
Aquí está mi respuesta, pero no la acepte, espere otras respuestas, estoy ansioso por ver otras respuestas.
Esto fue hecho desde cygwin. Y usando el comando 'nc' (el inteligente). El 'wc -l' solo cuenta líneas. Así que estoy vinculando cualesquiera dos comandos, en este caso, echo y wc, usando nc.
El comando de la izquierda se realizó primero.
nc es un comando que puede a) crear un servidor, o b) conectarse como el comando telnet en modo sin formato, a un servidor. Estoy usando el uso 'a' en el comando izquierdo y el uso 'b' en el comando derecho.
Así que nc se sentó allí escuchando a la espera de una entrada, y luego canalizó esa entrada
wc -l
y contó las líneas y emitió el número de líneas ingresadas.Luego ejecuté la línea para hacer eco de un texto y enviarlo sin formato a 127.0.0.1:123, que es el servidor mencionado.
Puede copiar el comando nc.exe de cygwin e intentar usar eso y el archivo cygwin1.dll que necesita en el mismo directorio. O podrías hacerlo desde el mismo Cygwin como yo. No veo nc.exe en gnuwin32. Tienen una búsqueda en http://gnuwin32.sourceforge.net/ y nc o netcat no aparecen. Pero puedes obtener cygwin https://cygwin.com/install.html
fuente
netstat -aon | find ":123"
ver que el comando de la izquierda creó el servidorwc
posterior alecho
comando)nc -lp9999 | prog1 | prog2 | nc 127.0.0.1 9999
puede ser necesario tomar medidas para garantizar que los buffers se vacíen de manera oportunaUn truco (preferiría no hacer esto, pero esto es lo que voy a hacer por ahora) es escribir una aplicación C # para hacer esto por usted. No he implementado algunas características clave en este programa (como usar los argumentos que se me dieron), pero aquí está:
Luego, eventualmente, cuando este programa sea completamente funcional y se elimine el código de depuración, lo usaría de la siguiente manera:
fuente