2010-11-16 11 views
24

Non riesco a capire come posso inviare comandi tramite il canale di shell JSch.Invio di comandi al server tramite il canale di shell JSch

faccio questo, ma non funziona:

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(); 

e poi ho letto di input in questo modo:

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

Qual è il messaggio di errore? C'è uno stacktrace? –

+0

Non c'è nessun messaggio di errore, non riesco a recuperare alcun messaggio. Il programma si arresta su line = fromServer.readLine(), witch indica che il messaggio non è stato inviato ... almeno, penso di sì ... – Nezzit

+0

Questo può aiutare: http://www.jcraft.com/jsch/examples/ –

risposta

10

Se si blocca a readLine() che significa che il tuo "while" non finisce mai (potrebbe essere improbabile considerando il tuo codice), oppure, readLine() è w attendendo la sua fonte, ovvero i blocchi IOstream, la causa del thread è available()!=true.

Non riesco a risolvere il problema senza visualizzare le informazioni di debug. Ma come consiglio, hai provato PipedIntputStream? L'idea è di reindirizzare l'input della tua console all'output "tuo" in modo da poterlo "scrivere". Per implementare questo, è necessario inizializzare l'ingresso/l'uscita.

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

Lo stesso vale per la tua domanda, come leggere l'output della console.

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

E ancora, se non siete sicuri di come molte linee di leggere e quindi vogliono usare "mentre", assicuratevi di fare qualcosa dentro, mentre per prevenire 1) occupato-attendere 2) terminando-condizione. Esempio:

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

Non capisco l'ultima parte. La posizione '32' è arbitraria? È possibile impostare un segno nella posizione corrente e ripristinarlo successivamente? – Kariem

+0

@Kariem 32 è 32 byte come buffer di mark. Sono passati anni, quindi non ricordo perché ho usato 32 invece di 4. 4 dovrebbe essere abbastanza grande da contenere un 'read()' ma forse il mio ragionamento è stato impostato più grande non danneggia la logica. – nilbot

-1

provare questo codice:

  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 merita comunque la risposta corretta. – Nishant

+3

L'API dice che channel.run() non dovrebbe essere chiamato: [qui] (http://epaul.github.com/jsch-documentation/javadoc/com/jcraft/jsch/Channel.html#run%28%29) – Kai

16

Prova questa:

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

Informazioni sulla riga 'if (i <0) break;', dopo essersi assicurati che l'inputstream abbia dati disponibili, è possibile che la lettura di questi dati restituisca un numero negativo che indica la quantità di dati letti?! Perché ha indicato che ha dati disponibili in primo luogo ?! –

+0

utile per me! – Daria

+0

Bene ... ma questo non è un canale shell, è un canale exec ... – nephewtom

1

seguente era un codice rapidamente scritto per il mio incarico. Non è un programma ben fatto. Ma serve al suo scopo.

  1. collega tramite SSH (usando JSch) a un server (utilizzando un file di chiave privata - mykey.pem)
  2. crea uno script di shell (per montare un volume e mkfs)
  3. Viene eseguito sulla macchina remota
  4. Per tutto il tempo si può vedere l'uscita sul stdout

il codice segue:

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 i flussi di input e output pipe sembra interessante:

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

provare questo

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

Mi rendo conto che questo è un vecchio thread, ma ho lottato con un problema simile oggi. Questa è la mia soluzione.

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(); 
    } 
} 

} 

Utilizzando questa classe si può semplicemente fare qualcosa di simile: shell = new ChannelConsole(this.session); String result = shell.execute("quota -v; echo; echo \"Disk storage information:\"; df -hk")

Problemi correlati