MISE À JOUR : Cet article a été remplacé par mon article plus récent « Java exec avec ProcessBuilder et Process ». Alors que le code Java montré dans ce tutoriel fonctionne sur des cas simples de « Java exec », le nouvel article montre comment lire correctement les flux de sortie de votre commande système dans les threads Java, et aussi comment écrire sur l’entrée standard de votre commande, si nécessaire.

N’hésitez pas à lire cet article pour des informations de fond/de legs, mais je vous recommande fortement d’utiliser le code source que je partage dans mon article plus récent « Java exec », car il résout les problèmes d’entrée standard, de sortie et d’erreur que je n’ai pas gérés correctement dans le code ci-dessous.

Introduction

J’ai lu beaucoup de choses sur Java, mais l’une des choses que je vois rarement discutée est la façon dont vous devriez vous y prendre pour exécuter des commandes système externes. Bien sûr, vous ne lisez probablement pas beaucoup à ce sujet parce que cela nuit à la portabilité des applications Java. Par exemple, si vous écrivez une application Java sur un système Unix, vous pourriez être intéressé par l’exécution de la commande « ps -ef » et la lecture de la sortie de cette commande. Pour les systèmes Unix, c’est génial, mais malheureusement, ce même programme ne fonctionnera pas sur un système Windows, car la commande ps n’est pas disponible sur Windows.

Bien, nous allons oublier la portabilité pour cet article, et démontrer une méthode qui peut être utilisée pour exécuter des commandes système. Nous avons reçu beaucoup de demandes sur ce sujet, alors c’est parti.

Discussion (Runtime exec and Process)

L’exécution d’une commande système est relativement simple – une fois que vous l’avez vu faire la première fois. Elle implique l’utilisation de deux classes Java, la classe Runtime et la classe Process. En gros, vous utilisez la méthode exec de la classe Runtime pour exécuter la commande en tant que processus distinct. L’invocation de la méthode exec renvoie un objet Process pour gérer le sous-processus. Ensuite, vous utilisez les méthodes getInputStream() et getErrorStream() de l’objet Process pour lire la sortie normale de la commande, et la sortie d’erreur de la commande. Ce que vous faites avec la sortie de la commande exécutée dépend entièrement de vous et de l’application que vous créez.

(Note : Il existe également une méthode getOutputStream() que vous pouvez utiliser pour écrire au processus, mais nous ne couvrirons pas cette méthode dans cet article. Nous couvrirons cela et quelques autres fonctionnalités avancées dans un futur article.)

Un exemple d’exécution Java

Le code présenté dans le Listing 1 fournit un exemple fonctionnel de notre technique « Java exec » dans un fichier nommé JavaRunCommand.java.

import java.io.*;public class JavaRunCommand { public static void main(String args) { String s = null; try { // run the Unix "ps -ef" command // using the Runtime exec method: Process p = Runtime.getRuntime().exec("ps -ef"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); // read the output from the command System.out.println("Here is the standard output of the command:\n"); while ((s = stdInput.readLine()) != null) { System.out.println(s); } // read any errors from the attempted command System.out.println("Here is the standard error of the command (if any):\n"); while ((s = stdError.readLine()) != null) { System.out.println(s); } System.exit(0); } catch (IOException e) { System.out.println("exception happened - here's what I know: "); e.printStackTrace(); System.exit(-1); } }}

Listing 1 (ci-dessus) : Le fichier JavaRunCommand.java montre comment vous pouvez exécuter une commande système externe à partir d’un programme Java.

Comment fonctionne notre code Java exec

La première chose que vous faites est de spécifier la commande que vous voulez exécuter en fournissant cette commande à la classe Runtime. Comme vous ne pouvez pas créer votre propre instance de la classe Runtime, vous utilisez d’abord la méthode getRuntime pour accéder à l’environnement d’exécution actuel, puis vous invoquez la méthode exec du Runtime. Celle-ci renvoie un objet Process.

Tout ce que vous faites ensuite implique des méthodes de l’objet Process. Dans ce cas, comme nous exécutons la commande « ps -ef » sur un système Unix, nous avons juste besoin de lire la sortie de la commande. Lire l’erreur standard n’est probablement pas nécessaire dans ce cas, mais j’ai pensé que cela valait au moins la peine d’être montré, si ce n’est une bonne pratique de programmation.

Je convertis les flux d’entrée avec l’InputStreamReader et le BufferedReader afin de pouvoir utiliser la méthode readLine() de la classe BufferedReader. Parce que j’utilise ces classes, cette application ne compilera pas correctement avec un ancien compilateur JDK 1.0.x (ces classes n’étaient pas disponibles en 1.0.x).

Télécharger le code source de l’exemple « Java exec »

Je pourrais m’étendre longuement sur ce sujet, mais la meilleure chose que je puisse vous recommander est de télécharger le code source et de travailler avec pendant un certain temps. Essayez d’exécuter différentes commandes pour voir si vous pouvez les faire fonctionner correctement, et essayez d’exécuter une commande qui nécessite une entrée (ce sera un peu plus compliqué).