您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

Java ssh实现远程服务器部署

时间:2022-03-17 10:54:01  来源:  作者:lehoon

pom依赖

        <dependency>
            <groupId>ch.ethz.ganymed</groupId>
            <artifactId>ganymed-ssh2</artifactId>
            <version>build210</version>
        </dependency>

 

BtpAbstractService类

/**
 * <p>Title: abstract service</p>
 * <p>Author: lehoon</p>
 * <p>Date: 2022/2/28 16:48</p>
 */
@Slf4j
public abstract class BtpAbstractService {
    protected String deployPath;
    protected String deployBasePath;
    //service operate request
    protected BtpDeployServiceBaseEntity serviceBaseEntity;

    public BtpAbstractService(BtpDeployServiceBaseEntity serviceBaseEntity) {
        this.serviceBaseEntity = serviceBaseEntity;
    }

    protected boolean isDeployBasePathEnvEmpty() {
        deployBasePath = StringUtils.trimToEmpty(getDeployBasePath());
        return StringUtils.isBlank(deployBasePath);
    }

    protected String getDeployBasePath() {
        return getEnvByName(BtpDeployNodeEnvType.BTP_DEPLOY_NODE_ENV_TYPE_DEPLOY_HOMEPATH.getValue());
    }

    protected String getEnvByName(String name) {
        if (serviceBaseEntity == null || CollectionUtil.isEmpty(serviceBaseEntity.getEnvMap())) return null;
        if (serviceBaseEntity.getEnvMap().contAInsKey(name)) return serviceBaseEntity.getEnvMap().get(name).getEnvValue();
        return null;
    }

    protected void updateDeployPath() {
        deployPath = String.format("%s/%s", fixFsFilePath(deployBasePath), serviceBaseEntity.getServiceId());
    }

    protected boolean checkNod.NETState() {
        return TcpHelper.isRemoteAlive(serviceBaseEntity.getNodeHost(), serviceBaseEntity.getNodePort());
    }

    protected String shellDisableEchoCmd() {
        return " >> /dev/null 2>&1";
    }

    protected void sleepCmd() {
        sleep(500);
    }

    protected void sleep3() {
        sleep(2000);
    }

    protected void sleep5() {
        sleep(5000);
    }

    protected void sleep(int timeout) {
        try {
            Thread.sleep(timeout);
        } catch (InterruptedException e) {
        }
    }

    protected String fixFsFilePath(String path) {
        if (path == null || path.length() == 0) return "";
        if (!path.endsWith("/")) return path;
        return path.substring(0, path.length() - 1);
    }

    protected boolean isDeployBasePathValid() {
        return deployBasePath != null && deployBasePath.startsWith("/");
    }


    abstract protected void preCheck() throws BtpDeployException;
    abstract protected void nextCheck() throws BtpDeployException;
    abstract protected void process() throws BtpDeployException;
    abstract protected void rollBack() throws BtpDeployException;
}

 

BtpAbstractSSHService类

/**
 * <p>Title: ssh 操作</p>
 * <p>Description: </p>
 * <p>Author: lehoon</p>
 * <p>Date: 2022/1/20 15:38</p>
 */
@Slf4j
public abstract class BtpAbstractSSHService extends BtpAbstractService {
    //ssh connection
    protected Connection connection = null;

    public BtpAbstractSSHService(BtpDeployServiceBaseEntity serviceBaseEntity) {
        super(serviceBaseEntity);
    }

    public void service() throws BtpDeployException {
        preCheck();

        try {
            login(1000);
        } catch (BtpDeployException e) {
            log.error("登陆远程服务器失败. ", e);
            throw e;
        }

        try {
            nextCheck();
            sleep3();
            process();
            disConnect();
        } catch (BtpDeployException e) {
            log.error("部署服务操作失败, 错误信息,", e);
            rollBack();
            disConnect();
            throw e;
        } finally {
            disConnect();
        }
    }

    public void disConnect() {
        if (connection == null) return;
        connection.close();
        connection = null;
    }

    /**
     * 登陆远程服务器
     * @param timeout
     * @throws Exception
     */
    public void login(int timeout) throws BtpDeployException {
        connection = new Connection(serviceBaseEntity.getNodeHost(), serviceBaseEntity.getNodePort());
        try {
            connection.connect(null, timeout, 0);
            boolean isAuthenticate = connection.authenticateWithPassword(serviceBaseEntity.getUserName(), serviceBaseEntity.getPassword());
            if (!isAuthenticate) {
                throw new BtpDeployException("用户名密码错误,登陆失败");
            }
        } catch (IOException e) {
            log.error("登陆远程服务器失败,", e);
            if (e.getCause().getMessage().indexOf("method password not supported") != -1) {
                throw new BtpDeployException("远程服务器不支持密码认证, 请修改ssh配置文件");
            }

            throw new BtpDeployException("登陆远程服务器失败, 请检查原因");
        } catch (Exception e){
            throw new BtpDeployException("登陆远程服务器失败, 请检查原因");
        }
    }

    private void checkConnectState() throws IOException {
        if (connection == null) throw new IOException("未与服务器建立连接, 不能执行命令.");
        if (!connection.isAuthenticationComplete()) throw new IOException("与服务器连接认证未通过, 不能执行命令.");
    }

    private String readCmdResult(InputStream inputStream) {
        StringBuilder result = new StringBuilder(1024);

        try {
            InputStream stdout = new StreamGobbler(inputStream);
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
            String cmdResLine = null;

            while (true) {
                cmdResLine = br.readLine();
                if (cmdResLine == null) {
                    break;
                }
                result.Append(cmdResLine);
            }
        } catch (IOException e) {
            log.error("读取远程服务器shell指令结果失败, ", e);
        }

        return result.toString();
    }

    public boolean executeCmd(String cmd) throws BtpDeploySSHExecException {
        try {
            return execute1(cmd);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BtpDeploySSHExecException(e.getMessage());
        }
    }

    private Session openSession() throws Exception {
        checkConnectState();

        try {
            return connection.openSession();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            throw new Exception("打开终端执行环境会话失败,执行命令失败.");
        }
    }

    /**
     * 执行命令
     * @param cmd
     * @return
     * @throws IOException
     */
    public String execute(String cmd) throws Exception {
        sleepCmd();
        Session session = openSession();
        preHandleSession(session);
        session.execCommand(cmd);
        String result = readCmdResult(session.getStdout());
        log.info("执行命令execute[{}],返回结果为[{}]",  cmd, result);
        session.close();
        return result;
    }

    public boolean execute1(String cmd) throws Exception {
        sleepCmd();
        Session session = openSession();
        preHandleSession(session);
        session.execCommand(cmd);
        String result = readCmdResult(session.getStdout());
        log.info("执行命令execute1[{}],返回结果为[{}]", cmd, result);
        int code = 0;
        try {
            code = session.getExitStatus();
            log.info("执行命令execute1[{}],操作码为[{}],返回结果为[{}]", cmd, code, result);
        } catch (Exception e) {
            log.error("执行命令出错", e.fillInStackTrace());
        } finally {
            if (session != null) session.close();
        }
        return code == 0;
    }

    /**
     * 创建目录
     * @param dir
     * @return
     */
    public String mkdir(String dir) throws BtpDeploySSHExecException {
        String cmd = String.format("mkdir -p %s", dir);
        try {
            return execute(cmd);
        } catch (Exception e) {
            log.error("创建目录失败,", e);
            throw new BtpDeploySSHExecException(e.getMessage());
        }
    }

    public boolean mkdir1(String dir) throws BtpDeploySSHExecException {
        String cmd = String.format("mkdir -p %s", dir);
        return executeCmd(cmd);
    }

    public boolean createDirectory(String directory) throws BtpDeploySSHExecException{
        return mkdir1(directory);
    }

    /**
     * 解压zip文件到指定目录
     * @param zipSrc
     * @param distDir
     * @return
     */
    public boolean unzip(String zipSrc, String distDir) throws BtpDeploySSHExecException {
        String cmd = String.format("unzip -oq %s -d %s", zipSrc, distDir);
        return executeCmd(cmd);
    }

    /**
     * 修改文件内容
     * @param src
     * @param dist
     * @param filePath
     * @return
     * @throws Exception
     */
    public String replaceInFile(String src, String dist, String filePath) throws BtpDeploySSHExecException {
        String cmd = String.format("sed -i 's/%s/%s/' %s", src, dist, filePath);
        try {
            return execute(cmd);
        } catch (Exception e) {
            log.error("修改文件内容失败", e);
            throw new BtpDeploySSHExecException();
        }
    }

    public boolean rmdir(String filePath) throws BtpDeploySSHExecException {
        if (filePath == null || filePath.length() == 0) return false;
        for (String path : SAFE_DELETE_FILESYSTEM_PATH_DEFAULT) {
            if (path.equalsIgnoreCase(filePath)) throw new BtpDeploySSHExecException(String.format("目录[%s]不允许删除", filePath));
        }

        String cmd = String.format("rm -rf %s", filePath);
        return executeCmd(cmd);
    }

    protected boolean deleteDirectory(String directory) throws BtpDeploySSHExecException {
        if (directory == null || directory.length() == 0 || "/".equalsIgnoreCase(directory)) return true;
        String cmd = String.format("rm -rf %s", directory);
        return executeCmd(cmd);
    }

    /**
     * 删除文件
     * @return
     * @throws IOException
     */
    protected boolean deleteFile(String filePath) throws BtpDeploySSHExecException {
        if (filePath == null || filePath.length() == 0 || "/".equalsIgnoreCase(filePath)) return true;
        String cmd = String.format("rm -rf %s", filePath);
        return executeCmd(cmd);
    }

    protected boolean deleteFile1(String filePath) {
        try {
            return deleteFile(filePath);
        } catch (BtpDeploySSHExecException e) {
            return false;
        }
    }

    /**
     * 文件拷贝:war包+策略zip文件
     * src=路径+文件名;des=目的路径
     *
     * */
    public void copyDoucment(String src, String des)
            throws BtpDeploySSHExecException {
        if (connection == null) throw new BtpDeploySSHExecException("未与服务器建立连接, 不能执行上传文件命令.");
        try {
            SCPClient scpClient = connection.createSCPClient();
            scpClient.put(src, des);
        } catch (IOException e) {
            log.error("上传文件到远程服务器失败,", e);
            throw new BtpDeploySSHExecException();
        }
    }

    /**
     * 进入指定目录并返回目录名称
     * @param basePath
     * @return
     * @throws IOException
     */
    public String cmdPwd(String basePath) throws BtpDeploySSHExecException {
        String cmd = String.format("cd %s && pwd", basePath);
        try {
            return execute(cmd);
        } catch (Exception e) {
            log.error(String.format("切换文件目录失败,目录[%s]不存在", basePath), e);
            throw new BtpDeploySSHExecException();
        }
    }

    public String moveFile(String oldPath, String newPath) throws BtpDeploySSHExecException {
        String cmd = String.format("mv %s %s", oldPath, newPath);
        try {
            return execute(cmd);
        } catch (Exception e) {
            log.error(String.format("移动文件失败,原文件[%s]目标目录[%s]不存在", oldPath, newPath), e);
            throw new BtpDeploySSHExecException();
        }
    }

    public String lsCmd(String filePath) throws BtpDeploySSHExecException {
        String cmd = String.format("ls %s", filePath);
        try {
            return execute(cmd);
        } catch (Exception e) {
            log.error(String.format("获取文件路径失败,文件[%s]不存在", filePath), e);
            throw new BtpDeploySSHExecException();
        }
    }

    public boolean checkFileExist(String filePath) throws BtpDeploySSHExecException {
        String checkFilePath = lsCmd(filePath);

        if (filePath.equalsIgnoreCase(checkFilePath)) {
            return true;
        }

        return false;
    }


    /**
     * 上传文件到远程服务器
     * @param localFileName
     * @param remotePath
     * @param remoteFileName
     * @throws IOException
     */
    public void uploadFileToRemote(String localFileName, String remotePath, String remoteFileName)
            throws BtpDeploySSHExecException {
        if (connection == null) throw new BtpDeploySSHExecException("未与服务器建立连接, 不能执行上传文件命令.");

        try {
            SCPClient scpClient = connection.createSCPClient();// 建立SCP客户端:就是为了安全远程传输文件
            scpClient.put(localFileName, remoteFileName, remotePath, "0600");
        } catch (IOException e) {
            log.error("上传文件到远程服务器失败,", e);
            throw new BtpDeploySSHExecException();
        }
    }

    public boolean uploadFile2Remote(String localFileName, String remotePath, String remoteFileName) {
        try {
            uploadFileToRemote(localFileName, remotePath, remoteFileName);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    protected boolean checkDeployBasePathExist() throws BtpDeploySSHExecException {
        String tempPathPwd = cmdPwd(deployBasePath);

        if (StringUtils.isBlank(tempPathPwd)) {
            log.info("远程服务器上部署根目录在远程服务器上不存在, {}", deployBasePath);
            return false;
        }

        deployBasePath = tempPathPwd;
        return true;
    }

    protected boolean checkDeployPathExist() throws BtpDeploySSHExecException {
        String tempPathPwd = cmdPwd(deployPath);

        if (StringUtils.isBlank(tempPathPwd)) {
            log.info("远程服务器上部署目录在远程服务器上不存在{}", deployPath);
            return false;
        }

        deployPath = tempPathPwd;
        return true;
    }

    protected boolean dos2unix(String filePath) throws BtpDeploySSHExecException {
        if (filePath == null || filePath.length() == 0) return false;
        String cmd = String.format("dos2unix %s", filePath);
        return executeCmd(cmd);
    }

    protected String getFileName(String filename) {
        if (filename == null || filename.length() == 0) return null;
        return filename.substring(0, filename.lastIndexOf("."));
    }

    private void preHandleSession(Session session) throws IOException {
        session.requestPTY("vt100");
    }

    private static List<String> SAFE_DELETE_FILESYSTEM_PATH_DEFAULT
            = new ArrayList<String>(16);

    static {
        SAFE_DELETE_FILESYSTEM_PATH_DEFAULT.add("/");
        SAFE_DELETE_FILESYSTEM_PATH_DEFAULT.add("/boot");
        SAFE_DELETE_FILESYSTEM_PATH_DEFAULT.add("/home");
        SAFE_DELETE_FILESYSTEM_PATH_DEFAULT.add("/opt");
        SAFE_DELETE_FILESYSTEM_PATH_DEFAULT.add("/usr");
        SAFE_DELETE_FILESYSTEM_PATH_DEFAULT.add("/etc");
    }
}

 

具体操作类通过实现
BtpAbastractSSHApamaService类即可



Tags:Java ssh   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Java ssh实现远程服务器部署
pom依赖 <dependency> <groupId>ch.ethz.ganymed</groupId> <artifactId>ganymed-ssh2</artifactId> <version>build210</version...【详细内容】
2022-03-17  Search: Java ssh  点击:(445)  评论:(0)  加入收藏
SSHJ - 功能齐全的Java SSH库
SSH(Secure Shell,安全外壳协议),是专为远程登录会话和其他网络服务提供安全性的应用层协议。在日常开发中,包括登录远程服务器、远程执行命令脚本、文件传输等,都使用了 SSH 协议...【详细内容】
2020-07-19  Search: Java ssh  点击:(5376)  评论:(0)  加入收藏
▌简易百科推荐
Java 8 内存管理原理解析及内存故障排查实践
本文介绍Java8虚拟机的内存区域划分、内存垃圾回收工作原理解析、虚拟机内存分配配置,以及各垃圾收集器优缺点及场景应用、实践内存故障场景排查诊断,方便读者面临内存故障时...【详细内容】
2024-03-20  vivo互联网技术    Tags:Java 8   点击:(17)  评论:(0)  加入收藏
如何编写高性能的Java代码
作者 | 波哥审校 | 重楼在当今软件开发领域,编写高性能的Java代码是至关重要的。Java作为一种流行的编程语言,拥有强大的生态系统和丰富的工具链,但是要写出性能优异的Java代码...【详细内容】
2024-03-20    51CTO  Tags:Java代码   点击:(25)  评论:(0)  加入收藏
在Java应用程序中释放峰值性能:配置文件引导优化(PGO)概述
译者 | 李睿审校 | 重楼在Java开发领域,优化应用程序的性能是开发人员的持续追求。配置文件引导优化(Profile-Guided Optimization,PGO)是一种功能强大的技术,能够显著地提高Ja...【详细内容】
2024-03-18    51CTO  Tags:Java   点击:(29)  评论:(0)  加入收藏
Java生产环境下性能监控与调优详解
堆是 JVM 内存中最大的一块内存空间,该内存被所有线程共享,几乎所有对象和数组都被分配到了堆内存中。堆被划分为新生代和老年代,新生代又被进一步划分为 Eden 和 Survivor 区,...【详细内容】
2024-02-04  大雷家吃饭    Tags:Java   点击:(60)  评论:(0)  加入收藏
在项目中如何避免和解决Java内存泄漏问题
在Java中,内存泄漏通常指的是程序中存在一些不再使用的对象或数据结构仍然保持对内存的引用,从而导致这些对象无法被垃圾回收器回收,最终导致内存占用不断增加,进而影响程序的性...【详细内容】
2024-02-01  编程技术汇  今日头条  Tags:Java   点击:(76)  评论:(0)  加入收藏
Java中的缓存技术及其使用场景
Java中的缓存技术是一种优化手段,用于提高应用程序的性能和响应速度。缓存技术通过将计算结果或者经常访问的数据存储在快速访问的存储介质中,以便下次需要时可以更快地获取。...【详细内容】
2024-01-30  编程技术汇    Tags:Java   点击:(75)  评论:(0)  加入收藏
JDK17 与 JDK11 特性差异浅谈
从 JDK11 到 JDK17 ,Java 的发展经历了一系列重要的里程碑。其中最重要的是 JDK17 的发布,这是一个长期支持(LTS)版本,它将获得长期的更新和支持,有助于保持程序的稳定性和可靠性...【详细内容】
2024-01-26  政采云技术  51CTO  Tags:JDK17   点击:(95)  评论:(0)  加入收藏
Java并发编程高阶技术
随着计算机硬件的发展,多核处理器的普及和内存容量的增加,利用多线程实现异步并发成为提升程序性能的重要途径。在Java中,多线程的使用能够更好地发挥硬件资源,提高程序的响应...【详细内容】
2024-01-19  大雷家吃饭    Tags:Java   点击:(111)  评论:(0)  加入收藏
这篇文章彻底让你了解Java与RPA
前段时间更新系统的时候,发现多了一个名为Power Automate的应用,打开了解后发现是一个自动化应用,根据其描述,可以自动执行所有日常任务,说的还是比较夸张,简单用了下,对于office、...【详细内容】
2024-01-17  Java技术指北  微信公众号  Tags:Java   点击:(102)  评论:(0)  加入收藏
Java 在 2023 年仍然流行的 25 个原因
译者 | 刘汪洋审校 | 重楼学习 Java 的过程中,我意识到在 90 年代末 OOP 正值鼎盛时期,Java 作为能够真正实现这些概念的语言显得尤为突出(尽管我此前学过 C++,但相比 Java 影响...【详细内容】
2024-01-10  刘汪洋  51CTO  Tags:Java   点击:(81)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条