2009-04-29 4 views
9

J'ai une application Java qui utilise ProcessBuilder pour préparer une commande de système d'exploitation et me donne un objet Process. (La commande os actuelle est rsync sur ssh en utilisant cygwin). Cela fonctionne bien dans Windows, mais si je veux arrêter le processus en utilisant process.destroy() il ne va pas tuer les processus ssh et rsync enfant ..... Je dois les tuer manuellement en utilisant le gestionnaire de tâches Windows ..Java ProcessBuilder process.destroy() ne détruit pas les processus enfants dans winXP

Est-il possible d'obtenir le OutputStream du processus et envoyer un ctrl-c en quelque sorte avant d'appeler destroy();?

Si quelqu'un a des idées sur une solution de contournement ce serait génial. Merci, D

+1

La fonction Ctrl-C est une fonction de terminal qui envoie un signal (SIGTERM?) À l'identificateur de processus. Donc, pour émuler que vous auriez besoin de l'id de processus et pour pouvoir envoyer un signal –

Répondre

5

Je pense aussi que l'émulation de Ctrl-C afin de tuer complètement ssh est problématique.

Ce que je ferais, est l'une des approches suivantes. Soit utiliser les commandes windows pour trouver qui sont les fils de ssh (ce qui est un peu problématique, puisque vous devez connaître votre pid actuel pour recevoir vos propres enfants). Je crois que pstools de sysinternals est un bon outil de ligne de commande qui devrait vous permettre de suivre les processus orphelins. Voir this example pour contrôler les processus Windows soit avec taskList.exe (qui peut vous donner sa sortie au format CSV BTW) ou en exécutant un VBScript spécial.

La deuxième approche utilise une bibliothèque Java telle que winp pour exécuter et contrôler le processus SSH. Je crois que vous seriez capable de lister tous ses enfants et de les tuer de force si envoyer le bon message ne suffirait pas. Ce serait mon approche préférée. Veuillez noter que la méthode killRecursively fait exactement ce que vous voulez.

Veuillez noter que ces approches ne doivent pas afficher uniquement les fenêtres de votre application. Vous pouvez encapsuler ceux dans une classe qui fonctionnerait différemment sur les machines Windows et Linux.

Veuillez noter que je n'ai pas essayé d'obtenir un contrôle fin sur les processus Windows avec, donc je ne suis pas sûr de la maturité des solutions que j'ai trouvées.

+0

winp semble avoir gagné en popularité, et fait partie de Hudson (en fait, a été écrit pour cela). L'URL java.net ne résout plus, mais l'article original existe toujours à https://weblogs.java.net/blog/kohsuke/archive/2008/03/introducing_win.html (notez que certaines de ces informations sont daté, comme seulement 32bit). La nouvelle URL pour winp (avec des liens vers mvn et github) est: http://winp.kohsuke.org/ – toddkaufmann

+0

@toddkaufmann merci, mis à jour l'URL. –

0

Je ne suis pas sûr de ce que Process.destroy() fait sous les couvertures (envoie un signal ou similaire?). Ce que vous pouvez trouver fonctionne mieux est d'invoquer votre ssh/rsync dans un script shell, et que cela retourne un ID de processus sur stdout, puis lorsque vous voulez tuer le processus, effectuez un /bin/kill avec cet id de processus. Un peu brouillon, mais peut-être plus fiable.

Notez que vous pouvez /bin/kill avec SIGTERM, et SIGKILL si c'est particulièrement têtu.

+2

Process.destroy() appelle la fonction Windows TerminateProcess (http://msdn.microsoft.com/en-us/library/ms686714(VS .85) .aspx). –

Questions connexes