2011-04-29 4 views
11

J'essayais d'exécuter plusieurs commandes via le protocole SSH en utilisant la bibliothèque JSch. Mais je semble avoir bloqué et ne trouve aucune solution. La méthode setCommand() peut uniquement exécuter des commandes uniques par session. Mais je veux exécuter les commandes séquentiellement, tout comme l'application connectbot sur la plate-forme Android. Jusqu'à présent, mon code est:Plusieurs commandes via Shell Jsch

package com.example.ssh; 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.util.Properties; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 

import com.jcraft.jsch.Channel; 
import com.jcraft.jsch.JSch; 
import com.jcraft.jsch.JSchException; 
import com.jcraft.jsch.Session; 

public class ExampleSSH extends Activity { 
    /** Called when the activity is first created. */ 
    EditText command; 
    TextView result; 
    Session session; 
    ByteArrayOutputStream baos; 
    ByteArrayInputStream bais; 
    Channel channel; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     bais = new ByteArrayInputStream(new byte[1000]); 
     command = (EditText) findViewById(R.id.editText1); 
     result = (TextView) findViewById(R.id.terminal); 
    } 

    public void onSSH(View v){ 
     String username = "xxxyyyzzz"; 
     String password = "aaabbbccc"; 
     String host  = "192.168.1.1"; // sample ip address 
     if(command.getText().toString() != ""){ 
      JSch jsch = new JSch(); 
      try { 
       session = jsch.getSession(username, host, 22); 
       session.setPassword(password); 

       Properties properties = new Properties(); 
       properties.put("StrictHostKeyChecking", "no"); 
       session.setConfig(properties); 
       session.connect(30000); 

       channel = session.openChannel("shell"); 
       channel.setInputStream(bais); 
       channel.setOutputStream(baos); 
       channel.connect(); 

      } catch (JSchException e) { 
       // TODO Auto-generated catch block 
       Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); 
      } 
     } 
     else{ 
      Toast.makeText(this, "Command cannot be empty !", Toast.LENGTH_LONG).show(); 
     } 
    } 

    public void onCommand(View v){ 
     try { 
      bais.read(command.getText().toString().getBytes()); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     baos = new ByteArrayOutputStream(); 
     channel.setOutputStream(baos); 
     result.setText(baos.toString()); 

    } 
} 

Le code semble se connecter au serveur mais je pense qu'il ya un problème avec les tampons d'entrée et de sortie tableau parce qu'il n'y a pas de sortie du tout. Quelqu'un peut-il me guider s'il vous plaît comment gérer l'entrée et la sortie vers et depuis le serveur correctement pour obtenir la sortie désirée?

Répondre

12

La commande est une chaîne et peut être tout ce que le shell distant accepte. Essayez

cmd1 ; cmd2 ; cmd3 

pour exécuter plusieurs commandes en séquence. Ou

cmd1 && cmd2 && cmd3 

d'exécuter des commandes jusqu'à ce que l'une échoue.

Même cela pourrait fonctionner:

cmd1 
cmd2 
cmd3 

ou en Java:

channel.setCommand("cmd1\ncmd2\ncmd3"); 

Sidenote: Ne pas mettre les mots de passe et noms d'utilisateur dans le code. Placez-les dans un fichier de propriétés et utilisez une propriété système pour spécifier le nom du fichier de propriétés. De cette façon, vous pouvez conserver le fichier même en dehors du projet et vous assurer que les mots de passe/noms d'utilisateur ne fuient pas.

11

Si vous ne disposez pas de distinguer les entrées ou sorties des commandes individuelles, la réponse d'Aaron (donnant toutes les commandes dans une rangée, séparées par \n ou ;) est très bien.

Si vous devez les gérer séparément, ou si vous ne connaissez pas les commandes ultérieures avant que les précédentes ne soient terminées: Vous pouvez ouvrir plusieurs fois exec-Channels sur la même session (connexion), l'une après l'autre (après l'autre). avant était fermé). Chacun a sa propre commande. (Mais ils ne partagent environnement, donc une commande cd dans le premier n'a pas d'effet sur les derniers.)

Il vous suffit de prendre soin d'avoir l'objet Session autour, et ne pas créer un nouveau pour chaque commander.

Une autre option serait une shell channel, puis de passer les commandes individuelles au shell distant en entrée (c'est-à-dire via un flux). Mais alors vous devez prendre soin de ne pas mélanger l'entrée à une commande avec la commande suivante (c'est-à-dire si vous savez ce que font les commandes ou si vous avez un utilisateur interactif qui peut fournir à la fois la commande et la commande suivante, et sait lequel doit être utilisé quand.)

+0

des exemples de comment cela est-il fait? – Pixie

4

Configurez un objet SCPInfo pour contenir le nom d'utilisateur, le mot de passe, le port: 22 et ip.

List<String> commands = new ArrayList<String>(); 
    commands.add("touch test1.txt"); 
    commands.add("touch test2.txt"); 
    commands.add("touch test3.txt"); 
    runCommands(scpInfo, commands); 

public static void runCommands(SCPInfo scpInfo, List<String> commands){ 
    try { 
     JSch jsch = new JSch(); 
     Session session = jsch.getSession(scpInfo.getUsername(), scpInfo.getIP(), scpInfo.getPort()); 
     session.setPassword(scpInfo.getPassword()); 
     setUpHostKey(session); 
     session.connect(); 

     Channel channel=session.openChannel("shell");//only shell 
     channel.setOutputStream(System.out); 
     PrintStream shellStream = new PrintStream(channel.getOutputStream()); // printStream for convenience 
     channel.connect(); 
     for(String command: commands) { 
      shellStream.println(command); 
      shellStream.flush(); 
     } 

     Thread.sleep(5000); 

     channel.disconnect(); 
     session.disconnect(); 
    } catch (Exception e) { 
     System.err.println("ERROR: Connecting via shell to "+scpInfo.getIP()); 
     e.printStackTrace(); 
    } 
} 

private static void setUpHostKey(Session session) { 
    // Note: There are two options to connect 
    // 1: Set StrictHostKeyChecking to no 
    // Create a Properties Object 
    // Set StrictHostKeyChecking to no 
    // session.setConfig(config); 
    // 2: Use the KnownHosts File 
    // Manually ssh into the appropriate machines via unix 
    // Go into the .ssh\known_hosts file and grab the entries for the hosts 
    // Add the entries to a known_hosts file 
    // jsch.setKnownHosts(khfile); 
    java.util.Properties config = new java.util.Properties(); 
    config.put("StrictHostKeyChecking", "no"); 
    session.setConfig(config); 
} 
+0

Cela ne fonctionnera que si les commandes ne prennent aucune entrée, sinon les commandes suivantes seront interprétées comme entrées du premier. –

+1

génial! Exactement ce que je cherchais. –

Questions connexes