java远程连接linux

简介: 主要解决执行su命令时异常卡住

最近在公司项目中,需用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;    
}

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

相关文章
|
3月前
|
Web App开发 搜索推荐 Unix
Linux系统之MobaXterm远程连接centos的GNOME桌面环境
【10月更文挑战第21天】Linux系统之MobaXterm远程连接centos的GNOME桌面环境
787 4
Linux系统之MobaXterm远程连接centos的GNOME桌面环境
|
2月前
|
分布式计算 Java Hadoop
linux中HADOOP_HOME和JAVA_HOME删除后依然指向旧目录
通过以上步骤,可以有效地解决 `HADOOP_HOME`和 `JAVA_HOME`删除后依然指向旧目录的问题。确保在所有相关的配置文件中正确设置和删除环境变量,并刷新当前会话,使更改生效。通过这些措施,能够确保系统环境变量的正确性和一致性。
38 1
|
3月前
|
算法 Java Linux
java制作海报七:java Graphics2D 合成图片 在 linux下中文不显示,echarts图上的中文也不显示问题
这篇文章讨论了在Linux环境下使用Java Graphics2D合成图片时遇到的中文显示问题,并提供了解决方案,包括如何在Linux系统中添加中文字体库。
59 1
java制作海报七:java Graphics2D 合成图片 在 linux下中文不显示,echarts图上的中文也不显示问题
|
3月前
|
Java Linux
java读取linux服务器下某文档的内容
java读取linux服务器下某文档的内容
50 3
java读取linux服务器下某文档的内容
|
3月前
|
运维 Java Linux
【运维基础知识】Linux服务器下手写启停Java程序脚本start.sh stop.sh及详细说明
### 启动Java程序脚本 `start.sh` 此脚本用于启动一个Java程序,设置JVM字符集为GBK,最大堆内存为3000M,并将程序的日志输出到`output.log`文件中,同时在后台运行。 ### 停止Java程序脚本 `stop.sh` 此脚本用于停止指定名称的服务(如`QuoteServer`),通过查找并终止该服务的Java进程,输出操作结果以确认是否成功。
118 1
|
3月前
|
算法 Java Linux
java制作海报五:java 后端整合 echarts 画出 折线图,项目放在linux上,echarts图上不显示中文,显示方框口口口
这篇文章介绍了如何在Java后端整合ECharts库来绘制折线图,并讨论了在Linux环境下ECharts图表中文显示问题。
77 1
|
4月前
|
Oracle Java 关系型数据库
Linux下JDK环境的配置及 bash: /usr/local/java/bin/java: cannot execute binary file: exec format error问题的解决
如果遇到"exec format error"问题,文章建议先检查Linux操作系统是32位还是64位,并确保安装了与系统匹配的JDK版本。如果系统是64位的,但出现了错误,可能是因为下载了错误的JDK版本。文章提供了一个链接,指向Oracle官网上的JDK 17 Linux版本下载页面,并附有截图说明。
Linux下JDK环境的配置及 bash: /usr/local/java/bin/java: cannot execute binary file: exec format error问题的解决
|
3月前
|
Java Linux Maven
用sdkman在linux上管理多个java版本
本文介绍了如何在Linux上使用SDKMAN来管理多个Java版本,包括安装SDKMAN、验证安装、列出和安装不同版本的JDK、Maven和Gradle,以及如何切换使用不同版本。
123 0
|
20天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
82 17
|
30天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者