2009-09-11 8 views
80

J'essaie d'exécuter certaines commandes Linux depuis Java en utilisant la redirection (> &) et les pipes (|). Comment Java peut-il invoquer les commandes csh ou bash?Vous voulez appeler une commande shell Linux à partir de Java

J'ai essayé d'utiliser:

Process p = Runtime.getRuntime().exec("shell command"); 

Mais ce n'est pas compatible avec les tuyaux ou les redirections.

+2

'cat' et' csh' n'ont rien à voir l'un avec l'autre. – Bombe

+4

Je peux comprendre la question pour d'autres commandes, mais pour chat: pourquoi diable ne pas simplement lu dans le fichier? – Atmocreations

+7

Tout le monde se trompe la première fois - exec() de Java n'utilise pas le shell du système sous-jacent pour exécuter la commande (comme l'indique kts). La redirection et la tuyauterie sont des caractéristiques d'un vrai shell et ne sont pas disponibles depuis exec() de Java. – SteveD

Répondre

76

exec n'exécute pas une commande dans votre shell

essayer

Process p = Runtime.getRuntime().exec(new String[]{"csh","-c","cat /home/narek/pk.txt"}); 

à la place.

EDIT :: Je n'ai pas csh sur mon système, donc j'ai utilisé bash à la place. Ce qui suit a fonctionné pour moi

Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","ls /home/XXX"}); 
+0

ne fonctionne pas, désolé – Narek

+0

@Narek. Désolé pour ça. Je l'ai corrigé en supprimant les \\ 's Apparemment, ils ne sont pas nécessaires, je n'ai pas csh sur mon système, mais ça fonctionne avec bash – KitsuneYMG

+3

Comme d'autres l'ont mentionné, ceci devrait être indépendant que vous ayez csh ou bash, n'est pas cela? – Narek

26

Utilisez ProcessBuilder pour séparer les commandes et les arguments au lieu des espaces. Cela devrait fonctionner indépendamment du shell utilisé:

import java.io.BufferedReader; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.ArrayList; 
import java.util.List; 

public class Test { 

    public static void main(final String[] args) throws IOException, InterruptedException { 
     //Build command 
     List<String> commands = new ArrayList<String>(); 
     commands.add("/bin/cat"); 
     //Add arguments 
     commands.add("/home/narek/pk.txt"); 
     System.out.println(commands); 

     //Run macro on target 
     ProcessBuilder pb = new ProcessBuilder(commands); 
     pb.directory(new File("/home/narek")); 
     pb.redirectErrorStream(true); 
     Process process = pb.start(); 

     //Read output 
     StringBuilder out = new StringBuilder(); 
     BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream())); 
     String line = null, previous = null; 
     while ((line = br.readLine()) != null) 
      if (!line.equals(previous)) { 
       previous = line; 
       out.append(line).append('\n'); 
       System.out.println(line); 
      } 

     //Check result 
     if (process.waitFor() == 0) { 
      System.out.println("Success!"); 
      System.exit(0); 
     } 

     //Abnormal termination: Log command parameters and output and throw ExecutionException 
     System.err.println(commands); 
     System.err.println(out.toString()); 
     System.exit(1); 
    } 
} 
+0

Même après java.util. *; est correctement importé je ne peux pas obtenir l'exemple ci-dessus pour courir. – nottinhill

+0

Qu'est-ce qui ne fonctionne pas pour vous? – Tim

+0

@Stephan J'ai mis à jour l'exemple de code ci-dessus pour supprimer les instructions de journalisation et les variables qui ont été déclarées en dehors du code collé, et il devrait maintenant compiler & exécuter. N'hésitez pas à essayer et laissez-moi savoir comment cela fonctionne. – Tim

10

bâtiment sur @ exemple Tim pour faire une méthode autonome: (. L'exemple de test est un command that lists all files in a directory and its subdirectories, recursively, in chronological order)

import java.io.BufferedReader; 
import java.io.File; 
import java.io.InputStreamReader; 
import java.util.ArrayList; 

public class Shell { 

    /** Returns null if it failed for some reason. 
    */ 
    public static ArrayList<String> command(final String cmdline, 
    final String directory) { 
     try { 
      Process process = 
       new ProcessBuilder(new String[] {"bash", "-c", cmdline}) 
        .redirectErrorStream(true) 
        .directory(new File(directory)) 
        .start(); 

      ArrayList<String> output = new ArrayList<String>(); 
      BufferedReader br = new BufferedReader(
       new InputStreamReader(process.getInputStream())); 
      String line = null; 
      while ((line = br.readLine()) != null) 
       output.add(line); 

      //There should really be a timeout here. 
      if (0 != process.waitFor()) 
       return null; 

      return output; 

     } catch (Exception e) { 
      //Warning: doing this is no good in high quality applications. 
      //Instead, present appropriate error messages to the user. 
      //But it's perfectly fine for prototyping. 

      return null; 
     } 
    } 

    public static void main(String[] args) { 
     test("which bash"); 

     test("find . -type f -printf '%[email protected]\\\\t%p\\\\n' " 
      + "| sort -n | cut -f 2- | " 
      + "sed -e 's/ /\\\\\\\\ /g' | xargs ls -halt"); 

    } 

    static void test(String cmdline) { 
     ArrayList<String> output = command(cmdline, "."); 
     if (null == output) 
      System.out.println("\n\n\t\tCOMMAND FAILED: " + cmdline); 
     else 
      for (String line : output) 
       System.out.println(line); 

    } 
} 

Par Si quelqu'un peut me dire pourquoi j'ai besoin de quatre et huit barres obliques inverses, au lieu de deux et quatre, je peux apprendre quelque chose. Il y a un autre niveau de non-évitement qui se produit que ce que je compte. Edit: J'ai essayé ce même code sous Linux, et il s'avère que j'ai besoin de la moitié moins de backslashes dans la commande de test! (C'est-à-dire: le nombre attendu de deux et quatre.) Maintenant, ce n'est plus juste bizarre, c'est un problème de portabilité.

+0

Vous devriez poser votre question en tant que nouvelle question sur StackOverflow, et non dans votre réponse. – vog

Questions connexes