工具类一:java代码实现ssh远程登陆服务器,执行shell命令和ftp传输

需求:

项目中经常会遇到在代码中实现执行shell命令的需求,或者通过ftp传输文件的需求。分为两种情况:

  1. 服务器在远端,需要先登录再操作。使用工具类JSch(Java Secure Channel)实现
  2. 在本机上操作,无需登录。可使用RunTime类或者ProcessBuilder类实现
    文本介绍第一种情况的实现

步骤

  1. 引入pom依赖
<dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.27</version>
</dependency>
  1. 登录服务器,打开会话。这是最基础的一步,常用的三种通道,即ChannelShell、ChannelExec、ChannelSftp都基于Session
    /**
     * 登陆并打开服务器会话
     * @param ip       目标主机名或ip
     */
    private static Session getSession(String ip, String username, String password, Integer port) {
     
        Session session = null;
        JSch jSch = new JSch();
        try {
     
            if (port != null) {
     
                session = jSch.getSession(username, ip, port.intValue());
            } else {
     
                session = jSch.getSession(username, ip);
            }
            if (password != null) {
     
                session.setPassword(password);
            }
            //关闭主机密钥检查,否则会导致连接失败
            Properties properties = new Properties();
            properties.setProperty("StrictHostKeyChecking", "no");
            session.setConfig(properties);
            //打开会话,并设置超时时间
            session.connect(30000);
        } catch (JSchException e) {
     
            e.printStackTrace();
        }
        return session;
    }
  1. 打开sftp通道
    /**
     * 获取sftp连接
     */
    public static ChannelSftp getChannelSftp(Session session) {
     
        ChannelSftp channel = null;
        try {
     
            //打开通道,设置通道类型
            channel = (ChannelSftp) session.openChannel("sftp");
            channel.connect();
        } catch (Exception e) {
     
            e.printStackTrace();
        }
        return channel;
    }
  1. 实现本地文件通过ftp上传至服务器。如果想要从其他源上传文件,只需要更改方法中InputStream的获取方式,例如可以将hdfs上的文件上传
    /**
     * 示例四:向指定服务器的路径上传文件
     * @param ip
     * @param username
     * @param password
     * @param port
     * @param srcPath 本地文件路径
     * @param desPath 服务器目标路径(带文件名)
     * @return
     */
    public static Boolean upload(String ip, String username, String password, Integer port,String srcPath,String desPath) {
     
        Boolean flage = false;
        Session session = getSession(ip, username, password, port);
        ChannelSftp channelSftp = getChannelSftp(session);
        try {
     
            InputStream inputStream = new FileInputStream(srcPath);
            //上传
            channelSftp.put(inputStream,desPath);
            channelSftp.quit();
            channelSftp.exit();
            flage = true;
        } catch (Exception e) {
     
            e.printStackTrace();
        } finally {
     
            channelSftp.disconnect();
            session.disconnect();
        }
        return flage;
    }
    // 测试
    public static void main(String[] args) {
     
        Boolean b = upload("192.168.136.101", "hdp", "111111", 22,"D:\\feiq\\FeiqCfg.xml","/home/hdp/manage/FeiqCfg.xml");
        if (b) System.out.println("上传成功");
    }
  1. 打开ChannelExec通道。至于ChannelShell与ChannelExec通道的区别,可自行搜获,这里不展开讨论
    /**
     * 打开exec通道
     */
    public static ChannelExec getChannelExec(Session session) {
     
        ChannelExec channel = null;
        try {
     
            //设置通道类型
            channel = (ChannelExec) session.openChannel("exec");
        } catch (Exception e) {
     
            e.printStackTrace();
        }
        return channel;
    }
  1. 连接ChannelExec通道,执行shell命令,并返回执行结果
    /**
     * 示例三:直接获取服务器磁盘使用情况(不读写文件的方式)
     */
    public static List<String[]> getDiskUsage(String ip, String username, String password, Integer port) {
     
        List<String[]> result = null;
        Session session = getSession(ip, username, password, port);
        ChannelExec channelExec = getChannelExec(session);
        try {
     
            channelExec.setCommand("df -hl | awk '{if (NR>1){print}}'");
            channelExec.connect();
            InputStream inputStream = channelExec.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String line = null;
            while ((line = reader.readLine()) != null) {
     
                String[] split = line.split("\\s+");
                result.add(split);
            }
            reader.close();
        } catch (Exception e) {
     
            e.printStackTrace();
        } finally {
     
            channelExec.disconnect();
            session.disconnect();
        }
        return result;
    }
    
    // 测试
    public static void main(String[] args) {
     
        List<String[]> usage = getDiskUsage("192.168.136.101", "hdp", "111111", 22);
        usage.forEach(x -> System.out.println(x));
        //Boolean b = upload("192.168.136.101", "hdp", "111111", 22,"D:\\feiq\\FeiqCfg.xml","/home/manage/FeiqCfg.xml");
        //if (b) System.out.println("上传成功");
    }

注意
1.登陆服务器是,支持密钥的方式登陆,只需在jsch.getSession之前调用jsch.addIdentity方法设置一下密钥的相关信息就可以了
2.通道断开后,还要将session断开,否则程序将一直处于运行状态

你可能感兴趣的:(shell)