From b0844986b6a598d5b8945198ce1dc69a8f3236f6 Mon Sep 17 00:00:00 2001 From: shenym3 Date: Thu, 14 Dec 2023 17:51:07 +0800 Subject: [PATCH] =?UTF-8?q?[fix]:[][=E9=9D=99=E6=80=81=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E4=BF=AE=E6=94=B9]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jeesite/modules/util/BuildLogUtils.java | 121 +++++++++ .../com/jeesite/modules/util/ExecScript.java | 238 ++++++++++++++++++ 2 files changed, 359 insertions(+) create mode 100644 src/main/java/com/jeesite/modules/util/BuildLogUtils.java create mode 100644 src/main/java/com/jeesite/modules/util/ExecScript.java diff --git a/src/main/java/com/jeesite/modules/util/BuildLogUtils.java b/src/main/java/com/jeesite/modules/util/BuildLogUtils.java new file mode 100644 index 0000000..7f94c40 --- /dev/null +++ b/src/main/java/com/jeesite/modules/util/BuildLogUtils.java @@ -0,0 +1,121 @@ +package com.asiainfo.ai.mirror.util; + +import com.asiainfo.mlp.common.core.exception.resource.ResourceNotFoundException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.MediaType; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +/** + * 构建日志读取工具类 + */ +@Slf4j +public final class BuildLogUtils { + + public static SseEmitter getInitSse() { + return new SseEmitter(1000000L); + } + + /** + * 通过sse动态获取日志内容 + * + * @param filePath 文件路径 + * @param sseEmitter sse + * @return SseEmitter + */ + public static SseEmitter getBuildLogBySse(String filePath, SseEmitter sseEmitter) { + // 超时时间设置为1000s + File logFile = new File(filePath); + //定义文件读取的上次位置 + AtomicLong lastTimeFileSize = new AtomicLong(); + //设置线程定时读取日志文件 + ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); + try { + executorService.scheduleWithFixedDelay(() -> { + RandomAccessFile randomFile; + //指定文件可读可写 + try { + randomFile = new RandomAccessFile(logFile, "rw"); + } catch (FileNotFoundException e) { + log.error("日志文件路径={}的文件不存在", filePath, e); + throw new ResourceNotFoundException("构建过程日志文件 ", filePath); + } + try { + //移动文件指针位置 + randomFile.seek(lastTimeFileSize.get()); + } catch (IOException e) { + log.error("日志文件路径={}的文件移动指针位置出现异常", filePath, e); + throw new ResourceNotFoundException("构建过程日志文件移动指针位置出现异常", filePath); + } + String content; + while (true) { + try { + if ((content = randomFile.readLine()) == null) { + break; + } + } catch (IOException e) { + log.error("日志文件路径={}的文件读取出现异常", filePath, e); + throw new RuntimeException("构建过程日志文件读取出现异常"); + } + content = new String(content.getBytes(StandardCharsets.ISO_8859_1)); + try { + sseEmitter.send(content, MediaType.APPLICATION_JSON); + } catch (IOException e) { + log.error("日志文件路径={}的文件发送到前端出现异常", filePath, e); + throw new RuntimeException("日志文件发送到前端出现异常"); + } + + //构建结束标识(成功/失败) + if (StringUtils.containsAny(content, "镜像构建失败", "镜像构建流程结束")) { + try { + sseEmitter.send(SseEmitter.event().name("finish").data("finish")); + } catch (IOException e) { + log.error("日志文件路径={}的文件发送结束事件出现异常", filePath, e); + throw new RuntimeException("日志文件发送结束事件到前端出现异常"); + } + executorService.shutdown(); + sseEmitter.complete(); + } + } + try { + lastTimeFileSize.set(randomFile.length()); + } catch (IOException e) { + log.error("获取日志文件路径={}的文件长度出现异常", filePath, e); + throw new RuntimeException("获取日志文件的文件长度出现异常"); + } + try { + randomFile.close(); + } catch (IOException e) { + log.error("日志文件路径={}的文件读取关闭时出现异常", filePath, e); + throw new RuntimeException("日志文件读取关闭时出现异常"); + } + }, 0, 10, TimeUnit.SECONDS); + } catch (Exception e) { + log.error("查询日志出现异常", e); + //出现异常关闭线程池和服务发送事件 + executorService.shutdown(); + sseEmitter.completeWithError(e); + throw new RuntimeException("查询日志出现异常"); + } + + //设置超时回调 + sseEmitter.onTimeout(() -> { + executorService.shutdown(); + log.warn("日志文件路径={}的文件日志查询超时", filePath); + }); + //设置查询完成回调 + sseEmitter.onCompletion(() -> log.info("日志文件路径={}的文件日志查询完成", filePath)); + return sseEmitter; + } + +} diff --git a/src/main/java/com/jeesite/modules/util/ExecScript.java b/src/main/java/com/jeesite/modules/util/ExecScript.java new file mode 100644 index 0000000..2b0d25c --- /dev/null +++ b/src/main/java/com/jeesite/modules/util/ExecScript.java @@ -0,0 +1,238 @@ +package com.asiainfo.ai.mirror.util; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.util.Scanner; +import java.util.concurrent.TimeUnit; + + +/*** + * linux脚本运行 + * + * @author xiaopu + * + */ + +public class ExecScript { + + private static final Logger log = LoggerFactory.getLogger(ExecScript.class); + public static String run(String command) throws IOException { + Scanner input = null; + Process process = null; + String result = ""; + try { + log.info("ExecScript-------->run----------->{}:{}", command); + process = Runtime.getRuntime().exec(command); + + try { + // 标准输入流(必须写在 waitFor 之前) + // String inStr = consumeInputStream(process.getInputStream()); + + // log.info("ExecScript-------->run----------->InputStream:{}",inStr); + // 标准错误流(必须写在 waitFor 之前) + // String errStr = consumeInputStream(process.getErrorStream()); + // log.info("ExecScript-------->run----------->ErrorStream:{}",errStr); + // 获取进程的标准输入流 + InputStream is1 = process.getInputStream(); + // 获取进城的错误流 + InputStream is2 = process.getErrorStream(); + + new Thread() { + public void run() { + BufferedReader br1 = new BufferedReader(new InputStreamReader(is1)); + try { + String line1 = null; + while ((line1 = br1.readLine()) != null) { + if (line1 != null) { + log.info("ExecScript-------->run----------->InputStream:{}", line1); + } + } + } + catch (IOException e) { + log.info("ExecScript-------->run----------->InputStream ERROR:", e); + } + finally { + try { + is1.close(); + } + catch (IOException e) { + log.info("ExecScript-------->run----------->ErrorStream ERROR:", e); + } + } + } + }.start(); + + new Thread() { + public void run() { + BufferedReader br2 = new BufferedReader(new InputStreamReader(is2)); + try { + String line2; + while ((line2 = br2.readLine()) != null) { + //fixbug: [PRDAI_ISSUE_721] 问题修复:已知为非空值的冗余nullcheck + if (StringUtils.isNotBlank(line2)) { + log.info("ExecScript-------->run----------->ErrorStream:{}", line2); + } + } + } + catch (IOException e) { + log.info("ExecScript-------->run----------->ErrorStream ERROR:", e); + } + finally { + try { + is2.close(); + } + catch (IOException e) { + log.info("ExecScript-------->run----------->ErrorStream ERROR:", e); + } + } + } + }.start(); + + // 等待命令执行完成 + process.waitFor(); + } + catch (InterruptedException e) { + log.info("ExecScript-------->run----------->异常:", e); + return ""; + } + InputStream is = process.getInputStream(); + input = new Scanner(is); + while (input.hasNextLine()) { + result += input.nextLine() + "\n"; + } + result = command + "\n" + result; // 加上命令本身,打印出来 + log.info("ExecScript-------->run----------->SH执行结果:{}", result); + } + finally { + if (input != null) { + input.close(); + } + if (process != null) { + process.destroy(); + } + } + return result; + } + + /** + * 消费inputstream,并返回 + * + * @throws IOException + */ + public static String consumeInputStream(InputStream is) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String s; + StringBuilder sb = new StringBuilder(); + while ((s = br.readLine()) != null) { + // System.out.println(s); + sb.append(s); + } + return sb.toString(); + } + + public static String run(String command, long timeOut) throws IOException { + log.info("ExecScript-------->run----------->{}:{}", command, timeOut); + Scanner input = null; + String result = ""; + Process process = null; + try { + process = Runtime.getRuntime().exec(command); + try { + // 等待命令执行完成 + process.waitFor(timeOut, TimeUnit.SECONDS); + } + catch (InterruptedException e) { + log.info("ExecScript-------->run----------->异常:", e); + return ""; + } + InputStream is = process.getInputStream(); + input = new Scanner(is); + while (input.hasNextLine()) { + result += input.nextLine() + "\n"; + } + result = command + "\n" + result; // 加上命令本身,打印出来 + log.info("ExecScript-------->run----------->SH执行结果:{}", result); + } + finally { + if (input != null) { + input.close(); + } + if (process != null) { + process.destroy(); + } + } + return result; + } + + public static String run(String[] command, File file, long timeOut) throws IOException { + log.info("ExecScript-------->run----------->{}:{}", command, timeOut); + Scanner input = null; + String result = ""; + Process process = null; + try { + process = Runtime.getRuntime().exec(command, null, file); + try { + // 等待命令执行完成 + process.waitFor(timeOut, TimeUnit.SECONDS); + } + catch (InterruptedException e) { + log.info("ExecScript-------->run----------->异常:", e); + return ""; + } + InputStream is = process.getInputStream(); + input = new Scanner(is); + while (input.hasNextLine()) { + result += input.nextLine() + "\n"; + } + result = command + "\n" + result; // 加上命令本身,打印出来 + log.info("ExecScript-------->run----------->SH执行结果:{}", result); + } + finally { + if (input != null) { + input.close(); + } + if (process != null) { + process.destroy(); + } + } + return result; + } + + public static String run(String[] command, long timeOut) throws IOException { + log.info("ExecScript-------->run----------->{}:{}", command, timeOut); + Scanner input = null; + String result = ""; + Process process = null; + try { + process = Runtime.getRuntime().exec(command); + try { + // 等待命令执行完成 + process.waitFor(timeOut, TimeUnit.SECONDS); + } + catch (InterruptedException e) { + log.info("ExecScript-------->run----------->异常:", e); + return ""; + } + InputStream is = process.getInputStream(); + input = new Scanner(is); + while (input.hasNextLine()) { + result += input.nextLine() + "\n"; + } + result = command + "\n" + result; // 加上命令本身,打印出来 + log.info("ExecScript-------->run----------->SH执行结果:{}", result); + } + finally { + if (input != null) { + input.close(); + } + if (process != null) { + process.destroy(); + } + } + return result; + } + +} -- Gitee