package com.nflg.scheduled; import cn.hutool.core.util.StrUtil; import com.jcraft.jsch.*; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; 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; import java.util.Vector; import java.util.concurrent.TimeUnit; @Slf4j public class DeployTest { private static final String serviceName = "scheduled"; 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-" + serviceName + "-1.0.0-SNAPSHOT.jar"; @Test public void DeployToSit() throws JSchException, IOException, SftpException { SSHUtil sshUtil = new SSHUtil(); sshUtil.connect("192.168.163.84", 22, "root", "CMP2025nf"); //处理主jar包 handleFile(sshUtil, localPath + jarName, remotePath + jarName); // //处理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 IOException, SftpException { 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 IOException, SftpException { BasicFileAttributes localFileAttr = Files.readAttributes(Paths.get(localPath), BasicFileAttributes.class); printInfo("处理文件:{},大小:{}", localPath, getSize(localFileAttr.size())); if (sshUtil.fileExists(remotePath)) { int updateTime = sshUtil.getFileUpdateTime(remotePath); // printInfo("本地文件时间:{},远程文件时间:{}",localFileAttr.lastModifiedTime().to(TimeUnit.SECONDS),updateTime); if (localFileAttr.lastModifiedTime().to(TimeUnit.SECONDS) != updateTime) { printError("文件不一致,开始上传"); sshUtil.uploadFile(localPath, remotePath); } else { printInfo("文件一致"); } } else { printError("文件不存在,开始上传"); sshUtil.uploadFile(localPath, remotePath); } printInfo("处理完成"); } 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 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 Long getFileSize(String remotePath) throws SftpException { SftpATTRS attrs = channelSftp.stat(remotePath); return attrs.getSize(); } /** * 获取远程文件大小 */ public int getFileUpdateTime(String remotePath) throws SftpException { SftpATTRS attrs = channelSftp.stat(remotePath); return attrs.getMTime(); } /** * 检查远程文件是否存在 */ 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 ChannelSftp.LsEntry getFileAttributes(String remotePath) throws SftpException { Vector list = channelSftp.ls(remotePath); if (list != null && !list.isEmpty()) { return list.get(0); } return null; } /** * 上传文件 */ 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"; }