Supposons que j'ai deux programmes appelés ProgramA
et ProgramB
. Je veux les exécuter simultanément dans l'interpréteur Windows cmd. Mais je veux que le StdOut
d' ProgramA
accroché à StdIn
des ProgramB
et StdOut
des ProgramB
accroché à StdIn
des ProgramA
.
Quelque chose comme ça
________________ ________________ | | | | | StdIn (== ← === ← == (StdOut | | Programme A | | Programme B | | | | | | StdOut) == → === → ==) StdIn | | ________________ | | ________________ |
Existe-t-il une commande pour ce faire - un moyen d'obtenir cette fonctionnalité à partir de cmd?
windows
batch-file
redirection
stdout
stdin
DarthRubik
la source
la source
Réponses:
Non seulement cela peut être fait, mais cela ne peut être fait qu'avec un fichier batch! :-)
Le problème peut être résolu en utilisant un fichier temporaire comme "pipe". La communication bidirectionnelle nécessite deux fichiers "pipe".
Le processus A lit stdin de "pipe1" et écrit stdout dans "pipe2" Le
processus B lit stdin de "pipe2" et écrit stdout dans "pipe1"
Il est important que les deux fichiers existent avant de lancer l'un ou l'autre processus. Les fichiers doivent être vides au début.
Si un fichier de commandes tente de lire à partir d'un fichier qui se trouve être à la fin actuelle, il ne renvoie simplement rien et le fichier reste ouvert. Ainsi, ma routine readLine lit en continu jusqu'à ce qu'elle obtienne une valeur non vide.
Je veux pouvoir lire et écrire une chaîne vide, donc ma routine writeLine ajoute un caractère supplémentaire que readLine supprime.
Mon processus A contrôle le flux. Il initie les choses en écrivant 1 (message à B), puis entre dans une boucle avec 10 itérations où il lit une valeur (message de B), ajoute 1, puis écrit le résultat (message à B). Enfin, il attend le dernier message de B, puis écrit un message "quitter" dans B et quitte.
Mon processus B se trouve dans une boucle conditionnellement sans fin qui lit une valeur (message de A), ajoute 10, puis écrit le résultat (message dans A). Si B lit jamais un message "quitter", il se termine immédiatement.
Je voulais démontrer que la communication est entièrement synchrone, donc j'introduis un retard dans les boucles de processus A et B.
Notez que la procédure readLine est dans une boucle étroite qui abuse continuellement à la fois du CPU et du système de fichiers pendant qu'elle attend l'entrée. Un délai PING pourrait être ajouté à la boucle, mais les processus ne seront pas aussi réactifs.
J'utilise un vrai tuyau pour faciliter le lancement des processus A et B. Mais le tuyau n'est pas fonctionnel en ce sens qu'aucune communication ne le traverse. Toutes les communications se font via mes fichiers "pipe" temporaires.
J'aurais tout aussi bien pu utiliser START / B pour lancer les processus, mais je dois ensuite détecter quand ils se terminent tous les deux afin de savoir quand supprimer les fichiers temporaires "pipe". Il est beaucoup plus simple d'utiliser le tuyau.
J'ai choisi de mettre tout le code dans un seul fichier - le script principal qui lance A et B, ainsi que le code pour A et B. J'aurais pu utiliser un fichier de script distinct pour chaque processus.
test.bat
--PRODUCTION--
La vie est un peu plus facile avec une langue de niveau supérieur. Voici un exemple qui utilise VBScript pour les processus A et B. J'utilise toujours le batch pour lancer les processus. J'utilise une méthode très cool décrite dans Est-il possible d'incorporer et d'exécuter VBScript dans un fichier batch sans utiliser de fichier temporaire? pour incorporer plusieurs scripts VBS dans un même script batch.
Avec un langage plus élevé comme VBS, nous pouvons utiliser un canal normal pour transmettre des informations de A à B. Nous n'avons besoin que d'un seul fichier "canal" temporaire pour transmettre des informations de B à A. Parce que nous avons maintenant un canal fonctionnel, le A le processus n'a pas besoin d'envoyer un message "quitter" à B. Le processus B boucle simplement jusqu'à ce qu'il atteigne la fin du fichier.
C'est bien d'avoir accès à une fonction de veille appropriée dans VBS. Cela me permet d'introduire facilement un court délai dans la fonction readLine pour donner une pause au CPU.
Cependant, il y a une ride dans readLIne. Au début, j'obtenais des échecs intermittents jusqu'à ce que je réalise que parfois readLine détectait que des informations étaient disponibles sur stdin et essayait immédiatement de lire la ligne avant que B n'ait la chance de terminer l'écriture de la ligne. J'ai résolu le problème en introduisant un court délai entre le test de fin de fichier et la lecture. Un retard de 5 ms semblait faire l'affaire pour moi, mais je l'ai doublé à 10 ms juste pour être sûr. Il est très intéressant que le lot ne souffre pas de ce problème. Nous en avons discuté brièvement (5 courts messages) sur http://www.dostips.com/forum/viewtopic.php?f=3&t=7078#p47432 .
La sortie est la même que pour la solution par lots pure, sauf que les lignes finales de «sortie» ne sont pas là.
la source
Remarque - Rétrospectivement, en relisant la question, cela ne fait pas ce qui est demandé. Depuis, alors qu'il relie deux processus ensemble (d'une manière intéressante qui fonctionnerait même sur un réseau!), Il ne relie pas les deux.
J'espère que vous obtiendrez quelques réponses à cela.
Voici ma réponse mais ne l'acceptez pas, attendez d'autres réponses, je suis impatient de voir d'autres réponses.
Cela a été fait à partir de cygwin. Et en utilisant la commande 'nc' (la plus intelligente). Le «wc -l» ne compte que les lignes. Je relie donc les deux commandes, dans ce cas, echo et wc, en utilisant nc.
La commande de gauche a été exécutée en premier.
nc est une commande qui peut a) créer un serveur, ou b) se connecter comme la commande telnet en mode brut, à un serveur. J'utilise l'utilisation «a» dans la commande de gauche et l'utilisation «b» dans la commande de droite.
Donc, nc était assis à écouter en attendant une entrée, puis il dirigeait cette entrée vers
wc -l
et comptait les lignes et produisait le nombre de lignes entrées.J'ai ensuite couru la ligne pour faire écho du texte et envoyer ce brut à 127.0.0.1:123 qui est le serveur mentionné.
Vous pouvez copier la commande nc.exe à partir de cygwin et essayer d'utiliser cela et le fichier cygwin1.dll dont il a besoin dans le même répertoire. Ou vous pouvez le faire à partir de cygwin lui-même comme je l'ai fait. Je ne vois pas nc.exe dans gnuwin32. Ils ont une recherche http://gnuwin32.sourceforge.net/ et nc ou netcat ne s'affiche pas. Mais vous pouvez obtenir cygwin https://cygwin.com/install.html
la source
netstat -aon | find ":123"
pour voir que la commande de gauche a créé le serveurwc
arrière vers laecho
commande).nc -lp9999 | prog1 | prog2 | nc 127.0.0.1 9999
des mesures devront peut-être être prises pour s'assurer que les tampons sont vidés en temps opportunUn hack (je préférerais ne pas le faire, mais c'est ce que je vais faire pour l'instant) consiste à écrire une application C # pour le faire pour vous. Je n'ai pas implémenté certaines fonctionnalités clés de ce programme (comme utiliser les arguments qui m'ont été fournis), mais voici:
Puis, finalement, lorsque ce programme sera pleinement fonctionnel et que le code de débogage sera supprimé, vous utiliserez quelque chose comme ceci:
la source