2010-11-16 25 views
24

No puedo entender cómo puedo enviar comandos a través del canal de shell JSch.Envío de comandos al servidor a través del canal de shell JSch

hago esto, pero no funciona:

JSch shell = new JSch(); 
String command = "cd home/s/src"; 
Session session = shell.getSession(username, host, port); 
MyUserInfo ui = new MyUserInfo(); 
ui.setPassword(password); 
session.setUserInfo(ui); 
session.connect(); 

channel = session.openChannel("shell"); 
fromServer = new BufferedReader(new InputStreamReader(channel.getInputStream())); 
toServer = channel.getOutputStream(); 
channel.connect(); 
toServer.write((command + "\r\n").getBytes()); 
toServer.flush(); 

y luego leí entrada de la siguiente manera:

StringBuilder builder = new StringBuilder(); 

int count = 0; 
String line = ""; 

while(line != null) { 
    line = fromServer.readLine(); 
    builder.append(line).append("\n"); 

    if (line.endsWith(".") || line.endsWith(">")){ 
     break; 
    } 
} 
String result = builder.toString(); 
ConsoleOut.println(result); 
+0

¿Cuál es el mensaje de error? ¿Hay un stacktrace? –

+0

No hay mensaje de error, simplemente no recibo ningún mensaje. El programa se detiene en line = fromServer.readLine(), witch significa que el mensaje no se ha enviado ... al menos, creo que sí ... – Nezzit

+0

Que esto ayude: http://www.jcraft.com/jsch/examples/ –

Respuesta

10

Si se cuelga al readLine(), lo que significa que su "tiempo" nunca se termina (es poco probable teniendo en cuenta su código) o readLine() es w Aiting para su fuente, es decir, IOstream bloquea la causa del hilo available()!=true.

No puedo solucionar el problema de tu código sin ver tu información de depuración. Pero como consejo, ¿has intentado PipedIntputStream? La idea es conectar la entrada de tu consola a "tu" salida para que puedas "escribirla". Para implementar esto, debe inicializar la entrada/salida.

InputStream in = new PipedInputStream(); 
PipedOutputStream pin = new PipedOutputStream((PipedInputStream) in); 
/**...*/ 
channel.setInputStream(in); 
channel.connect(); 
/** ...*/ 
pin.write(myScript.getBytes()); 

Lo mismo ocurre con su pregunta, cómo leer la salida de la consola.

PipedInputStream pout = new PipedInputStream((PipedOutputStream) out); 
/** 
* ... 
*/ 
BufferedReader consoleOutput = new BufferedReader(new InputStreamReader(pout)); 
consoleOutput.readLine(); 

Y de nuevo, si usted no está seguro de cuántas líneas para leer y por lo tanto quieren usar "mientras que", asegúrese de hacer algo en su interior, mientras que para evitar 1) ocupado en espera 2) que termina condición. Ejemplo:

while(!end) 
{ 
    consoleOutput.mark(32); 
    if (consoleOutput.read()==0x03) end = true;//End of Text 
    else 
    { 
    consoleOutput.reset(); 
    consoleOutput.readLine(); 
    end = false; 
    } 
} 
+0

No entiendo la última parte. ¿La posición '32' es arbitraria? ¿Es posible establecer una marca en la posición actual y restablecerla luego? – Kariem

+0

@Kariem 32 tiene 32 bytes como marcador de marca. Han pasado años, así que no recuerdo por qué utilicé 32 en lugar de 4. 4 debería ser lo suficientemente grande como para acomodar un 'read()', pero tal vez mi razonamiento fue más grande y no daña la lógica. – nilbot

-1

prueba este código:

  JSch jsch=new JSch(); 

     System.out.println("Getting session"); 
     Session session=jsch.getSession("root","10.0.0.0",22); 

      System.out.println("session is ::::"+session.getHost()); 
      // username and password will be given via UserInfo interface. 
      UserInfo ui = new MyUserInfo("[email protected]", null); 
      //UserInfo ui = new MyUserInfo(password, null); 
      session.setUserInfo(ui); 
      session.setPassword("[email protected]"); 
      Properties config = new java.util.Properties(); 
      config.put("StrictHostKeyChecking", "no"); 
      session.setConfig(config); 
      session.connect(40000); 


       Channel channel=session.openChannel("exec"); 
       ((ChannelExec)channel).setCommand("ls"); 

       channel.connect(); 
       channel.run(); 

       // get I/O streams for remote scp 
       OutputStream out=channel.getOutputStream(); 
       InputStream in=channel.getInputStream(); 


      String output=""; 
      while (channel.isClosed()!=true) { 

       try { 
       output+=streamToString(in); 

      } catch (Exception e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     } 

      System.out.println("Output is :::"+output); 
      channel.disconnect(); 
      session.disconnect(); 
    } 

    public static String streamToString(InputStream input)throws Exception 
    { String output = ""; while(input.available()>0) { output += ((char)(input.read())); } return output; } 



    public static OutputStream stringToStream(String charset) throws IOException{ 

     byte[] bytes = charset.getBytes(); 
     /*ByteArrayInputStream bais = new ByteArrayInputStream(bytes); 
     InputStreamReader isr = new InputStreamReader(bais);*/ 
     InputStream is = null; 
     OutputStream os = null; 
     try { 
      is = new ByteArrayInputStream(charset.getBytes("UTF-8")); 
     } catch (UnsupportedEncodingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     //byte[] buf = new byte[1024]; 
     int numRead; 

      while ((numRead = is.read(bytes)) >= 0) { 
       os.write(bytes, 0, numRead); 
      }   
     return os;  
+0

+1 merece la respuesta correcta. – Nishant

+3

La API dice que no se debe llamar a channel.run(): [aquí] (http://epaul.github.com/jsch-documentation/javadoc/com/jcraft/jsch/Channel.html#run%28%29) – Kai

16

Prueba esto:

JSch jsch = new JSch(); 

try 
{ 
    Session session = jsch.getSession("root", "192.168.0.1", 22); 
    java.util.Properties config = new java.util.Properties(); 
    config.put("StrictHostKeyChecking", "no"); 
    session.setConfig(config); 

    session.connect(); 

    String command = "lsof -i :80"; 
    Channel channel = session.openChannel("exec"); 
    ((ChannelExec) channel).setCommand(command); 
    channel.setInputStream(null); 
    ((ChannelExec) channel).setErrStream(System.err); 
    InputStream in = channel.getInputStream(); 

    channel.connect(); 

    byte[] tmp = new byte[1024]; 
    while (true) 
    { 
    while (in.available() > 0) 
    { 
     int i = in.read(tmp, 0, 1024); 
     if (i < 0) 
     break; 
     System.out.print(new String(tmp, 0, i)); 
    } 
    if (channel.isClosed()) 
    { 
     System.out.println("exit-status: " + channel.getExitStatus()); 
     break; 
    } 
    try 
    { 
     Thread.sleep(1000); 
    } 
    catch (Exception ee) 
    { 
    } 
    } 

    channel.disconnect(); 
    session.disconnect(); 
} 
catch (Exception e) 
{ 
    System.out.println(e.getMessage()); 
} 
+1

Acerca de la línea 'if (i <0) break;', después de asegurarse de que inputstream tiene datos disponibles, ¿es posible que al leer estos datos se obtenga un número negativo que indique la cantidad de datos leídos? ¿Por qué indicó que tiene datos disponibles en primer lugar? –

+0

¡útil para mí! – Daria

+0

Bueno ... pero este no es un canal de shell, es el canal de ejecución ... – nephewtom

1

Siguiendo era un código rápidamente por escrito para mi asignación. No es un programa bien hecho. Pero sirve para su propósito.

  1. Se conecta a través de SSH (usando JSCH) a un servidor (utilizando un archivo de clave privada - mykey.pem)
  2. Crea un script de shell (para montar un volumen y mkfs)
  3. Se ejecuta en el equipo remoto
  4. al mismo tiempo se puede ver la salida de su salida estándar

el código siguiente manera:

public class connectSSH { 

public void connect(String dnsName, String privKey) throws IOException { 
    JSch jSch = new JSch(); 

    try { 

        //Authenticate through Private Key File 
     jSch.addIdentity(privKey); 
        //Give the user and dnsName 
     Session session = jSch.getSession("root", dnsName, 22); 
        //Required if not a trusted host 
     java.util.Properties config = new java.util.Properties(); 
     config.put("StrictHostKeyChecking", "no"); 
     session.setConfig(config); 
     System.out.println("Connecting SSH to " + dnsName + " - Please wait for few minutes... "); 
     session.connect(); 
      //Open a shell 
     Channel channel=session.openChannel("shell"); 
     channel.setOutputStream(System.out); 
      //Create a Shell Script 
     File shellScript = createShellScript(); 
      //Convert the shell script to byte stream 
     FileInputStream fin = new FileInputStream(shellScript); 
     byte fileContent[] = new byte[(int)shellScript.length()]; 
     fin.read(fileContent); 
     InputStream in = new ByteArrayInputStream(fileContent); 
      //Set the shell script to the channel as input stream 
     channel.setInputStream(in); 
      //Connect and have fun! 
     channel.connect();   

    } catch (JSchException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

public File createShellScript() { 
    String filename = "shellscript.sh"; 
    File fstream = new File(filename); 

    try{ 
      // Create file 
     PrintStream out = new PrintStream(new FileOutputStream(fstream)); 
     out.println("#!/bin/bash"); 
     out.println("echo \"hi\" > /tmp/test.info"); 
     out.println("echo \"n\" > /tmp/fdisk.in"); 
     out.println("echo \"p\" >> /tmp/fdisk.in"); 
     out.println("echo \"1\" >> /tmp/fdisk.in"); 
     out.println("echo >> /tmp/fdisk.in"); 
     out.println("echo >> /tmp/fdisk.in"); 
     out.println("echo \"w\" >> /tmp/fdisk.in"); 

     out.println("/sbin/fdisk /dev/sdf < /tmp/fdisk.in"); 
     out.println("mkfs.ext3 /dev/sdf1"); 
     out.println("mkdir /usr/myebs"); 
     out.println("mount /dev/sdf1 /usr/myebs"); 
     out.println("partprobe /dev/sdf1"); 

     out.println("echo \"Success\""); 

     //Close the output stream 
     out.close(); 
    }catch (Exception e){//Catch exception if any 
     System.err.println("Error: " + e.getMessage()); 
    } 
    return fstream; 

} 

public static void main(String[] args) { 
    connectSSH ssh = new connectSSH(); 
    String privKey = "/Users/neo/Desktop/mykey.pem"; 
    try { 
     ssh.connect("yourexampleserver.com", privKey); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

} 
1

Con flujos de entrada y de salida por tuberías parece interesante:

JSch jsch = new JSch(); 
jsch.addIdentity("/home/audrius/.ssh/blablabla", "blablablabla"); 

String user = "audrius"; 
String host = "ultrastudio.org"; 

Session session = jsch.getSession(user, host, 439); 
session.setConfig("StrictHostKeyChecking", "no");   
session.connect(); 

Channel channel = session.openChannel("shell"); 

PipedInputStream pip = new PipedInputStream(40); 
channel.setInputStream(pip); 

PipedOutputStream pop = new PipedOutputStream(pip); 
PrintStream print = new PrintStream(pop);   
channel.setOutputStream(System.out); 

print.println("ls"); 
0

probar esto

Channel channel=session.openChannel("shell"); 
      OutputStream ops = channel.getOutputStream(); 
     PrintStream ps = new PrintStream(ops, true); 

     channel.connect(); 
     ps.println("mkdir folder"); 
     ps.println("dir"); 
//give commands to be executed inside println.and can have any no of commands sent. 
         ps.close(); 

     InputStream in=channel.getInputStream(); 
     byte[] bt=new byte[1024]; 


     while(true) 
     { 

     while(in.available()>0) 
     { 
     int i=in.read(bt, 0, 1024); 
     if(i<0) 
      break; 
      String str=new String(bt, 0, i); 
      //displays the output of the command executed. 
      System.out.print(str); 


     } 
     if(channel.isClosed()) 
     { 

      break; 
     } 
     Thread.sleep(1000); 
     channel.disconnect(); 
     session.disconnect(); 
     } 
2
private void executeRemoteCommandAsSudo(String sudoAs, String password, 
      String command, int delayInSeconds) 
{ 
    logger.info("executeRemoteCommandAsSudo started...."); 
    logger.info("sudoAs=" + sudoAs); 
    logger.info("command=" + command); 
    logger.info("delayInSeconds=" + delayInSeconds); 
    Session session = null; 
    Channel channel = null; 
    try { 
     session = getSession(); 
     channel = session.openChannel("exec"); 
     String sudoCommand = "sudo su - " + sudoAs; 
     ((ChannelExec) channel).setCommand(sudoCommand); 
     ((ChannelExec) channel).setPty(true); 
     channel.connect(); 
     InputStream inputStream = channel.getInputStream(); 
     OutputStream out = channel.getOutputStream(); 
     ((ChannelExec) channel).setErrStream(System.err); 
     out.write((password + "\n").getBytes()); 
     out.flush(); 
     Thread.sleep(1000); 
     out.write((command + "\n").getBytes()); 
     out.flush(); 
     Thread.sleep(1000 * delayInSeconds); 
     out.write(("logout" + "\n").getBytes()); 
     out.flush(); 
     Thread.sleep(1000); 
     logInfo(channel, inputStream); 
     out.write(("exit" + "\n").getBytes()); 
     out.flush(); 
     out.close(); 
     Thread.sleep(1000); 
    } catch (Exception ex) { 
     logger.error(ex.getMessage()); 
    } finally { 
     session.disconnect(); 
     channel.disconnect(); 
    } 
    logger.info("executeRemoteCommandAsSudo completed...."); 
} 
private void logInfo(Channel channel, InputStream in) 
{ 
    try { 
     byte[] tmp = new byte[1024]; 
     while (true) { 
      while (in.available() > 0) { 
       int i = in.read(tmp, 0, 1024); 
       if (i < 0) 
        break; 
       logger.info(new String(tmp, 0, i)); 
      } 
      if (channel.isClosed()) { 
       logger.info("exit-status: " + channel.getExitStatus()); 
       break; 
      } 
     } 
    } catch (Exception ex) { 
     logger.error(ex); 
    } 
} 

private Session getSession() throws JSchException 
{ 
    JSch jsch = new JSch(); 
    logger.info("ftpUser=" + ftpUser); 
    logger.info("ftpHost=" + ftpHost); 
    Session session = jsch.getSession(ftpUser, ftpHost, 22); 
    session.setPassword(ftpPassword); 
    java.util.Properties config = new java.util.Properties(); 
    config.put("StrictHostKeyChecking", "no"); 
    session.setConfig(config); 
    session.connect(); 
    return session; 
} 
0

Soy consciente de que este es un viejo hilo, pero he luchado con un problema similar en la actualidad. Esta es mi solución.

public class ChannelConsole { 

// ================================================ 
// static fields 
// ================================================ 

// ================================================ 
// instance fields 
// ================================================ 

private Session session; 

// ================================================ 
// constructors 
// ================================================ 

public ChannelConsole(Session session) { 
    this.session = session; 
} 

// ================================================ 
// getters and setters 
// ================================================ 

// ================================================ 
// public methods 
// ================================================ 

public String execute(String command) throws JSchException { 
    command = command.trim() + "\n"; 

    ChannelExec channel = (ChannelExec) this.session.openChannel("exec"); 
    channel.setCommand(command); 

    ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); 
    channel.setOutputStream(responseStream); 

    channel.connect(); 

    try { 
     awaitChannelClosure(channel); 
    } catch (InterruptedException e) { 
     // no one cares 
    } 

    String result = responseStream.toString(); 
    closeQuietly(responseStream); 
    return result; 

} 

// ================================================ 
// private methods 
// ================================================ 

private void awaitChannelClosure(ChannelExec channel) throws InterruptedException { 
    while (channel.isConnected()) { 
     Thread.sleep(100); 
    } 
} 

private static void closeQuietly(Closeable closeable) { 
    if (closeable == null) { 
     return; 
    } 

    try { 
     closeable.close(); 
    } catch (IOException ignored) { 
     ignored.printStackTrace(); 
    } 
} 

} 

El uso de esta clase sólo se puede hacer algo como: shell = new ChannelConsole(this.session); String result = shell.execute("quota -v; echo; echo \"Disk storage information:\"; df -hk")

Cuestiones relacionadas