Java 通过JSch外壳通道向服务器发送命令

Java 通过JSch外壳通道向服务器发送命令,java,ssh,jsch,Java,Ssh,Jsch,我不知道如何通过JSCHshell通道发送命令 我这样做了,但不起作用: 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); s

我不知道如何通过JSCHshell通道发送命令

我这样做了,但不起作用:

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();
然后我像这样读输入:

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);
请尝试以下代码:

         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("Lab@123", null);
          //UserInfo ui = new MyUserInfo(password, null);
          session.setUserInfo(ui);
          session.setPassword("Lab@123");
          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;      

如果它挂起在
readLine()
上,则表示您的“while”永远不会结束(考虑到您的代码可能不太可能),或者,
readLine()
正在等待它的源代码,即
IOstream
阻塞线程,因为
可用()=正确

我无法在不查看调试信息的情况下对代码进行故障排除。但是作为建议,您是否尝试过
PipedIntputStream
?其思想是将控制台输入通过管道传输到“您的”输出,以便您可以“编写”它。要实现这一点,您需要初始化输入/输出

InputStream in = new PipedInputStream();
PipedOutputStream pin = new PipedOutputStream((PipedInputStream) in);
/**...*/
channel.setInputStream(in);
channel.connect();
/** ...*/
pin.write(myScript.getBytes());
您的问题也是如此,如何读取控制台输出

PipedInputStream pout = new PipedInputStream((PipedOutputStream) out);
/**
* ...
*/
BufferedReader consoleOutput = new BufferedReader(new InputStreamReader(pout));
consoleOutput.readLine();
再说一次,如果你不确定要读多少行,因此想使用“while”,请确保在while中做一些事情,以防止1)忙着等待2)结束条件。例如:

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

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());
}
JSch-JSch=new-JSch();
尝试
{
Session Session=jsch.getSession(“root”,“192.168.0.1”,22);
java.util.Properties config=new java.util.Properties();
配置放置(“检查”、“否”);
session.setConfig(config);
session.connect();
String命令=“lsof-i:80”;
Channel=session.openChannel(“exec”);
((ChannelExec)channel).setCommand(command);
channel.setInputStream(空);
((ChannelExec)channel.setErrStream(System.err);
InputStream in=channel.getInputStream();
channel.connect();
字节[]tmp=新字节[1024];
while(true)
{
while(in.available()>0)
{
inti=in.read(tmp,0,1024);
if(i<0)
打破
系统输出打印(新字符串(tmp,0,i));
}
if(channel.isClosed())
{
System.out.println(“退出状态:+channel.getExitStatus());
打破
}
尝试
{
睡眠(1000);
}
捕获(异常ee)
{
}
}
通道断开();
session.disconnect();
}
捕获(例外e)
{
System.out.println(e.getMessage());
}

以下是我的作业的快速编写代码。不是一个很好的程序。 但这符合它的目的

  • 通过SSH(使用Jsch)连接到服务器(使用私钥文件-mykey.pem)
  • 创建shell脚本(装载卷和mkfs)
  • 在远程计算机上运行
  • 一直以来,您都可以在标准输出上看到输出
  • 守则如下:

    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();
        }
    
    }
    
    }
    
    公共类connectSSH{
    public void connect(字符串dnsName,字符串privKey)引发IOException{
    JSch JSch=新的JSch();
    试一试{
    //通过私钥文件进行身份验证
    jSch.额外性(私钥);
    //给用户和dnsName
    Session Session=jSch.getSession(“根”,dnsName,22);
    //如果不是受信任的主机,则为必需
    java.util.Properties config=new java.util.Properties();
    配置放置(“检查”、“否”);
    session.setConfig(config);
    System.out.println(“将SSH连接到”+dnsName+“-请稍等几分钟…”);
    session.connect();
    //开壳
    Channel=session.openChannel(“shell”);
    channel.setOutputStream(系统输出);
    //创建一个Shell脚本
    文件shellScript=createShellScript();
    //将shell脚本转换为字节流
    FileInputStream fin=新的FileInputStream(shellScript);
    byte fileContent[]=新字节[(int)shellScript.length()];
    fin.read(文件内容);
    InputStream in=新的ByteArrayInputStream(文件内容);
    //将shell脚本设置为作为输入流的通道
    通道设置输入流(in);
    //连接并享受乐趣!
    channel.connect();
    }捕获(JSCHEException e){
    //TODO自动生成的捕捉块
    e、 printStackTrace();
    }
    }
    公共文件createShellScript(){
    字符串filename=“shellscript.sh”;
    File fstream=新文件(文件名);
    试一试{
    //创建文件
    PrintStream out=新的PrintStream(新文件输出流(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
    使用管道输入和输出流似乎很有趣:

    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");
    
    试试这个

    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();   
             }
    
    Channel=session.openChannel(“shell”);
    OutputStream ops=channel.getOutputStream();
    PrintStream ps=新的PrintStream(ops,true);
    channel.connect();
    ps.println(“mkdir文件夹”);
    ps.println(“dir”);
    //给出要在println内执行的命令,并且可以不发送任何命令。
    ps.close();
    InputStream in=channel.getInputStream();
    字节[]bt=新字节[1024];
    while(true)
    {
    而
    
    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;
    }
    
    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();
        }
    }
    
    }
    
    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);