開發與維運

java远程连接linux

最近在公司项目中,需用java远程连接linux服务器。最终选定了用jsch的方式。但在实现的过程中遇到两个问题。
①通过jsch的exec通道时,执行su命令会异常开始,原因是因为执行su命令后返回的结果标准化输出后为空,所以异常卡死;最后放弃此种方式改用shell通道
②使用jsch的shell通道时,如何获取到返回结果。通过readline的方式读取时执行su依旧会进入死循环,最后决定通过读取字节码的方式来获取返回结果,通过字节码的方式读取时又遇到终端显示字体颜色的乱码问题,通过设置伪终端的方式解决。
一下为解决的代码:
首先创建会话:
public static Session createSession(String OSIP, String OSUserName, String OSPassword){




    
    Session session = null;
    JSch jsch = new JSch();    
    try {
         // 通过jsch创建一个会话
         session = jsch.getSession(OSUserName, OSIP, port);
         // 设置会话自动传输密码
         session.setPassword(OSPassword);
         // 创建Properties类
         Properties config = new Properties();
         // 设置第一次登录不验证密码
         config.put("StrictHostKeyChecking", "no");
         // 设置公钥和私钥
         config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
         // 导入会话设置
         session.setConfig(config);
         // 设置会话超时时间
         session.setTimeout(timeOut);
         Log.printLog("ssh连接" + OSIP);
         // 连接上目标IP的会话
         session.connect();
         //代码调试,信息打印
         //System.out.println("username"+session.getUserName()+session.isConnected());
    } catch (JSchException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return session;
    
}

建议交互式shell通道:

public static ChannelShell createChannelShell(Session session) {
    ChannelShell channelShell = null;
    try {
        Channel channel = session.openChannel("shell");
        channelShell = (ChannelShell) channel;
        //解决终端高亮显示时颜色乱码问题
        channelShell.setPtyType("dump");
        channelShell.setPty(true);
        channelShell.connect();
        Log.printLog("与" + session.getHost() + "的SHELL通道建立成功");
    } catch (JSchException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return channelShell;
    
}

执行命令:

public static String execShellCmd(ChannelShell channelShell, String command, int sleepTime){

    StringBuffer sBuffer = new StringBuffer();
    int beat = 0;
    String result = "";
    String endResult = "";
    try {
        // 远端界面返回
        InputStream in = channelShell.getInputStream();
        // 本地内容推送到远端
        OutputStream out = channelShell.getOutputStream();
        // 要执行命令后加换行符才可以执行
        String execCommand = command + changeLine;
        Log.printLog("要执行的命令:" + command);
        // 写入执行命令
        out.write(execCommand.getBytes());
        // 清空缓存区,开始执行
        out.flush();
        Thread.sleep(sleepTime);             
        while (true) {
            if (beat > 3) {
                break;
            }
            if (in.available() >0 ) {      
                //InputStream按位读取,并保存在stringbuffer中
                   byte[] bs =new byte[in.available()];
                   in.read(bs);
                   sBuffer.append(new String(bs));
                   beat ++;
               }else {                   
                   if (sBuffer.length() >0) {
                    beat++;
                }
               }
        }
        // 将stringbuff读取的InputStream数据,转换成特定编码格式的字符串,一般为UTF-8格式
        result = new String(sBuffer.toString().getBytes(charsetName));
        
        // 将返回结果,按行截取并放进数组里面
        String[] strings = result.split(changeLine);
        
        // 通过遍历,筛选无意义的字符
        for (int i = 1; i < strings.length; i++) {
            if (!strings[i].contains("#") && !strings[i].contains(command) &&
                !strings[i].contains("$") && !strings[i].contains(">")) {
                //获取筛选后的字符
                endResult = endResult+strings[i] +changeLine;
            }
        }
    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }
    Log.printLog("命令执行完,返回的结果为:" + endResult);
    return endResult;    
}

其实在结果返回的处理这部分。代码逻辑有点混乱。但是能用。感觉处理的不是很好。也请各位帮忙能优化下。

Leave a Reply

Your email address will not be published. Required fields are marked *