diff --git a/client+/neutrino-proxy-client-starter/Dockerfile b/client+/neutrino-proxy-client-starter/Dockerfile index e2a41943..bfa84f56 100644 --- a/client+/neutrino-proxy-client-starter/Dockerfile +++ b/client+/neutrino-proxy-client-starter/Dockerfile @@ -9,7 +9,7 @@ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN mkdir -p /root/neutrino-proxy/config WORKDIR /root/neutrino-proxy COPY ./target/neutrino-proxy-client.jar /root/neutrino-proxy/neutrino-proxy-client.jar -COPY ./src/main/resources/app-copy.yml /root/neutrino-proxy/config/app.yml +COPY src/main/resources/app-copy.yml /root/neutrino-proxy/config/app.yml #VOLUME ["/root/neutrino-proxy"] ENTRYPOINT ["java","-jar","neutrino-proxy-client.jar","config=./config/app.yml"] diff --git a/client+/neutrino-proxy-client-starter/pom.xml b/client+/neutrino-proxy-client-starter/pom.xml index 9c2a34ba..ae6e3488 100644 --- a/client+/neutrino-proxy-client-starter/pom.xml +++ b/client+/neutrino-proxy-client-starter/pom.xml @@ -4,8 +4,9 @@ 4.0.0 io.github.javpower neutrino-proxy-client-spring-boot-starter - ${revision} - jar + 2.0.1 + neutrino-proxy-client-spring-boot-starter + a tool about easy neutrino-proxy-client https://github.com/javpower/neutrino-proxy @@ -28,7 +29,7 @@ - 2.3.2 + 2.3.2 2.7.13 2.0.1 @@ -67,12 +68,6 @@ lombok 1.18.30 - - net.dreamlu - mica-auto - ${mica-auto.vaersion} - provided - com.jcraft @@ -84,7 +79,12 @@ jzlib 1.1.3 - + + net.dreamlu + mica-auto + ${mica-auto.version} + provided + @@ -116,9 +116,20 @@ maven-compiler-plugin 3.8.1 - 21 - 21 - UTF-8 + 8 + 8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + true + + @@ -126,7 +137,7 @@ spring-boot-maven-plugin ${spring-boot.version} - com.gc.easy.EasyHttpApplication + org.dromara.neutrinoproxy.client.starter.SpringProxyClient true @@ -197,5 +208,4 @@ - diff --git a/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/ssh/Test.java b/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/ssh/Test.java deleted file mode 100644 index 6ef517de..00000000 --- a/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/ssh/Test.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.dromara.neutrinoproxy.client.starter.ssh; -/** - * - * @author: gc.x - * @date: 2024/1/21 - */ -public class Test { - public static void main(String[] args) { - - // 添加SSH连接 - String sshId = SSHConnectionFactory.factory.addConnection("194.36.209.398", "root", "xxxxxx", 1234, 6379,"xx.xx.xx.xx"); - SSHConnectionFactory.factory.openTunnel(sshId); - try { - Thread.sleep(100000000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - // 关闭SSH隧道 - SSHConnectionFactory.factory.closeTunnel(sshId); - - } -} diff --git a/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/util/RemoteDeployUtil.java b/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/util/RemoteDeployUtil.java new file mode 100644 index 00000000..380ca75b --- /dev/null +++ b/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/util/RemoteDeployUtil.java @@ -0,0 +1,139 @@ +package org.dromara.neutrinoproxy.client.starter.util; + +import com.jcraft.jsch.*; +import lombok.extern.slf4j.Slf4j; + +import java.io.*; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +/** + * 远程发布工具类 + * @author: gc.x + * @date: 2024/1/21 + */ +@Slf4j +public class RemoteDeployUtil { + + public static void uploadAndStartJar(List localFilePaths, String remoteDirectory, String remoteStartCommand, + String remoteUsername, String remoteHost, String remotePassword) { + log.info("Start================="); + JSch jsch = new JSch(); + Session session = null; + ChannelSftp channelSftp = null; + try { + session = jsch.getSession(remoteUsername, remoteHost, 22); + session.setPassword(remotePassword); + session.setConfig("StrictHostKeyChecking", "no"); + session.connect(); + channelSftp = (ChannelSftp) session.openChannel("sftp"); + channelSftp.connect(); + // 创建远程目录(如果不存在) + try { + channelSftp.cd(remoteDirectory); + } catch (SftpException e) { + channelSftp.mkdir(remoteDirectory); + channelSftp.cd(remoteDirectory); + } + // 上传本地文件到远程服务器指定目录 + for (String localFilePath : localFilePaths) { + uploadFileWithProgress(channelSftp, localFilePath, remoteDirectory); + } + channelSftp.disconnect(); + // 执行远程命令启动jar包 + log.info("Command:"+remoteStartCommand); + ChannelExec channelExec = (ChannelExec) session.openChannel("exec"); + channelExec.setCommand(remoteStartCommand); + ByteArrayOutputStream commandOutput = new ByteArrayOutputStream(); + channelExec.setOutputStream(commandOutput); + channelExec.connect(); + // 使用新线程读取并打印命令输出 + Thread outputThread = new Thread(() -> { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(channelExec.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + outputThread.start(); + // 等待命令执行完成 + while (!channelExec.isClosed()) { + Thread.sleep(1000); + } + // 等待命令输出线程结束 + outputThread.join(); + channelExec.disconnect(); + log.info("=================End"); + } catch (JSchException | SftpException | InterruptedException | IOException e) { + e.printStackTrace(); + } finally { + if (channelSftp != null) { + channelSftp.disconnect(); + } + if (session != null) { + session.disconnect(); + } + } + } + + private static void uploadFileWithProgress(ChannelSftp channelSftp, String localFilePath, String remoteDirectory) throws SftpException, IOException { + File file = new File(localFilePath); + String fileName = file.getName(); + String remoteFilePath = remoteDirectory + File.separator + fileName; + AtomicLong uploadedSize = new AtomicLong(); + try (InputStream inputStream = new FileInputStream(file)) { + // 如果远程目录已经存在同名文件,则先备份原文件 + if (fileExists(channelSftp, remoteFilePath)) { + backupRemoteFile(channelSftp, remoteFilePath); + } + channelSftp.put(inputStream, remoteFilePath, new SftpProgressMonitor() { + @Override + public void init(int op, String src, String dest, long max) { + // 初始化回调函数,可以做一些准备工作 + } + @Override + public void end() { + // 上传结束回调函数,可以做一些清理工作 + } + @Override + public boolean count(long count) { + uploadedSize.addAndGet(count); + // 计算上传进度 + int progress = (int) ((uploadedSize.get() * 100) / file.length()); + + // 每上传 10% 显示一次进度,可根据实际情况调整 + if (progress % 10 == 0) { + log.info(fileName+"-----Upload progress: " + progress + "%"); + } + // 返回 true 则继续传输,否则中止传输 + return true; + } + }, ChannelSftp.RESUME); + } + } + + private static boolean fileExists(ChannelSftp channelSftp, String remoteFilePath) { + try { + channelSftp.lstat(remoteFilePath); + return true; + } catch (SftpException e) { + return false; + } + } + + private static void backupRemoteFile(ChannelSftp channelSftp, String remoteFilePath) throws SftpException { + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String backupTime = now.format(formatter); + String backupFilePath = remoteFilePath + "." + backupTime; + channelSftp.rename(remoteFilePath, backupFilePath); + log.info("Remote file already exists. Backing up the original file as: " + backupFilePath); + } +} + + + diff --git a/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/util/SSHClient.java b/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/util/SSHClient.java new file mode 100644 index 00000000..aad352dc --- /dev/null +++ b/client+/neutrino-proxy-client-starter/src/main/java/org/dromara/neutrinoproxy/client/starter/util/SSHClient.java @@ -0,0 +1,122 @@ +package org.dromara.neutrinoproxy.client.starter.util; + +import com.jcraft.jsch.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Paths; +import java.util.Scanner; +/** + * 简易ssh客户端 + * @author: gc.x + * @date: 2024/1/21 + */ +public class SSHClient { + + private static final String COMMAND_UPLOAD = "upload"; + private Session session; + + public void connect(String remoteHost, String remoteUsername, String remotePassword) { + JSch jsch = new JSch(); + try { + session = jsch.getSession(remoteUsername, remoteHost, 22); + session.setPassword(remotePassword); + session.setConfig("StrictHostKeyChecking", "no"); + session.connect(); + System.out.println("Connected to " + remoteHost); + } catch (JSchException e) { + e.printStackTrace(); + } + } + public void startShell() { + if (session == null || !session.isConnected()) { + System.out.println("Not connected to a remote host"); + return; + } + Channel channel; + try { + channel = session.openChannel("shell"); + channel.connect(); + Scanner scanner = new Scanner(System.in); + String line; + while (true) { + System.out.print("$ "); + line = scanner.nextLine(); + if (line.equals("exit")) { + break; + } else if (line.startsWith(COMMAND_UPLOAD)) { + processUploadCommand(line); + } else { + System.out.println("Executing command: " + line); + executeCommand(line); + } + } + } catch (JSchException e) { + e.printStackTrace(); + }finally { + disconnect(); + } + } + + public void disconnect() { + if (session != null && session.isConnected()) { + session.disconnect(); + System.out.println("Disconnected from remote host"); + } + } + + private void processUploadCommand(String command) { + String[] parts = command.split("\\s+"); + if (parts.length < 3) { + System.out.println("Invalid upload command"); + return; + } + String localFilePath = parts[1]; + String remoteDirectory = parts[2]; + String remoteFilename = Paths.get(localFilePath).getFileName().toString(); + if (parts.length >= 4) { + remoteFilename = parts[3]; + } + uploadFile(localFilePath, remoteDirectory, remoteFilename); + } + + private void uploadFile(String localFilePath, String remoteDirectory, String remoteFilename) { + ChannelSftp channelSftp = null; + try { + channelSftp = (ChannelSftp) session.openChannel("sftp"); + channelSftp.connect(); + channelSftp.cd(remoteDirectory); + System.out.println("Uploading file: " + localFilePath + " to: " + remoteDirectory + "/" + remoteFilename); + channelSftp.put(localFilePath, remoteFilename); + System.out.println("File uploaded successfully"); + } catch (JSchException | SftpException e) { + e.printStackTrace(); + } finally { + if (channelSftp != null) { + channelSftp.disconnect(); + } + } + } + private void executeCommand(String command) { + ChannelExec channelExec = null; + + try { + channelExec = (ChannelExec) session.openChannel("exec"); + channelExec.setCommand(command); + BufferedReader in = new BufferedReader(new InputStreamReader(channelExec.getInputStream())); + channelExec.connect(); + String line; + while ((line = in.readLine()) != null) { + System.out.println(line); + } + channelExec.disconnect(); + } catch (JSchException | IOException e) { + e.printStackTrace(); + } finally { + if (channelExec != null) { + channelExec.disconnect(); + } + } + } +} diff --git a/client+/neutrino-proxy-client-starter/src/main/resources/test.jks b/client+/neutrino-proxy-client-starter/src/main/resources/test.jks index 3a4d1ad8..e69de29b 100644 Binary files a/client+/neutrino-proxy-client-starter/src/main/resources/test.jks and b/client+/neutrino-proxy-client-starter/src/main/resources/test.jks differ