zoukankan      html  css  js  c++  java
  • java-springboot使用JSch远程

    转载自https://www.cnblogs.com/ArcherWuAIot/p/12790486.html

    JSch 是SSH2的一个纯Java实现。它允许通过代码的方式连接到一个sshd 服务器,使用端口转发,X11转发,文件传输等等。可以将它的功能集成到自己写的程序中。实现一个java工具类。

    SSH由客户端和服务端的软件两部分组成,在客户端可以使用的软件有SecureCRT、putty、Xshell等,而在服务器端运行的是一个sshd的服务,通过使用SSH,可以把所有传输的数据进行加密,而且也能够防止dns和IP欺骗,此外,SSH传输的数据是经过压缩的,可以加快传输速度。服务器端的配置文件路径: /etc/ssh/sshd_config

    spring-boot引用:

    dependencies {
    
        compile group: 'com.jcraft', name: 'jsch', version: '0.1.55'
    
    }

    代码里的命令调用:

     try {
                String result = clusterCommondService.execOnly(
                        "xxxxxxxxx " + name + " xxxx" + "
    ");
            } catch (Exception e) {
                log.error("Error when init :", e);
                return null;
            }

    java代码实现

    @Slf4j
    @Service
    public class ClusterCommondService {

    @Value("${cluster.pemPrivateKey}")
    protected String pemPrivateKey;
    @Value("${cluster.port}")
    protected int port;
    @Value("${cluster.user}")
    protected String user;
    //写在配置文件里的配置值
    @Autowired
    private ClusterIpUtil clusterIpUtil;
    //连接的IP
    private Session session = null;
    private boolean bConnect = false;

    //默认第一次是false,先建立连接

        protected String ip;

    private void initConnection() throws JSchException {
    ip = clusterIpUtil.getClusterIp();
    String begin = "-----BEGIN RSA PRIVATE KEY-----";
    String end = "-----END RSA PRIVATE KEY-----";
    String a = pemPrivateKey.replace(" ", " ");
    String privateKey = begin + " " + a + " " + end;
    JSch jsch = new JSch();
    jsch.addIdentity(user, privateKey.getBytes(), null, null);
    session = jsch.getSession(user, ip, port);
    session.setConfig("PreferredAuthentications", "publickey");
    session.setConfig("StrictHostKeyChecking", "no");
    session.setConfig("userauth.gssapi-with-mic", "no");
    session.setConfig("UserKnownHostsFile", "/dev/null");
    session.setServerAliveCountMax(3);
    //连接三次,连不上就不连接了
            session.connect();
    bConnect = true;
    }
    //设置连接信息,应该是代替了客户端的/etc/ssh/ssh_config

    public String exec(String cmd) throws JSchException, IOException {
    if (!bConnect) {
    initConnection();
    }
    ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
    //使用exec方式建立连接(补充,jsch跑命令分两种方式,一种是exec,一种是sftp;从远端拿文件或者向远端传文件的话用sftp,跑命令然后拿返回值的话用exec)
    channelExec.setCommand(cmd);
    //把命令放进连接里
    channelExec.setInputStream(null);
    channelExec.setErrStream(System.err);
    //设置输入流和错误信息流,清空输入流
    InputStream in = channelExec.getInputStream();
    //建一个in是输入流
    channelExec.connect();
    //建立连接,和远端建立连接之后上面的命令就自动执行了(此时的in里面就有返回值了)
    int res = -1;
    StringBuilder buf = new StringBuilder(1024);
    byte[] tmp = new byte[1024];
    while (true) {
    while (in.available() > 0) {
    int i = in.read(tmp, 0, 1024);
    if (i < 0) break;
    //这如果读不到了,就说明读完了命令,就可以退出去了
    buf.append(new String(tmp, 0, i));
    }
    if (channelExec.isClosed()) {
    //判断连接关闭,这个是在把信息读出来之后判断的
    res = channelExec.getExitStatus();
    //这个是状态码,正常是0,如果运行命令出问题就不是0了;不同的数值代表不同的错误
    if (res != 0)
    log.error(format("Exit-status: %d", res));
    break;
    }
    }
    if (res != 0){
    log.error(buf.toString());
    channelExec.disconnect();
    //操作完后channel连接关闭
    return null;
    }
    channelExec.disconnect();
    //操作完后channel连接关闭
            return buf.toString();
    }

    private String download(String downloadFile) throws JSchException, SftpException, IOException {
    if (!bConnect)
    initConnection();
    ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
    channelSftp.connect();

    StringBuilder result = new StringBuilder();
    String temp = "";
    InputStream is = channelSftp.get(downloadFile);
    byte[] buff = new byte[1024 * 2];
    int read;
    if (is != null) {
    log.debug("Start to read input stream");
    do {
    read = is.read(buff, 0, buff.length);
    if (read > 0) {
    temp = new String(buff);
    result.append(temp);
    }
    } while (read >= 0);
    log.debug("input stream read done.");
    }
    channelSftp.disconnect();
    return result.toString();
    }

    public synchronized String execOnly(String cmd) throws IOException, JSchException {
    String result = exec(cmd);
    close();
    //在close()里边把bconnect置为false,关闭此次连接。(每调用一次后,就关闭连接)
    return result;
    }

    public String execAndDownload(String cmd) throws IOException, JSchException, SftpException {
    String fileName = exec(cmd);
    String fileData = download(fileName.replace(" ", ""));
    close();
    //ession连接关闭
    return fileData;
    }

    private void close() {
    session.disconnect();
    bConnect = false;
    }
    }

    session是跟远程主机建立一个连接,JSch 在这个连接上建立一个通道专门执行命令,setCommand就是一个字节数组,存储我要执行的命令,然后打开一个流,通过这个流将我要执行的命令送到远程主机上执行,上图代码中的in里面是返回过来的数据。

  • 相关阅读:
    MySQL之索引优化
    使用Nginx+Lua(OpenResty)开发高性能Web应用
    Eclipse设置背景色
    删除排序数组中的重复项再练习
    计数排序_数组与集合时间比较
    nodejs+redis应用
    redis的一些优缺点
    Redis的线程模型
    GC仅仅是守护线程,空闲执行
    SpringIOC和AOP的生活案例
  • 原文地址:https://www.cnblogs.com/lingjies/p/13153812.html
Copyright © 2011-2022 走看看