diff --git a/ds-build/pom.xml b/ds-build/pom.xml index 62b2a16e..cae7337a 100644 --- a/ds-build/pom.xml +++ b/ds-build/pom.xml @@ -45,5 +45,18 @@ log4j ${log4j.version} + + + + com.github.mwiede + jsch + 0.2.19 + + + + com.alibaba + fastjson + ${fastjson.version} + diff --git a/ds-build/src/main/java/Util/PublishUtil.java b/ds-build/src/main/java/Util/PublishUtil.java new file mode 100644 index 00000000..a1c3d5dc --- /dev/null +++ b/ds-build/src/main/java/Util/PublishUtil.java @@ -0,0 +1,126 @@ +package Util; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.ZipUtil; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.jfinal.kit.Kv; +import com.jfinal.kit.PathKit; +import com.jfinal.kit.StrKit; + +import java.io.File; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class PublishUtil { + /** + * 删除本机所有Docker镜像 + * docker images --format "{{.Repository}}:{{.Tag}}" | xargs -r docker rmi -f + *

+ * 登录远程仓库 + * 方法1: + * docker login -u 驿来特充电 -p ylt5033. registry.cn-hangzhou.aliyuncs.com + * 方法2: + * docker login --username=驿来特充电 --password=ylt5033. registry.cn-hangzhou.aliyuncs.com + *

+ * # 搜索 + * docker search registry.cn-hangzhou.aliyuncs.com/yltcharge/zhu-que:20240903 + *

+ * #拉取 + * docker pull registry.cn-hangzhou.aliyuncs.com/yltcharge/zhu-que:20240903 + */ + public static void publish(String projectName) throws Exception { + System.out.println("正在生成" + projectName + "的镜像..."); + //配置文件 + String path = PathKit.getRootClassPath() + "\\publishImage.json"; + JSONObject jo = JSONObject.parseObject(FileUtil.readUtf8String(path)); + //主机 + String host = jo.getString("host"); + String user = jo.getString("user"); + String pwd = jo.getString("pwd"); + int port = jo.getIntValue("port"); + JSONArray ja = jo.getJSONArray("project"); + + String workingPath = null, remotePath = null, localLibPath = null; + + for (Object o : ja) { + JSONObject project = (JSONObject) o; + String p = project.getString("projectName"); + if (p.equals(projectName)) { + workingPath = project.getString("workingPath"); + remotePath = project.getString("remotePath"); + localLibPath = project.getString("localLibPath"); + break; + } + } + + //声明SSH对象 + SSHUtil ssh = new SSHUtil(user, pwd, host, port); + ssh.connect(); + + // 格式化日期 + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String newVersion = now.format(formatter); + newVersion = newVersion.replace(" ", "").replace("-", "").replace(":", ""); + + //准备工作 + ssh.exec("rm -rf " + remotePath); + + System.out.println("正在上传Dockerfile..."); + ssh.upload(workingPath + "/Dockerfile", "/usr/local/" + projectName + "/Dockerfile"); + + + if (!StrKit.isBlank(localLibPath)) { + System.out.println("正在创建lib目录..."); + ssh.mkdir("/usr/local/" + projectName + "/lib"); + ssh.mkdir(remotePath); + //遍历lib目录下的文件 + for (File file : FileUtil.loopFiles(localLibPath)) { + System.out.println("正在上传jar包:" + file.getName()); + ssh.upload(file.getAbsolutePath(), remotePath + "/lib/" + file.getName()); + } + } + //打包target为zip + String localFile = workingPath + "/target.zip"; + if (FileUtil.exist(localFile)) { + FileUtil.del(localFile); + } + System.out.println("正在上传target.zip..."); + // 将目录打包成ZIP文件,不包含目录本身,只包含目录下的文件和子目录 + ZipUtil.zip(workingPath + "/target", localFile, true); + //上传 + ssh.upload(localFile, remotePath + "/target.zip"); + //删除target.zip + FileUtil.del(localFile); + //解压缩 + System.out.println("正在解压缩target.zip..."); + ssh.exec("cd " + remotePath + " && unzip target.zip"); + ssh.exec("cd " + remotePath + " && rm -rf target.zip"); + + + //打包 + System.out.println("开始打包镜像,稍等...."); + String cmd = "cd /usr/local/" + projectName + " && docker build -t " + projectName + ":" + newVersion + " ."; + ssh.exec(cmd); + System.out.println(cmd); + //获取最新打包后的镜像ID + cmd = "docker images --format \"{{.Repository}} {{.Tag}} {{.ID}} {{.CreatedAt}}\" | grep " + projectName + " | sort -k4,5 -r | head -n1 | awk '{print $3}'"; + Kv kv = ssh.exec(cmd); + String imageId = kv.getStr("message").replace("[", "").replace("]", ""); + System.out.println("镜像打包完成,镜像ID=" + imageId); + + System.out.println("打标签..."); + cmd = "docker tag " + imageId + " registry.cn-hangzhou.aliyuncs.com/yltcharge/" + projectName + ":" + newVersion; + ssh.exec(cmd); + +// System.out.println("开始推送到远程仓库,稍等..."); +// cmd = "docker push registry.cn-hangzhou.aliyuncs.com/yltcharge/" + projectName + ":" + newVersion; +// ssh.exec(cmd); +// +// System.out.println("推送到远程仓库完成!"); + + ssh.disconnect(); + System.out.println("恭喜,镜像打包成功!"); + } +} diff --git a/ds-build/src/main/java/Util/SSHUtil.java b/ds-build/src/main/java/Util/SSHUtil.java new file mode 100644 index 00000000..93390a8e --- /dev/null +++ b/ds-build/src/main/java/Util/SSHUtil.java @@ -0,0 +1,270 @@ +package Util; + +import com.jcraft.jsch.*; +import com.jfinal.kit.Kv; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +public class SSHUtil { + private static Logger log = LoggerFactory.getLogger(SSHUtil.class); + + private String charset = "UTF-8"; // 设置编码格式 + private String user; // 用户名 + private String passwd; // 登录密码 + private String host; // 主机IP + private int port = 22; //默认端口 + private JSch jsch; + private Session session; + + private ChannelSftp sftp; + + /** + * @param user 用户名 + * @param passwd 密码 + * @param host 主机IP + */ + public SSHUtil(String user, String passwd, String host) { + this.user = user; + this.passwd = passwd; + this.host = host; + } + + /** + * @param user 用户名 + * @param passwd 密码 + * @param host 主机IP + */ + public SSHUtil(String user, String passwd, String host, int port) { + this.user = user; + this.passwd = passwd; + this.host = host; + this.port = port; + } + + /** + * 连接到指定的IP + * + * @throws JSchException + */ + public void connect() throws JSchException { + jsch = new JSch(); + session = jsch.getSession(user, host, port); + session.setPassword(passwd); + java.util.Properties config = new java.util.Properties(); + config.put("StrictHostKeyChecking", "no"); + session.setConfig(config); + session.connect(600); + Channel channel = session.openChannel("sftp"); + channel.connect(600); + sftp = (ChannelSftp) channel; + log.info("连接到SFTP成功。host: " + host); + } + + /** + * 关闭连接 + */ + public void disconnect() { + if (sftp != null && sftp.isConnected()) { + sftp.disconnect(); + } + if (session != null && session.isConnected()) { + session.disconnect(); + } + } + + /** + * 执行一条命令 + */ + public Kv exec(String command) throws Exception { + Kv kv = Kv.create(); + int returnCode = -1; + BufferedReader reader; + Channel channel; + + channel = session.openChannel("exec"); + ((ChannelExec) channel).setCommand(command); + channel.setInputStream(null); + ((ChannelExec) channel).setErrStream(System.err); + InputStream in = channel.getInputStream(); + reader = new BufferedReader(new InputStreamReader(in));//中文乱码貌似这里不能控制,看连接的服务器的 + + channel.connect(); + // System.out.println("The remote command is: " + command); + String buf; + List strList = new ArrayList<>(); + while ((buf = reader.readLine()) != null) { + System.out.println(buf); + strList.add(buf); + } + kv.set("message", strList.toString()); + reader.close(); + // Get the return code only after the channel is closed. + if (channel.isClosed()) { + returnCode = channel.getExitStatus(); + } + channel.disconnect(); + kv.set("returnCode", returnCode); + return kv; + } + + /** + * 执行相关的命令 + */ + public void exec() { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + String command = ""; + BufferedReader reader = null; + Channel channel = null; + try { + while ((command = br.readLine()) != null) { + channel = session.openChannel("exec"); + ((ChannelExec) channel).setCommand(command); + channel.setInputStream(null); + ((ChannelExec) channel).setErrStream(System.err); + + channel.connect(); + InputStream in = channel.getInputStream(); + reader = new BufferedReader(new InputStreamReader(in, + Charset.forName(charset))); + String buf = null; + while ((buf = reader.readLine()) != null) { + System.out.println(buf); + } + } + } catch (IOException e) { + e.printStackTrace(); + } catch (JSchException e) { + e.printStackTrace(); + } finally { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + channel.disconnect(); + } + } + + /** + * 上传文件 + */ + public void upload(String local, String remote) throws Exception { + File file = new File(local); + if (file.isDirectory()) { + throw new RuntimeException(local + " is not a file"); + } + InputStream inputStream = null; + try { + String rpath = remote.substring(0, remote.lastIndexOf("/") + 1); + if (!isDirExist(rpath)) { + mkdir(rpath); + } + inputStream = new FileInputStream(file); + sftp.setInputStream(inputStream); + sftp.put(inputStream, remote); + } catch (Exception e) { + throw e; + } finally { + if (inputStream != null) { + inputStream.close(); + } + } + } + + /** + * 下载文件 + */ + public void downloadFile(String remote, String local) throws Exception { + OutputStream outputStream = null; + try { + sftp.connect(5000); + outputStream = new FileOutputStream(new File(local)); + sftp.get(remote, outputStream); + outputStream.flush(); + } catch (Exception e) { + throw e; + } finally { + if (outputStream != null) { + outputStream.close(); + } + } + } + + /** + * 移动到相应的目录下 + * + * @param pathName 要移动的目录 + * @return + */ + public boolean changeDir(String pathName) { + if (pathName == null || pathName.trim().equals("")) { + log.debug("invalid pathName"); + return false; + } + try { + sftp.cd(pathName.replaceAll("\\\\", "/")); + log.debug("directory successfully changed,current dir=" + sftp.pwd()); + return true; + } catch (SftpException e) { + log.error("failed to change directory", e); + return false; + } + } + + /** + * 创建一个文件目录,mkdir每次只能创建一个文件目录 + * 或者可以使用命令mkdir -p 来创建多个文件目录 + */ + public void mkdir(String createpath) { + try { + if (isDirExist(createpath)) { + sftp.cd(createpath); + return; + } + String pathArry[] = createpath.split("/"); + StringBuffer filePath = new StringBuffer("/"); + for (String path : pathArry) { + if (path.equals("")) { + continue; + } + filePath.append(path + "/"); + if (isDirExist(filePath.toString())) { + sftp.cd(filePath.toString()); + } else { + // 建立目录 + sftp.mkdir(filePath.toString()); + // 进入并设置为当前目录 + sftp.cd(filePath.toString()); + } + } + sftp.cd(createpath); + } catch (SftpException e) { + throw new RuntimeException("创建路径错误:" + createpath); + } + } + + + /** + * 判断目录是否存在 + * + * @param directory + * @return + */ + public boolean isDirExist(String directory) { + boolean isDirExistFlag = false; + try { + SftpATTRS sftpATTRS = sftp.lstat(directory); + return sftpATTRS.isDir(); + } catch (Exception e) { + if (e.getMessage().equalsIgnoreCase("no such file")) { + isDirExistFlag = false; + } + } + return isDirExistFlag; + } +}