Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();
java
runtime.exec
user590444
la source
la source
Réponses:
Il y a de nombreuses raisons qui
waitFor()
ne reviennent pas.Mais cela se résume généralement au fait que la commande exécutée ne se ferme pas.
Ceci, encore une fois, peut avoir de nombreuses raisons.
Une raison courante est que le processus produit une sortie et que vous ne lisez pas les flux appropriés. Cela signifie que le processus est bloqué dès que la mémoire tampon est pleine et attend que votre processus continue sa lecture. Votre processus attend à son tour que l'autre processus se termine (ce qu'il ne fera pas car il attend votre processus, ...). C'est une situation classique de blocage.
Vous devez continuellement lire le flux d'entrée des processus pour vous assurer qu'il ne se bloque pas.
Il y a un bel article qui explique tous les pièges
Runtime.exec()
et montre des moyens de les contourner appelé "Quand Runtime.exec () ne le fera pas" (oui, l'article date de 2000, mais le contenu s'applique toujours!)la source
waitFor()
ne revient pas.Il semble que vous ne lisez pas la sortie avant d'attendre qu'elle se termine. Cela ne fonctionne que si la sortie ne remplit pas le tampon. Si c'est le cas, il attendra que vous lisiez la sortie, catch-22.
Peut-être avez-vous des erreurs que vous ne lisez pas. Cela permettrait à l'application de s'arrêter et d'attendre pour attendre indéfiniment. Un moyen simple de contourner ce problème consiste à rediriger les erreurs vers la sortie normale.
la source
pb.redirectError(new File("/dev/null"));
redirectError
n'est disponible que depuis Java 1.7Également de Java doc:
Essaye ça:
la source
DefaultExecutor executor = new DefaultExecutor(); PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdoutOS, stderrOS); executor.setStreamHandler(pumpStreamHandler); executor.execute(cmdLine);
:, où stoutOS et stderrOS sontBufferedOutputStream
s que j'ai créés pour écrire dans les fichiers appropriés.process.close()
. Mais lorsque j'ouvre le flux d'entrée comme suggéré ci-dessus et que je ferme immédiatement, le problème disparaît. Donc, dans mon cas, Spring attendait le signal de fermeture du flux. Même si j'utilise Java 8 fermable automatiquement.Je voudrais ajouter quelque chose aux réponses précédentes, mais comme je n'ai pas le représentant à commenter, je vais simplement ajouter une réponse. Ceci est destiné aux utilisateurs d'Android qui programment en Java.
Selon le message de RollingBoy, ce code a presque fonctionné pour moi:
Dans mon cas, waitFor () ne se libérait pas car j'exécutais une instruction sans retour ("ip adddr flush eth0"). Un moyen simple de résoudre ce problème consiste simplement à vous assurer de toujours renvoyer quelque chose dans votre relevé. Pour moi, cela signifiait exécuter ce qui suit: "ip adddr flush eth0 && echo done". Vous pouvez lire le tampon toute la journée, mais si rien n'est jamais retourné, votre thread ne relâchera jamais son attente.
J'espère que cela aide quelqu'un!
la source
process.waitFor()
qui se bloque, c'est lereader.readLine()
qui se bloque si vous n'avez pas de sortie. J'ai essayé d'utiliser lewaitFor(long,TimeUnit)
délai d'expiration en cas de problème et j'ai découvert que c'était la lecture du blocage. Ce qui rend la version expirée nécessite un autre thread pour faire la lecture ...Il existe plusieurs possibilités:
stdout
.stderr
.stdin
.la source
Comme d'autres l'ont mentionné, vous devez consommer stderr et stdout .
Par rapport aux autres réponses, depuis Java 1.7, c'est encore plus facile. Vous n'avez plus besoin de créer vous-même des threads pour lire stderr et stdout .
Utilisez simplement le
ProcessBuilder
et utilisez les méthodesredirectOutput
en combinaison avecredirectError
ouredirectErrorStream
.la source
Pour la même raison, vous pouvez également utiliser
inheritIO()
pour mapper la console Java avec une console d'application externe comme:la source
Vous devriez essayer de consommer la sortie et l'erreur en même temps
la source
Je pense avoir observé un problème similaire: certains processus ont démarré, semblaient fonctionner correctement mais ne se sont jamais terminés. La fonction waitFor () attendait pour toujours, sauf si j'ai tué le processus dans le Gestionnaire des tâches.
Cependant, tout fonctionnait bien dans les cas où la longueur de la ligne de commande était de 127 caractères ou moins. Si les noms de fichiers longs sont inévitables, vous pouvez utiliser des variables d'environnement, ce qui peut vous permettre de garder la chaîne de ligne de commande courte. Vous pouvez générer un fichier de commandes (à l'aide de FileWriter) dans lequel vous définissez vos variables d'environnement avant d'appeler le programme que vous souhaitez réellement exécuter. Le contenu d'un tel lot pourrait ressembler à:
La dernière étape consiste à exécuter ce fichier de commandes à l'aide de Runtime.
la source
Voici une méthode qui fonctionne pour moi. REMARQUE: il existe du code dans cette méthode qui peut ne pas s'appliquer à vous, essayez donc de l'ignorer. Par exemple "logStandardOut (...), git-bash, etc".
}
la source
La lecture asynchrone du flux combinée à éviter Attendre avec un délai d'expiration résoudra le problème.
Vous pouvez trouver une page expliquant cela ici http://simplebasics.net/.net/process-waitforexit-with-a-timeout-will-not-be-able-to-collect-the-output-message/
la source