JAVA代码处理jar包、sftp传输、ssh执行命令。

39 篇文章 1 订阅

1.背景

  某公司开发、测试两套环境,暂未有一整套从开发到测试的部署工具,开发人员需要手动删除本地jar包内容,使用filezilla上传到开发、测试环境,再重启服务,由于使用springcloud,服务还得等未知时间后才能被发现并可用。

2.改造

  目的主要为了方便开发使用,提升开发效率,使用技术为jsch,为了快速实现,未做界面(后续效果好,可能会应用到部署生产环境中,可以省力),主要根据网上内容重写了部分工具类,并根据需要进行了部分整合,花了1天左右时间完成,方便后续开发者使用。

3.jsch

 JSch 是SSH2的一个纯Java实现。它允许你连接到一个sshd 服务器,使用端口转发,X11转发,文件传输等等。你可以将它的功能集成到你自己的 程序中。

maven依赖:

		<dependency>
			<groupId>com.jcraft</groupId>
			<artifactId>jsch</artifactId>
			<version>0.1.54</version>
		</dependency>

4.主要工具类

4.1 jar包删除指定文件(删除本地配置文件等)

package com.ybjdw.tool.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

/**
 * author: zhanggw
 * 创建时间:  2020/4/15
 */
public class JarUtil {
    private static Logger logger = LoggerFactory.getLogger(JarUtil.class);

    public static void main(String[] args) {
        String jarName = "E:\\idea_workspace\\product\\target\\product-0.0.1-SNAPSHOT.jar";
        List<String> deleteKeys = new ArrayList<>();
        deleteKeys.add("BOOT-INF/classes/application.properties");
        deleteKeys.add("BOOT-INF/classes/logback.xml");
        delete(jarName, deleteKeys, true);
    }

    public static void delete(String jarName, List<String> deletes, Boolean deleteBak) {
        JarOutputStream jos = null;
        InputStream inputStream = null;
        JarFile bakJarFile = null;
        File bakFile = null;
        try{
            //先备份
            File oriFile = new File(jarName);
            if (!oriFile.exists()) {
                logger.error("{}未找到!", jarName);
                return;
            }
            //将文件名命名成备份文件
            String bakJarName = jarName.substring(0, jarName.length() - 3) + DateUtils.getNowDateStr("yyyyMMddHHmmssSSS") + ".jar";
            bakFile = new File(bakJarName);
            boolean isOK = oriFile.renameTo(bakFile);
            if (!isOK) {
                logger.error("文件重命名失败!");
                return;
            }

            // 创建新jar包(删除指定内容)
            bakJarFile = new JarFile(bakJarName);
            jos = new JarOutputStream(new FileOutputStream(jarName));
            Enumeration<JarEntry> entries = bakJarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                if (!deletes.contains(entry.getName())) {
                    inputStream = bakJarFile.getInputStream(entry);
                    jos.putNextEntry(entry);
                    byte[] bytes = readStream(inputStream);
                    jos.write(bytes, 0, bytes.length);
                }
                else {
                    logger.debug("Delete内容" + entry.getName());
                }
            }
        }catch (Exception e){
            logger.error(e.getMessage());
        }finally {
            if(jos != null){
                try{
                    jos.flush();
                    jos.finish();
                    jos.close();
                }catch (Exception e){
                    logger.debug(e.getMessage());
                }
            }

            if(inputStream != null){
                try{
                    inputStream.close();
                }catch (Exception e){
                    logger.debug(e.getMessage());
                }
            }

            if(bakJarFile != null){
                try{
                    bakJarFile.close();
                }catch (Exception e){
                    logger.debug(e.getMessage());
                }
            }

            if(deleteBak){
                Boolean delFlag = bakFile.delete();
                if(delFlag !=null && !delFlag){
                    logger.debug("删除jar包中内容失败!");
                }
            }
        }
    }

    private static byte[] readStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();
        return outSteam.toByteArray();
    }
}

4.2 SFTP上传下载(备份服务器文件和上传更新等)

package com.ybjdw.tool.utils;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * author: zhanggw
 * 创建时间:  2020/4/15
 */
public class SftpUtil {

    private Logger logger = LoggerFactory.getLogger(SftpUtil.class);

    // host_name sftp
    private Map<String, ChannelSftp> sftpMap = new HashMap<>();
    private Map<String, Session> sessionMap = new HashMap<>();

    public static void main(String[] args) {
        String localPath = "E:/idea_workspace/product/target/product-0.0.1-SNAPSHOT.jar";
        SftpUtil sftpUtil = new SftpUtil();
        String host = "192.168.0.105";
        String username = "product";
        ChannelSftp sftp = sftpUtil.createSftp("192.168.0.105", 22, "product", "product");
        sftpUtil.uploadFile(sftp, "/home/product/app/product-0.0.1-SNAPSHOT.jar", localPath, true);
        sftpUtil.closeSFtp(host, username);
    }

    public ChannelSftp createSftp(String host, int port, String username, String password){
        ChannelSftp channel = null;
        try{
            String mapKey = host + "_" + username;
            JSch jsch = new JSch();
            Session session = jsch.getSession(username, host, port);

            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect(5000);
            sessionMap.put(mapKey, session);

            channel = (ChannelSftp)session.openChannel("sftp");
            channel.connect(5000);
            sftpMap.put(mapKey, channel);
        }catch (Exception e){
            logger.debug("sftp获取连接异常:"+e.getMessage());
        }
        return channel;
    }

    public void downloadFile(ChannelSftp sftp, String ftpPath, String localDir, boolean sameName) {
        OutputStream outputStream = null;
        try {
            String localPath = localDir + "/";
            if(sameName){
                localPath = localPath + ftpPath.substring(ftpPath.lastIndexOf("/") + 1);
            }else{
                localPath = localPath + DateUtils.getNowDateStr("yyyyMMddHHmmss") + "_" + ftpPath.substring(ftpPath.lastIndexOf("/") + 1);
            }
            File localFile = new File(localPath);
            outputStream = new FileOutputStream(localFile);
            sftp.get(ftpPath, outputStream);
        } catch (Exception e) {
            logger.debug(e.getMessage());
        }finally {
            if(outputStream != null){
                try {
                    outputStream.close();
                    logger.debug("{}下载完毕,本地路径:{}", ftpPath, localDir);
                } catch (IOException e) {
                    logger.debug(e.getMessage());
                }
            }
        }
    }

    public void closeSFtp(String host, String username){
        if(StringUtils.isBlank(host) && StringUtils.isBlank(username)){
            return;
        }

        String mapKey = host + "_" + username;
        ChannelSftp channelSftp = sftpMap.get(mapKey);
        if(channelSftp != null && !channelSftp.isClosed()){
            channelSftp.disconnect();
        }

        Session session = sessionMap.get(mapKey);
        if(session != null && session.isConnected()){
            session.disconnect();
        }
    }

    public void uploadFile(ChannelSftp sftp, String targetPath, String localPath, boolean overwrite){
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(localPath);
            if(overwrite){
              sftp.put(inputStream, targetPath, ChannelSftp.OVERWRITE);
            }else{
                sftp.put(inputStream, targetPath);
            }
        } catch (Exception e) {
            logger.debug("sftp上传文件异常:{}", e.getMessage());
        }finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.debug(e.getMessage());
                }
            }
            logger.debug("{}已上传到{}",localPath,targetPath);
        }
    }
}

4.3 SSH连接及执行命令(执行脚本、重启服务等)

package com.ybjdw.tool.utils;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;

/**
 * author: zhanggw
 * 创建时间:  2020/4/16
 */
public class SSHUtil {
    private static Logger logger = LoggerFactory.getLogger(SSHUtil.class);

    public static void main(String[] args) {
        SSHUtil sshUtil = new SSHUtil();
        sshUtil.execCommand("dev", "pwd");
    }

    public String execCommand(String env, String cmd){
        String host = "192.168.0.105";
        int port = 22;
        String username = "root";
        String password = "123456";

        if("test".equals(env)){
            host = "120.xx.xx.xx";
            password = "xxxxxx";
        }

        String ret = execCommand(host, port, username, password, cmd);
        logger.debug("命令执行结果:{}", ret);
        return ret;
    }

    public String execCommand(String host, int port, String user, String password, String command){
        String out = "";
        try{
            JSch jsch = new JSch();
            Session session = jsch.getSession(user, host, port);
            session.setConfig("StrictHostKeyChecking", "no");
            session.setPassword(password);
            session.connect();

            ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
            InputStream in = channelExec.getInputStream();
            channelExec.setCommand(command);
            channelExec.setErrStream(System.err);
            channelExec.connect();
            out = IOUtils.toString(in, "UTF-8");

            channelExec.disconnect();
            session.disconnect();
        }catch (Exception e){
            logger.debug(e.getMessage());
        }
        return out;
    }

}

最后的整合

package com.ybjdw.tool.utils;

import com.alibaba.fastjson.JSONObject;
import com.jcraft.jsch.ChannelSftp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * author: zhanggw
 * 创建时间:  2020/4/15
 */
public class AutoDeployUtil {
    private static Logger logger = LoggerFactory.getLogger(AutoDeployUtil.class);

    public static void main(String[] args) throws Exception{
        new AutoDeployUtil().testServiceUpdateAndReload("product");
    }

    public void testServiceUpdateAndReload(String serviceName){
        try{
            long startTime = System.currentTimeMillis();

            // 备份上传
            String localWorkSpace = "E:/idea_workspace";
            String localBackupDir = "d:/tmp/serviceJar";
            AutoDeployUtil autoDeployUtil = new AutoDeployUtil();
            logger.debug("开始修改jar包内容!");
            autoDeployUtil.perfectLocalJar(localWorkSpace, serviceName);
            logger.debug("开始备份并上传新jar包!");
            autoDeployUtil.backupAndUpload(localBackupDir,"dev",localWorkSpace,serviceName);

            SSHUtil sshUtil = new SSHUtil();
            // 开发环境重启
            logger.debug("开始重启开发环境!");
            String restartService = "sh restart_app.sh " + serviceName;
            sshUtil.execCommand("dev", restartService);

            // 传输到测试环境
            logger.debug("开始把新jar包传送到测试环境!");
            String cmd = "sh sftp_test.sh "+serviceName;
            sshUtil.execCommand("dev", cmd);

            // 测试环境重启
            logger.debug("开始重启测试环境服务!");
            sshUtil.execCommand("test", restartService);
            logger.debug("开发测试环境服务已更新重启,花费时间:{}秒", (System.currentTimeMillis()-startTime)/1000);

            JSONObject paramJson = new JSONObject();
            paramJson.put("userId", "1234");
            int sucTime = 0;
            for(int i=0; i < 10000000; i++){
                JSONObject retJson = httpTest("test", serviceName, "/testUri", paramJson,false);
                if(retJson.getBoolean("flag") != null){
                    sucTime++;
                }
                if(sucTime >= 60){
                    break;
                }
                Thread.sleep(100);
            }
            logger.debug("开发测试环境服务已可以使用,总花费时间:{}秒", (System.currentTimeMillis()-startTime)/1000);
        }catch (Exception e){
            logger.debug(e.getMessage());
        }
    }

    private static JSONObject httpTest(String env,String serviceName, String uri, JSONObject paramJson, boolean logFlag) {
        String url = HttpRequestUtils.getUrl(env,serviceName,uri);
        JSONObject data = new JSONObject();
        JSONObject reqParam = new JSONObject();
        data.putAll(paramJson);
        reqParam.put("data", data);

        HttpRequestUtils httpRequestUtils = new HttpRequestUtils();
        JSONObject response = httpRequestUtils.httpPost(url, reqParam, null);
        if(logFlag){
            logger.debug("响应结果:{}", response);
        }
        return response;
    }

    public void perfectLocalJar(String localWorkspace, String serviceName){
        String localJarPath = localWorkspace + "/" + serviceName + "/target/" + serviceName +"-0.0.1-SNAPSHOT.jar";
        List<String> deleteKeys = new ArrayList<>();
        deleteKeys.add("BOOT-INF/classes/application.properties");
        deleteKeys.add("BOOT-INF/classes/logback.xml");
        JarUtil.delete(localJarPath,deleteKeys,true);
        logger.debug("{}服务jar包已完善!", serviceName);
    }

    public void backupAndUpload(String localBackupDir, String env, String localWorkspace, String serviceName){
        logger.debug("{}环境{}服务开始备份并上传!", env, serviceName);

        // 连接信息
        String host = "192.168.0.105";
        int port = 22;
        String username = "";
        String password = "";
        if("dev".equals(env)){
            username = serviceName;
            password = serviceName;
        }
        if("test".equals(env)){
            host = "120.xx.xx.xx";
            username = "root";
            password = "xxxxxx";
        }

        // 下载备份
        String ftpPath = "/home/"+serviceName+"/app/"+serviceName+"-0.0.1-SNAPSHOT.jar";
        String localPath = localBackupDir + "/" + env;
        SftpUtil sftpUtil = new SftpUtil();
        ChannelSftp sftp = sftpUtil.createSftp(host, port, username, password);
        sftpUtil.downloadFile(sftp, ftpPath, localPath, false);

        // 上传jar
        String targetPath = "/home/"+serviceName+"/app/"+serviceName+"-0.0.1-SNAPSHOT.jar";
        String localJarPath = localWorkspace + "/" + serviceName + "/target/" + serviceName +"-0.0.1-SNAPSHOT.jar";
        sftpUtil.uploadFile(sftp, targetPath, localJarPath, true);

        // 关闭连接
        sftpUtil.closeSFtp(host, username);
    }

}

最后的效果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kenick

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值