package com.tongran.agent.client.utils; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.concurrent.TimeUnit; public class CrontabManager { // // 要添加的定时任务 // private static final String CRON_JOB = "*/10 * * * * /usr/local/tongran/sbin/test2.sh >/dev/null 2>&1"; // // 用于判断是否已存在的关键标识(可以是脚本路径) // private static final String JOB_IDENTIFIER = "/usr/local/tongran/sbin/test2.sh"; /** * 检查并添加定时任务 */ public static boolean ensureCronJobExists(String CRON_JOB, String JOB_IDENTIFIER) { try { // 1. 读取当前用户的 crontab ProcessBuilder pb = new ProcessBuilder("crontab", "-l"); pb.redirectErrorStream(true); Process process = pb.start(); // 设置超时(防止卡死) if (!process.waitFor(5, TimeUnit.SECONDS)) { process.destroy(); throw new IOException("crontab -l timeout"); } StringBuilder crontabContent = new StringBuilder(); try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { crontabContent.append(line).append("\n"); } } int exitCode = process.exitValue(); if (exitCode != 0 && exitCode != 1) { // exit code 1 表示没有 crontab 文件(正常) throw new IOException("crontab -l failed with exit code: " + exitCode); } String content = crontabContent.toString(); // 2. 检查是否已存在该任务 if (content.contains(JOB_IDENTIFIER)) { System.out.println("Crontab 任务已存在,无需添加。"); return true; } // 3. 如果不存在,追加任务 String newCrontab; if (content.trim().isEmpty()) { // 原来没有 crontab newCrontab = CRON_JOB + "\n"; } else { // 原来有 crontab,在末尾添加新任务 newCrontab = content; if (!content.endsWith("\n")) { newCrontab += "\n"; } newCrontab += CRON_JOB + "\n"; } // 4. 写入新的 crontab ProcessBuilder pbWrite = new ProcessBuilder("crontab", "-"); pbWrite.redirectErrorStream(true); Process writeProcess = pbWrite.start(); try (OutputStreamWriter writer = new OutputStreamWriter(writeProcess.getOutputStream())) { writer.write(newCrontab); writer.flush(); } if (!writeProcess.waitFor(5, TimeUnit.SECONDS)) { writeProcess.destroy(); throw new IOException("crontab - write timeout"); } int writeExitCode = writeProcess.exitValue(); if (writeExitCode != 0) { throw new IOException("crontab - write failed with exit code: " + writeExitCode); } System.out.println("Crontab 任务添加成功:\n" + CRON_JOB); return true; } catch (IOException | InterruptedException e) { System.err.println("操作 crontab 失败:" + e.getMessage()); e.printStackTrace(); return false; } } // === 使用示例 === public static void main(String[] args) { // 要添加的定时任务 String CRON_JOB = "*/10 * * * * /usr/local/tongran/sbin/test2.sh >/dev/null 2>&1"; // 用于判断是否已存在的关键标识(可以是脚本路径) String JOB_IDENTIFIER = "/usr/local/tongran/sbin/test2.sh"; // boolean success = ensureCronJobExists(CRON_JOB,JOB_IDENTIFIER); // if (success) { // System.out.println("✅ Crontab 状态正常。"); // } else { // System.err.println("❌ 操作失败,请检查权限或路径。"); // } } /** * 验证当前定时任务中是否包含目标脚本 */ public static boolean isCronEntryExists(String TARGET_SCRIPT) { try { AssertLog.info("验证: 检查当前定时任务是否包含 {}",TARGET_SCRIPT); Process process = Runtime.getRuntime().exec("crontab -l"); BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()) ); String line; while ((line = reader.readLine()) != null) { if (line.contains(TARGET_SCRIPT)) { AssertLog.info("✅ 发现目标脚本在当前定时任务中: {}",line.trim()); reader.close(); return true; } } reader.close(); int exitCode = process.waitFor(); if (exitCode != 0 && exitCode != 1) { // exitCode 1 表示没有 crontab throw new IOException("获取当前 crontab 失败,退出码: " + exitCode); } AssertLog.info("当前定时任务中未找到目标脚本"); return false; }catch (IOException | InterruptedException e) { System.err.println("操作 crontab 失败:" + e.getMessage()); e.printStackTrace(); return false; } } /** * 0. 清空 tr_live.cron 文件内容 */ public static void clearCronFile(String cronDir, String CRON_FILE_PATH) { try { AssertLog.info("步骤0: 清空 {} 文件内容",CRON_FILE_PATH); // 确保目录存在 new File(cronDir).mkdirs(); // 创建空文件(如果不存在)或清空现有内容 Files.write(Paths.get(CRON_FILE_PATH), new byte[0]); AssertLog.info("✅ {} 文件已清空",CRON_FILE_PATH); }catch (IOException e) { System.err.println("操作 crontab 失败:" + e.getMessage()); e.printStackTrace(); } } /** * 1. 备份当前定时任务到文件 */ public static void backupCurrentCrontab(String CRON_FILE_PATH) { try { AssertLog.info("步骤1: 备份当前定时任务到 {}",CRON_FILE_PATH); Process process = Runtime.getRuntime().exec("crontab -l"); BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()) ); // 读取当前 crontab 内容 StringBuilder currentCrontab = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { currentCrontab.append(line).append("\n"); } reader.close(); int exitCode = process.waitFor(); if (exitCode != 0 && exitCode != 1) { // exitCode 1 表示没有 crontab throw new IOException("获取当前 crontab 失败,退出码: " + exitCode); } // 写入当前定时任务内容 Files.write(Paths.get(CRON_FILE_PATH), currentCrontab.toString().getBytes()); AssertLog.info("✅ 当前定时任务已保存到: {}",CRON_FILE_PATH); }catch (IOException | InterruptedException e) { System.err.println("操作 crontab 失败:" + e.getMessage()); e.printStackTrace(); } } /** * 2. 在文件末尾添加新的定时任务 */ public static void appendNewCronEntry(String CRON_FILE_PATH, String NEW_CRON_ENTRY) { try { AssertLog.info("步骤2: 在文件末尾添加新定时任务"); // 检查是否已存在该定时任务 String fileContent = new String(Files.readAllBytes(Paths.get(CRON_FILE_PATH))); if (fileContent.contains(NEW_CRON_ENTRY)) { AssertLog.info("⚠️ 定时任务已存在,跳过添加"); return; } // 添加新定时任务到文件末尾 Files.write( Paths.get(CRON_FILE_PATH), (NEW_CRON_ENTRY + "\n").getBytes(), StandardOpenOption.APPEND ); AssertLog.info("✅ 新定时任务已添加到文件末尾"); }catch (IOException e) { System.err.println("操作 crontab 失败:" + e.getMessage()); e.printStackTrace(); } } /** * 3. 清除当前所有定时任务 */ public static void clearCurrentCrontab() { try { AssertLog.info("步骤3: 清除当前所有定时任务"); // 创建一个空的临时文件 File tempFile = File.createTempFile("empty_cron", ".tmp"); tempFile.deleteOnExit(); // 用空文件替换当前 crontab Process process = Runtime.getRuntime().exec("crontab " + tempFile.getAbsolutePath()); int exitCode = process.waitFor(); if (exitCode != 0) { throw new IOException("清除当前 crontab 失败,退出码: " + exitCode); } AssertLog.info("✅ 当前所有定时任务已清除"); }catch (IOException | InterruptedException e) { System.err.println("操作 crontab 失败:" + e.getMessage()); e.printStackTrace(); } } /** * 4. 重新加载定时任务文件 */ public static void installNewCrontab(String CRON_FILE_PATH) { try { AssertLog.info("步骤4: 加载新的定时任务文件"); // 检查文件是否存在 if (!Files.exists(Paths.get(CRON_FILE_PATH))) { throw new IOException("定时任务文件不存在: " + CRON_FILE_PATH); } // 执行 crontab 命令加载新文件 Process process = Runtime.getRuntime().exec("crontab " + CRON_FILE_PATH); // 读取输出 BufferedReader stdout = new BufferedReader( new InputStreamReader(process.getInputStream()) ); BufferedReader stderr = new BufferedReader( new InputStreamReader(process.getErrorStream()) ); String outputLine; while ((outputLine = stdout.readLine()) != null) { System.out.println("STDOUT: " + outputLine); } String errorLine; while ((errorLine = stderr.readLine()) != null) { System.err.println("STDERR: " + errorLine); } int exitCode = process.waitFor(); if (exitCode != 0) { throw new IOException("加载新 crontab 失败,退出码: " + exitCode); } AssertLog.info("✅ 新定时任务已成功加载"); }catch (IOException | InterruptedException e) { System.err.println("操作 crontab 失败:" + e.getMessage()); e.printStackTrace(); } } /** * 验证最终结果 */ public static void verifyFinalResult(String TARGET_SCRIPT) { try { AssertLog.info("\n--- 验证最终定时任务结果 ---"); Process process = Runtime.getRuntime().exec("crontab -l"); BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()) ); boolean found = false; String line; while ((line = reader.readLine()) != null) { System.out.println(line); if (line.contains(TARGET_SCRIPT)) { AssertLog.info("✅ 确认 " + TARGET_SCRIPT + " 已成功添加到定时任务中"); found = true; } } reader.close(); if (!found) { AssertLog.info("❌ 未在当前定时任务中找到目标脚本"); } } catch (Exception e) { AssertLog.info("验证 crontab 时出错: " + e.getMessage()); } } }