web-dev-qa-db-fra.com

Envoi de commandes au serveur via le canal JSch Shell

Je ne peux pas comprendre comment envoyer des commandes via le canal JSch Shell.

Je fais ça, mais ça ne marche pas:

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

puis je lis une entrée comme celle-ci:

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);
25
Nezzit

S'il se bloque à readLine() cela signifie que votre "while" ne se termine jamais (peut être peu probable compte tenu de votre code), ou, readLine() attend sa source, à savoir le IOstream bloque la cause du thread available()!=true.

Je ne peux pas tout à fait dépanner votre code sans voir vos informations de débogage. Mais comme conseil, avez-vous essayé PipedIntputStream? L'idée est de diriger votre entrée de console vers "votre" sortie afin de pouvoir "l'écrire". Pour implémenter cela, vous devez initialiser l'entrée/sortie.

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

Il en va de même pour votre question, comment lire la sortie de la console.

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

Et encore une fois, si vous n'êtes pas sûr du nombre de lignes à lire et que vous souhaitez donc utiliser "while", assurez-vous de faire quelque chose à l'intérieur while pour éviter 1) une attente occupée 2) une condition de fin. Exemple:

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

Essaye ça:

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());
}
18
Michael Cheremuhin
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;
}
2
user1345691

Voici un code écrit rapidement pour ma mission. Pas un programme bien fait. Mais sert son but.

  1. Se connecte via SSH (en utilisant Jsch) à un serveur (en utilisant un fichier de clé privée - mykey.pem)
  2. Crée un script Shell (pour monter un volume et mkfs)
  3. Fonctionne sur la machine distante
  4. Pendant tout ce temps, vous pouvez voir la sortie sur votre sortie standard

Le code suit:

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

}

}
2
neosab

Je me rends compte que c'est un vieux fil, mais j'ai lutté avec un problème similaire aujourd'hui. C'est ma solution.

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

}

En utilisant cette classe, vous pouvez simplement faire quelque chose comme: Shell = new ChannelConsole(this.session); String result = Shell.execute("quota -v; echo; echo \"Disk storage information:\"; df -hk")

1
Apokralipsa

Avec des flux d'entrée et de sortie canalisés semble intéressant:

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");
1
audriusa

Usage:

String remoteCommandOutput = exec("ssh://user:pass@Host/work/dir/path", "ls -t | head -n1");
String remoteShellOutput = Shell("ssh://user:pass@Host/work/dir/path", "ls")
Shell("ssh://user:pass@Host/work/dir/path", "ls", System.out)
Shell("ssh://user:pass@Host", System.in, System.out);

Mise en œuvre

0

essaye ça

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