Comment exécuter une commande Shell en Java

1. Vue d'ensemble

Avec ce didacticiel, nous illustrerons les deux façons d' exécuter une commande shell à partir du code Java .

La première consiste à utiliser la classe Runtime et à appeler sa méthode exec .

Le deuxième moyen, plus personnalisable, sera de créer et d'utiliser une instance ProcessBuilder .

2. Dépendance du système d'exploitation

Avant de créer un nouveau processus exécutant notre commande shell, nous devons d'abord déterminer le système d'exploitation sur lequel s'exécute notre JVM .

En effet, sous Windows , nous devons exécuter notre commande en tant qu'argument du shell cmd.exe et sur tous les autres systèmes d'exploitation, nous pouvons émettre un shell standard, appelé sh:

boolean isWindows = System.getProperty("os.name") .toLowerCase().startsWith("windows");

3. Entrée et sortie

en outrenous avons besoin d'un moyen de nous connecter aux flux d'entrée et de sortie de notre processus.

Au moins la sortie doit être consommée - sinon notre processus ne retourne pas avec succès, à la place il se bloquera.

Implémentons une classe couramment utilisée appelée StreamGobbler qui consomme un InputStream :

private static class StreamGobbler implements Runnable { private InputStream inputStream; private Consumer consumer; public StreamGobbler(InputStream inputStream, Consumer consumer) { this.inputStream = inputStream; this.consumer = consumer; } @Override public void run() { new BufferedReader(new InputStreamReader(inputStream)).lines() .forEach(consumer); } }

REMARQUE: cette classe implémente l' interface Runnable , ce qui signifie qu'elle peut être exécutée par n'importe quel exécuteur .

4. Runtime.exec ()

Un appel de méthode à Runtime.exec () est un moyen simple, pas encore personnalisable, de générer un nouveau sous-processus.

Dans l'exemple suivant, nous demanderons une liste de répertoires d'un répertoire personnel d'utilisateurs et l'imprimerons sur la console:

String homeDirectory = System.getProperty("user.home"); Process process; if (isWindows) { process = Runtime.getRuntime() .exec(String.format("cmd.exe /c dir %s", homeDirectory)); } else { process = Runtime.getRuntime() .exec(String.format("sh -c ls %s", homeDirectory)); } StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println); Executors.newSingleThreadExecutor().submit(streamGobbler); int exitCode = process.waitFor(); assert exitCode == 0;

5. ProcessBuilder

Pour la deuxième implémentation de notre problème informatique, nous utiliserons un ProcessBuilder . Ceci est préférable à l' approche Runtime car nous pouvons personnaliser certains détails.

Par exemple, nous pouvons:

  • changez le répertoire de travail que notre commande shell exécute en utilisant builder.directory ()
  • configurer une carte clé-valeur personnalisée comme environnement à l'aide de builder.environment ()
  • rediriger les flux d'entrée et de sortie vers des remplacements personnalisés
  • héritez des deux dans les flux du processus JVM actuel à l' aide de builder.inheritIO ()
ProcessBuilder builder = new ProcessBuilder(); if (isWindows) { builder.command("cmd.exe", "/c", "dir"); } else { builder.command("sh", "-c", "ls"); } builder.directory(new File(System.getProperty("user.home"))); Process process = builder.start(); StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println); Executors.newSingleThreadExecutor().submit(streamGobbler); int exitCode = process.waitFor(); assert exitCode == 0;

6. Conclusion

Comme nous l'avons vu dans ce tutoriel rapide, nous pouvons exécuter une commande shell en Java de deux manières distinctes.

En règle générale, si vous prévoyez de personnaliser l'exécution du processus généré, par exemple pour changer son répertoire de travail, vous devriez envisager d'utiliser un ProcessBuilder .

Comme toujours, vous trouverez les sources sur GitHub .