diff --git a/nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeployDevTest.java b/nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeployDevTest.java new file mode 100644 index 00000000..f33f4ab2 --- /dev/null +++ b/nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeployDevTest.java @@ -0,0 +1,334 @@ +package com.nflg.wms.admin; + +import cn.hutool.core.util.StrUtil; +import com.jcraft.jsch.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class DeployDevTest { + + private static final String serviceName = "admin-dev"; + private static final String localPath = System.getProperty("user.dir") + "//target//"; + private static final String remotePath = "/mnt/app/wms/" + serviceName + "/"; + private static final String jarName = "nflg-wms-admin-1.0.0-SNAPSHOT.jar"; + + @Test + public void DeployToSit() throws Exception { + SSHUtil sshUtil = new SSHUtil(); + sshUtil.connect("192.168.163.84", 22, "root", "CMP2025nf"); + //处理主jar包 + handleFile(sshUtil, localPath + jarName, remotePath + jarName); + //处理字体目录 +// handleDir(sshUtil, localPath, remotePath, "fonts"); + //处理lib目录 + handleDir(sshUtil, localPath, remotePath, "lib"); + //执行脚本启动服务 + sshUtil.exec("cd " + remotePath + " && ./restart.sh"); + sshUtil.disconnect(); + } + + private void handleDir(SSHUtil sshUtil, String localPath, String remotePath, String dirName) throws Exception { + printInfo("处理目录:" + dirName); + List files = getFileList(localPath + "lib"); + for (Path file : files) { + handleFile(sshUtil, file.toString(), remotePath + "lib/" + file.getFileName().toString()); + } + printInfo("处理目录完成"); + } + + public List getFileList(String folderPath) throws IOException { + Path path = Paths.get(folderPath); + if (Files.exists(path) && Files.isDirectory(path)) { + List fileList = new ArrayList<>(); + try (DirectoryStream stream = Files.newDirectoryStream(path)) { + for (Path entry : stream) { + fileList.add(entry); + } + } + return fileList; + } + return null; + } + + private void handleFile(SSHUtil sshUtil, String localPath, String remotePath) throws Exception { + BasicFileAttributes localFileAttr = Files.readAttributes(Paths.get(localPath), BasicFileAttributes.class); + printInfo("处理文件:{},大小:{}", localPath, getSize(localFileAttr.size())); + if (sshUtil.fileExists(remotePath)) { + if (!StrUtil.equals(getRemoteFileMD5(sshUtil, remotePath), getLocalFileMD5(localPath), true)) { + printError("文件不一致,开始上传"); + sshUtil.uploadFile(localPath, remotePath); + } else { + printInfo("文件一致"); + } + } else { + printError("文件不存在,开始上传"); + sshUtil.uploadFile(localPath, remotePath); + } + printInfo("处理完成"); + } + + private String getRemoteFileMD5(SSHUtil sshUtil, String remotePath) throws Exception { + String md5 = StrUtil.subPre(sshUtil.execWithReturn("md5sum " + remotePath), 32); + printInfo("远程文件MD5为" + md5); + return md5; + } + + private String getLocalFileMD5(String localPath) throws Exception { + String md5 = DigestUtils.md5Hex(new FileInputStream(localPath)); + printInfo("本地文件MD5为" + md5); + return md5; + } + + private String getSize(long size) { + long s = 1024; + if (size < s) { + return size + "B"; + } + s = s * 1024; + if (size < s) { + return String.format("%.2f", size / 1.00 / 1024) + "KB"; + } + s = s * 1024; + if (size < s) { + return String.format("%.2f", size / 1.00 / 1024 / 1024) + "MB"; + } + s = s * 1024; + return String.format("%.2f", size / 1.00 / 1024 / 1024 / 1024) + "GB"; + } + + private static class SSHUtil { + + private Session session; + private ChannelSftp channelSftp; + + /** + * 建立SSH连接 + */ + public void connect(String host, int port, String userName, String password) throws JSchException { + printInfo("开始连接服务器,ip:{},port:{},userName:{},password:{}", host, port, userName, password); + JSch jsch = new JSch(); + session = jsch.getSession(userName, host, port); + session.setPassword(password); + session.setConfig("StrictHostKeyChecking", "no"); + session.connect(); + printInfo("连接成功"); + + Channel channel = session.openChannel("sftp"); + channel.connect(); + channelSftp = (ChannelSftp) channel; + } + + public String execWithReturn(String command) throws Exception { + printInfo("开始执行命令:{}", command); + if (session == null || !session.isConnected()) { + throw new IllegalStateException("SSH未连接"); + } + ChannelExec channel = null; + BufferedReader reader = null; + try { + // 创建执行命令的通道 + channel = (ChannelExec) session.openChannel("exec"); + channel.setCommand(command); + // 获取输入流以读取命令输出 + InputStream in = channel.getInputStream(); + InputStream err = channel.getExtInputStream(); + channel.connect(); + reader = new BufferedReader(new InputStreamReader(in)); + String data = reader.readLine(); +// log.info("执行命令成功,返回数据:" + data); + BufferedReader errReader = new BufferedReader(new InputStreamReader(err)); + String errData = errReader.readLine(); +// log.info("执行命令失败,返回数据:" + errData); + if (StrUtil.isBlank(errData)) { + return data; + } else { + errReader.close(); + throw new Exception("执行命令失败:" + errData); + } + } finally { + if (channel != null) { + channel.disconnect(); + } + if (reader != null) { + try { + reader.close(); + } catch (Exception ignored) { + } + } + printInfo("执行命令完毕"); + } + } + + /** + * 执行远程命令并返回输出 + */ + public void exec(String command) { + printInfo("开始执行命令:{}", command); + if (session == null || !session.isConnected()) { + throw new IllegalStateException("SSH未连接"); + } + ChannelExec channel = null; + SshResultCallback callback = new SshResultCallback() { + @Override + public void onOutput(String output) { + printInfo(false, output); + } + + @Override + public void onErrorOutput(String errorOutput) { + printError(false, errorOutput); + } + + @Override + public void onCompleted(int exitStatus) { + printInfo("输出完毕,退出状态:" + exitStatus); + } + + @Override + public void onError(Exception e) { + printError(false, e.getMessage()); + } + }; + try { + // 创建执行命令的通道 + channel = (ChannelExec) session.openChannel("exec"); + channel.setCommand(command); + + // 获取输入流以读取命令输出 + InputStream in = channel.getInputStream(); + InputStream err = channel.getExtInputStream(); + + channel.connect(); + + // 读取命令输出 + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + BufferedReader errReader = new BufferedReader(new InputStreamReader(err)); + + String line; + while ((line = reader.readLine()) != null) { + callback.onOutput(line); + } + + // 读取错误输出 + String errLine; + while ((errLine = errReader.readLine()) != null) { + callback.onErrorOutput(errLine); + } + + // 获取退出状态 + int exitStatus = channel.getExitStatus(); + callback.onCompleted(exitStatus); + } catch (JSchException | IOException e) { + callback.onError(e); + } finally { + if (channel != null) { + channel.disconnect(); + } + if (session != null) { + session.disconnect(); + } + printInfo("执行命令完毕"); + } + } + + /** + * 检查远程文件是否存在 + */ + public boolean fileExists(String remotePath) throws SftpException { + try { + channelSftp.stat(remotePath); + return true; + } catch (SftpException e) { + if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { + return false; + } + throw e; + } + } + + /** + * 上传文件 + */ + public void uploadFile(String localPath, String remotePath) throws SftpException { + printInfo("开始上传本地文件{}到远程{}", localPath, remotePath); + channelSftp.put(localPath, remotePath); + printInfo("上传完成"); + } + + /** + * 关闭连接 + */ + public void disconnect() { + if (channelSftp != null) { + channelSftp.disconnect(); + } + if (session != null) { + session.disconnect(); + } + } + } + + public interface SshResultCallback { + void onOutput(String output); + + void onErrorOutput(String errorOutput); + + void onCompleted(int exitStatus); + + void onError(Exception e); + } + + private static void printError(String msg) { + if (StrUtil.isNotBlank(msg)) { + System.out.println(red + msg + reset); + } + } + + private static void printError(boolean addTime, String msg) { + if (addTime) { + System.out.println(red + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + msg + reset); + } else { + System.out.println(red + msg + reset); + } + } + + private static void printInfo(String msg) { + printInfo(true, msg); + } + + private static void printInfo(boolean addTime, String msg) { + if (addTime) { + System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + msg); + } else { + System.out.println(msg); + } + } + + private static void printInfo(String format, Object... args) { + printInfo(true, format, args); + } + + private static void printInfo(boolean addTime, String format, Object... args) { + if (addTime) { + System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " " + StrUtil.format(format, args)); + } else { + System.out.println(StrUtil.format(format, args)); + } + } + + public static final String red = "\u001B[31m"; + public static final String reset = "\u001B[0m"; +} diff --git a/nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeployTest.java b/nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeploySitTest.java similarity index 98% rename from nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeployTest.java rename to nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeploySitTest.java index 00f54ae8..6b678e2b 100644 --- a/nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeployTest.java +++ b/nflg-wms-admin/src/test/java/com/nflg/wms/admin/DeploySitTest.java @@ -16,10 +16,9 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; -import java.util.Vector; @Slf4j -public class DeployTest { +public class DeploySitTest { private static final String serviceName = "admin"; private static final String localPath = System.getProperty("user.dir") + "//target//"; @@ -33,9 +32,9 @@ public class DeployTest { //处理主jar包 handleFile(sshUtil, localPath + jarName, remotePath + jarName); //处理字体目录 - handleDir(sshUtil, localPath, remotePath, "fonts"); +// handleDir(sshUtil, localPath, remotePath, "fonts"); //处理lib目录 - handleDir(sshUtil, localPath, remotePath, "lib"); +// handleDir(sshUtil, localPath, remotePath, "lib"); //执行脚本启动服务 sshUtil.exec("cd " + remotePath + " && ./restart.sh"); sshUtil.disconnect(); @@ -82,7 +81,7 @@ public class DeployTest { } private String getRemoteFileMD5(SSHUtil sshUtil, String remotePath) throws Exception { - String md5 = StrUtil.subPre(sshUtil.execWithReturn("md5sum " + remotePath),32); + String md5 = StrUtil.subPre(sshUtil.execWithReturn("md5sum " + remotePath), 32); printInfo("远程文件MD5为" + md5); return md5; }