9
votes

Difficulté à fournir plusieurs entrées à une commande à l'aide d'Apache Commons Exec et d'extraction de la sortie

J'écris une application Java qui doit utiliser une application de ligne de commande externe à l'aide de la bibliothèque Apache Commons Exec. L'application que je dois exécuter a une durée de chargement assez longue, il serait donc préférable de garder une instance vivante au lieu de créer un nouveau processus à chaque fois. La façon dont le travail d'application est très simple. Une fois démarré, il attend de nouvelles entrées et génère des données comme une sortie, qui utilisent tous deux les E / S standard de l'application.

Ainsi, l'idée serait d'exécuter la ligne de commande, puis d'utiliser le pomptstreamhandler avec trois flux (sortie, erreur et entrée) et utilisez ces flux pour interagir avec l'application. Jusqu'à présent, j'ai eu ce travail dans des scénarios de base où j'ai une entrée, une sortie et l'application s'arrête alors. Mais dès que j'essaye d'avoir une deuxième transaction, quelque chose ne va pas. P>

Après avoir créé ma commande de commande, je crée mon exécuteur et le lancez-le comme suit: P>

while (!killThreads) {
    String input = inputQueue.take();

    processInput.write(input.getBytes());
    processInput.flush();

    IOQueue.put(input);
}


1 commentaires

Vous devriez ajouter une balise Java à votre message, aux «yeux» les plus expérimentés sur votre problème. Bonne chance.


3 Réponses :


10
votes

J'ai fini par jouer un moyen de faire ce travail. En regardant à l'intérieur du code de la bibliothèque Commons Exec, j'ai remarqué que les streampumpers utilisés par le PummStreamhandler n'ont pas afflué chaque fois qu'ils avaient de nouvelles données entrantes. C'est pourquoi le code a fonctionné lorsque je l'exécutions une seule fois, car il a automatiquement rougé et fermé le flux. J'ai donc créé des cours que j'ai appelés AutoflushingtreamPumper et AutoflushingPumpStreamhandler. Le plus tard est identique à un pompage de pompage normal mais utilise AutoflushingTreampumpers au lieu des habituels. L'autoflushingStreamPumper fait la même chose qu'un streampumper standard, mais afflète son flux de sortie chaque fois qu'il écrit quelque chose.

Je l'ai testé à peu près et il semble bien fonctionner. Merci à tous ceux qui ont essayé de comprendre cela!


3 commentaires

Aider un frère dehors? J'ai le même problème, pourriez-vous me faire un "solide" et publier le code que vous avez écrit (autoflushingStreamPumper et autoflushingpumpStreamHandler) ici ou à un gist ou quelque chose? Aucun sens dans la réinvention de cette roue ... Merci pour votre message!


Cela a aidé immensément, mais comme @groovycakes mentionné, un gist aurait aidé plus - alors voici un. Notez que c'est ce que j'utilise, pas nécessairement ce que l'OP utilisé. gist.github.com/4653381


Un exemple existe-t-il qui utilise AutoflushingTreamPumper et AutoflushingPumpstreamHandler?



2
votes

Pour mes besoins, il s'avère que je n'ai besoin que de remplacer le "ExecuTestreamhandler". Voici ma solution, qui capture STDERR dans un StringBuilder et vous permet de diffuser des choses à STDIN et de recevoir des objets de stdout:

class SendReceiveStreamHandler implements ExecuteStreamHandler


1 commentaires

Dans votre code, votre récepteur, votre transfertPleteEvent et DataReceiveEvent n'est pas dans vos importations. Quel paquet contient ces classes?



1
votes

Pour pouvoir écrire plus d'une commande dans le STDIN du processus, j'ai créé un nouveau xxx

à utiliser ce nouvel exécuteur, je garde le flux de canalisations dans le pumpStreamHandler à Évitez que la STDIN soit à proximité du pumpStreamhandler. xxx

Vous pouvez utiliser la méthode de l'exécutant () ou créer le vôtre.


0 commentaires