| | |
| | | /** |
| | | * 任务超时时间(秒) |
| | | */ |
| | | private static final int TASK_TIMEOUT_SECONDS = 300; // 5分钟 |
| | | private static final int TASK_TIMEOUT_SECONDS = 60; // 1分钟 |
| | | |
| | | /** |
| | | * 私有构造函数,防止外部实例化 |
| | |
| | | // 2. 生成唯一容器名称 |
| | | String containerName = CONTAINER_NAME_PREFIX + System.currentTimeMillis(); |
| | | |
| | | // 3. 清理旧容器 |
| | | // 3. 轻量级清理旧容器(可选,如果不需要可以注释掉) |
| | | cleanupOldContainers(); |
| | | |
| | | // 4. 构建Docker命令 |
| | | String command = MessageFormat.format(docx2pdfPath, profile, fileName); |
| | | // 4. 构建Docker命令(确保包含容器名称) |
| | | String command = buildDockerCommand(docx2pdfPath, profile, fileName, containerName); |
| | | log.info("docker执行命令:{}", command); |
| | | |
| | | // 5. 执行Docker命令(带超时) |
| | |
| | | } |
| | | |
| | | /** |
| | | * 构建Docker命令,确保包含容器名称 |
| | | * @param docx2pdfPath docker命令模板路径 |
| | | * @param profile 配置文件路径 |
| | | * @param fileName 文件名 |
| | | * @param containerName 容器名称 |
| | | * @return 完整的Docker命令 |
| | | */ |
| | | private String buildDockerCommand(String docx2pdfPath, String profile, String fileName, String containerName) { |
| | | // 如果命令模板中已经包含 --name 参数,则直接使用 |
| | | if (docx2pdfPath.contains("--name")) { |
| | | return MessageFormat.format(docx2pdfPath, profile, fileName); |
| | | } |
| | | |
| | | // 如果命令模板中没有 --name 参数,则添加容器名称 |
| | | // 假设命令模板格式为: docker run [其他参数] image_name |
| | | // 我们需要在 docker run 后添加 --name 参数 |
| | | |
| | | String baseCommand = MessageFormat.format(docx2pdfPath, profile, fileName); |
| | | |
| | | // 检查是否包含 docker run |
| | | if (baseCommand.contains("docker run")) { |
| | | // 在 docker run 后插入 --name 参数 |
| | | String[] parts = baseCommand.split("docker run", 2); |
| | | if (parts.length == 2) { |
| | | return "docker run --name " + containerName + parts[1]; |
| | | } |
| | | } |
| | | |
| | | // 如果无法解析,则直接返回原命令 |
| | | log.warn("无法解析Docker命令模板,使用原始命令: {}", baseCommand); |
| | | return baseCommand; |
| | | } |
| | | |
| | | /** |
| | | * 获取文件锁 |
| | | */ |
| | | private FileLock acquireFileLock() { |
| | |
| | | } |
| | | |
| | | /** |
| | | * 清理旧容器 |
| | | * 清理旧容器(轻量级版本) |
| | | */ |
| | | private void cleanupOldContainers() { |
| | | try { |
| | | // 查找并停止所有相关容器 |
| | | String findCommand = "docker ps -a --filter name=" + CONTAINER_NAME_PREFIX + "* --format '{{.Names}}'"; |
| | | // 只清理停止状态的容器,不干扰运行中的容器 |
| | | String findCommand = "docker ps -a --filter name=" + CONTAINER_NAME_PREFIX + "* --filter status=exited --format '{{.Names}}'"; |
| | | Process findProc = Runtime.getRuntime().exec(findCommand); |
| | | |
| | | BufferedReader reader = new BufferedReader(new InputStreamReader(findProc.getInputStream())); |
| | | String containerName; |
| | | boolean hasCleaned = false; |
| | | |
| | | while ((containerName = reader.readLine()) != null) { |
| | | if (!containerName.trim().isEmpty()) { |
| | | log.info("清理旧容器: {}", containerName); |
| | | log.info("清理已停止的旧容器: {}", containerName); |
| | | |
| | | // 停止容器 |
| | | String stopCommand = "docker stop " + containerName; |
| | | Runtime.getRuntime().exec(stopCommand); |
| | | |
| | | // 删除容器 |
| | | // 删除已停止的容器 |
| | | String rmCommand = "docker rm " + containerName; |
| | | Runtime.getRuntime().exec(rmCommand); |
| | | hasCleaned = true; |
| | | } |
| | | } |
| | | |
| | | reader.close(); |
| | | findProc.waitFor(10, TimeUnit.SECONDS); |
| | | findProc.waitFor(5, TimeUnit.SECONDS); |
| | | |
| | | if (!hasCleaned) { |
| | | log.debug("没有发现需要清理的旧容器"); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | log.warn("清理旧容器时出现异常", e); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 强制终止进程 |
| | | * 强制终止进程并销毁相关容器 |
| | | */ |
| | | private void forceKillProcess(Process proc) { |
| | | try { |
| | |
| | | log.warn("强制终止进程"); |
| | | } |
| | | } |
| | | |
| | | // 强制清理所有相关容器 |
| | | forceCleanupContainers(); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("强制终止进程失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 强制清理所有相关容器 |
| | | */ |
| | | private void forceCleanupContainers() { |
| | | try { |
| | | log.info("开始强制清理相关容器..."); |
| | | |
| | | // 清理带有特定前缀的容器 |
| | | cleanupContainersByPrefix(); |
| | | |
| | | // 清理可能残留的headless-wps容器(基于镜像名称) |
| | | cleanupContainersByImage("headless-wps-example"); |
| | | |
| | | log.info("容器强制清理完成"); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("强制清理容器失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据前缀清理容器 |
| | | */ |
| | | private void cleanupContainersByPrefix() { |
| | | try { |
| | | // 查找所有运行中的相关容器 |
| | | String runningCommand = "docker ps --filter name=" + CONTAINER_NAME_PREFIX + "* --format '{{.Names}}'"; |
| | | Process runningProc = Runtime.getRuntime().exec(runningCommand); |
| | | BufferedReader runningReader = new BufferedReader(new InputStreamReader(runningProc.getInputStream())); |
| | | |
| | | String containerName; |
| | | while ((containerName = runningReader.readLine()) != null) { |
| | | if (!containerName.trim().isEmpty()) { |
| | | log.warn("强制停止运行中的容器: {}", containerName); |
| | | |
| | | // 强制停止容器 |
| | | String killCommand = "docker kill " + containerName; |
| | | Process killProc = Runtime.getRuntime().exec(killCommand); |
| | | killProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | // 强制删除容器 |
| | | String rmCommand = "docker rm -f " + containerName; |
| | | Process rmProc = Runtime.getRuntime().exec(rmCommand); |
| | | rmProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | log.info("已强制清理容器: {}", containerName); |
| | | } |
| | | } |
| | | runningReader.close(); |
| | | runningProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | // 查找所有停止的相关容器并删除 |
| | | String stoppedCommand = "docker ps -a --filter name=" + CONTAINER_NAME_PREFIX + "* --format '{{.Names}}'"; |
| | | Process stoppedProc = Runtime.getRuntime().exec(stoppedCommand); |
| | | BufferedReader stoppedReader = new BufferedReader(new InputStreamReader(stoppedProc.getInputStream())); |
| | | |
| | | while ((containerName = stoppedReader.readLine()) != null) { |
| | | if (!containerName.trim().isEmpty()) { |
| | | log.warn("强制删除停止的容器: {}", containerName); |
| | | |
| | | // 强制删除容器 |
| | | String rmCommand = "docker rm -f " + containerName; |
| | | Process rmProc = Runtime.getRuntime().exec(rmCommand); |
| | | rmProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | log.info("已强制删除容器: {}", containerName); |
| | | } |
| | | } |
| | | stoppedReader.close(); |
| | | stoppedProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("根据前缀清理容器失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据镜像名称清理容器 |
| | | */ |
| | | private void cleanupContainersByImage(String imageName) { |
| | | try { |
| | | log.info("清理镜像为 {} 的容器", imageName); |
| | | |
| | | // 查找所有运行中的相关容器 |
| | | String runningCommand = "docker ps --filter ancestor=" + imageName + " --format '{{.Names}}'"; |
| | | Process runningProc = Runtime.getRuntime().exec(runningCommand); |
| | | BufferedReader runningReader = new BufferedReader(new InputStreamReader(runningProc.getInputStream())); |
| | | |
| | | String containerName; |
| | | while ((containerName = runningReader.readLine()) != null) { |
| | | if (!containerName.trim().isEmpty()) { |
| | | log.warn("强制停止运行中的容器: {}", containerName); |
| | | |
| | | // 强制停止容器 |
| | | String killCommand = "docker kill " + containerName; |
| | | Process killProc = Runtime.getRuntime().exec(killCommand); |
| | | killProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | // 强制删除容器 |
| | | String rmCommand = "docker rm -f " + containerName; |
| | | Process rmProc = Runtime.getRuntime().exec(rmCommand); |
| | | rmProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | log.info("已强制清理容器: {}", containerName); |
| | | } |
| | | } |
| | | runningReader.close(); |
| | | runningProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | // 查找所有停止的相关容器并删除 |
| | | String stoppedCommand = "docker ps -a --filter ancestor=" + imageName + " --format '{{.Names}}'"; |
| | | Process stoppedProc = Runtime.getRuntime().exec(stoppedCommand); |
| | | BufferedReader stoppedReader = new BufferedReader(new InputStreamReader(stoppedProc.getInputStream())); |
| | | |
| | | while ((containerName = stoppedReader.readLine()) != null) { |
| | | if (!containerName.trim().isEmpty()) { |
| | | log.warn("强制删除停止的容器: {}", containerName); |
| | | |
| | | // 强制删除容器 |
| | | String rmCommand = "docker rm -f " + containerName; |
| | | Process rmProc = Runtime.getRuntime().exec(rmCommand); |
| | | rmProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | log.info("已强制删除容器: {}", containerName); |
| | | } |
| | | } |
| | | stoppedReader.close(); |
| | | stoppedProc.waitFor(10, TimeUnit.SECONDS); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("根据镜像清理容器失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 清理资源 |
| | | */ |
| | | private void cleanupResources(Process proc, FileLock lock) { |