使用shell 发邮件,Concurrent log/output做为附件

本文介绍了一个使用Shell脚本从输入参数中提取请求ID、标志、邮件主题及收件人地址的方法,并根据标志决定复制日志文件或输出文件至指定目录,最后通过邮件发送出去。该脚本适用于系统管理和自动化运维场景。

--截取conc的参数

VL_REQID=`echo $1 | cut -d" " -f9 | cut -d"\"" -f2`  --request id
VL_FLAG=`echo $1 | cut -d" " -f10 | cut -d"\"" -f2` --log/output
VL_MSG=`echo $1 | cut -d"\"" -f12` --title
VL_MAILLIST=`echo $1 | cut -d"\"" -f14` --mail address

echo "Mail Message: " $VL_MSG
echo "Mail List: "$VL_MAILLIST

echo "Error Log/Output file) is sending out via email, request ID: "$VL_REQID
echo "---------------------------------------------------------------------------"

 if test "$VL_FLAG" = "LOG"
 then
   email_filename="l"$VL_REQID".req"
   cp  $APPLCSF/log/$email_filename $C_INBND_DIR/log/$email_filename
 else
   email_filename="o"$VL_REQID".out"
   cp  $APPLCSF/out/$email_filename $C_INBND_DIR/log/$email_filename
 fi
 
 if [ $? -gt 0 ]
 then
   echo "Log/Output file copy unsuccessfully"
 else
   sleep 10
   uuencode $C_INBND_DIR/log/$email_filename $email_filename | mailx -s "$VL_MSG" $VL_MAILLIST
   echo "Log/Output file send out successfully"
 fi
 
 exit 0

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10359218/viewspace-694932/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10359218/viewspace-694932/

package com.duxiaoman.ent.idm.app.utils; import com.duxiaoman.ent.idm.app.config.SparkConfig; import com.duxiaoman.ent.idm.app.model.*; import com.duxiaoman.ent.idm.app.pojo.ShellRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @Slf4j @Component public class SparkCliExecutor { @Autowired private SparkConfig sparkConfig; /** * 执行通用 Shell 命令 * @param shellRequest Shell 命令请求(包含命令列表、超时时间等) * @return 执行结果(统一 QueryResult 格式) */ public QueryResult executeShellCommand(ShellRequest shellRequest) { long startTime = System.currentTimeMillis(); List<String> output = new ArrayList<>(); int exitCode = -1; try { // 1. 校验命令合法性(避免空命令) List<String> command = shellRequest.getCommand(); if (command == null || command.isEmpty()) { String errorMsg = "Shell 命令不能为空"; log.error(errorMsg); return createErrorResult(startTime, output, errorMsg, exitCode); } log.info("开始执行 Shell 命令: {}", String.join(" ", command)); // 2. 构建进程(使用命令列表,避免 Shell 注入) ProcessBuilder processBuilder = new ProcessBuilder(command); // 可选:设置工作目录(若命令需在指定目录执行) if (shellRequest.getWorkDir() != null && !shellRequest.getWorkDir().isEmpty()) { processBuilder.directory(new File(shellRequest.getWorkDir())); log.debug("Shell 命令执行工作目录: {}", shellRequest.getWorkDir()); } // 合并错误流到标准输出(统一捕获日志) processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); // 3. 读取命令输出(异步读取,避免流阻塞) try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { output.add(line); log.debug("Shell 命令输出: {}", line); } } // 4. 超时控制(复用原有逻辑) if (shellRequest.getTimeoutSeconds() != null && shellRequest.getTimeoutSeconds() > 0) { if (!process.waitFor(shellRequest.getTimeoutSeconds(), TimeUnit.SECONDS)) { process.destroyForcibly(); // 强制终止超时进程 String errorMsg = String.format("Shell 命令超时(%d 秒),已强制终止", shellRequest.getTimeoutSeconds()); log.error(errorMsg); return createErrorResult(startTime, output, errorMsg, -1); } } else { process.waitFor(); // 无超时则等待命令执行完成 } // 5. 检查执行结果 exitCode = process.exitValue(); if (exitCode != 0) { String errorMsg = String.format("Shell 命令执行失败,退出码: %d,输出日志: %s", exitCode, String.join("\n", output)); log.error(errorMsg); return createErrorResult(startTime, output, errorMsg, exitCode); } // 6. 执行成功,返回结果 long endTime = System.currentTimeMillis(); log.info("Shell 命令执行成功,耗时: {} ms", (endTime - startTime)); return new QueryResult(true, output, null, null, endTime - startTime, exitCode); } catch (IOException e) { String errorMsg = "Shell 命令执行IO异常: " + e.getMessage(); log.error(errorMsg, e); return createErrorResult(startTime, output, errorMsg, exitCode); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 String errorMsg = "Shell 命令执行被中断: " + e.getMessage(); log.error(errorMsg, e); return createErrorResult(startTime, output, errorMsg, exitCode); } } /** * 执行Hive查询 * @param request 查询请求 * @return 执行结果 */ public QueryResult executeHiveQueryOld(QueryRequest request) { long startTime = System.currentTimeMillis(); List<String> output = new ArrayList<>(); int exitCode = -1; try { // 构建命令 List<String> command = buildCommand(request); log.info("开始执行 hive查询操作: {}", String.join(" ", command)); // 执行命令 ProcessBuilder processBuilder = new ProcessBuilder(command); processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); // 读取输出 try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { output.add(line); log.debug("Spark CLI output: {}", line); } } // 设置超时 if (request.getTimeoutSeconds() != null && request.getTimeoutSeconds() > 0) { if (!process.waitFor(request.getTimeoutSeconds(), TimeUnit.SECONDS)) { process.destroy(); String errorMsg = "hive 查询超时: " + request.getTimeoutSeconds() + " seconds"; log.error(errorMsg); return createErrorResult(startTime, output, errorMsg, -1); } } else { process.waitFor(); } exitCode = process.exitValue(); if (exitCode != 0) { String errorMsg = "Spark CLI execution failed with exit code: " + exitCode; log.error(errorMsg); return createErrorResult(startTime, output, errorMsg, exitCode); } long endTime = System.currentTimeMillis(); log.info("spark 执行成功 执行耗时 in {} ms", (endTime - startTime)); return new QueryResult(true, output, null,null, endTime - startTime, exitCode); } catch (IOException | InterruptedException e) { String errorMsg = "Spark 执行异常: " + e.getMessage(); log.error(errorMsg, e); return createErrorResult(startTime, output, errorMsg, exitCode); } } /** * 执行Hive查询并导出结果到文件 * @param request 导出请求 * @return 执行结果 */ public QueryResult exportHiveQuery(ExportRequest request) { long startTime = System.currentTimeMillis(); List<String> output = new ArrayList<>(); int exitCode = -1; try { // 确保输出目录存在 Path outputPath = Paths.get(request.getOutputPath()); Path parentDir = outputPath.getParent(); if (parentDir != null && !Files.exists(parentDir)) { Files.createDirectories(parentDir); log.info("Created output directory: {}", parentDir); } // 构建导出查询 String exportQuery = buildExportQuery(request); log.info("Export query: {}", exportQuery); // 构建命令 QueryRequest queryRequest = new QueryRequest(); queryRequest.setQuery(exportQuery); queryRequest.setDatabase(request.getDatabase()); queryRequest.setAdditionalConfigs(request.getAdditionalConfigs()); queryRequest.setAdditionalHiveConfigs(request.getAdditionalHiveConfigs()); queryRequest.setTimeoutSeconds(request.getTimeoutSeconds()); queryRequest.setQueue(request.getQueue()); queryRequest.setNumExecutors(request.getNumExecutors()); queryRequest.setExecutorMemory(request.getExecutorMemory()); List<String> command = buildCommand(queryRequest); log.info("Executing Spark CLI export command: {}", String.join(" ", command)); // 执行命令 ProcessBuilder processBuilder = new ProcessBuilder(command); processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); // 读取输出 try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { output.add(line); log.debug("Spark CLI output: {}", line); } } // 设置超时 if (request.getTimeoutSeconds() != null && request.getTimeoutSeconds() > 0) { if (!process.waitFor(request.getTimeoutSeconds(), TimeUnit.SECONDS)) { process.destroy(); String errorMsg = "Export command execution timed out after " + request.getTimeoutSeconds() + " seconds"; log.error(errorMsg); return createErrorResult(startTime, output, errorMsg, -1); } } else { process.waitFor(); } exitCode = process.exitValue(); if (exitCode != 0) { String errorMsg = "Spark CLI export execution failed with exit code: " + exitCode; log.error(errorMsg); return createErrorResult(startTime, output, errorMsg, exitCode); } // 检查输出文件是否存在 if (Files.exists(outputPath)) { long fileSize = Files.size(outputPath); log.info("Export completed successfully. File: {}, Size: {} bytes", request.getOutputPath(), fileSize); } else { log.warn("Export completed but output file does not exist: {}", request.getOutputPath()); } long endTime = System.currentTimeMillis(); log.info("Spark CLI export command executed successfully in {} ms", (endTime - startTime)); return new QueryResult(true, output,null, null, endTime - startTime, exitCode); } catch (IOException | InterruptedException e) { String errorMsg = "Failed to execute Spark CLI export command: " + e.getMessage(); log.error(errorMsg, e); return createErrorResult(startTime, output, errorMsg, exitCode); } } /** * 创建Hive表 * @param request 表创建请求 * @return 执行结果 */ public QueryResult createTable(TableRequest request) { long startTime = System.currentTimeMillis(); try { // 构建创建表的SQL语句 String createTableSql = buildCreateTableSql(request); log.info("Create table SQL: {}", createTableSql); // 构建查询请求 QueryRequest queryRequest = new QueryRequest(); queryRequest.setQuery(createTableSql); queryRequest.setDatabase(request.getDatabase()); queryRequest.setAdditionalConfigs(request.getAdditionalConfigs()); queryRequest.setAdditionalHiveConfigs(request.getAdditionalHiveConfigs()); queryRequest.setTimeoutSeconds(request.getTimeoutSeconds()); queryRequest.setQueue(request.getQueue()); queryRequest.setNumExecutors(request.getNumExecutors()); queryRequest.setExecutorMemory(request.getExecutorMemory()); return executeHiveQuery(queryRequest); } catch (Exception e) { String errorMsg = "Failed to create table: " + e.getMessage(); log.error(errorMsg, e); return createErrorResult(startTime, new ArrayList<>(), errorMsg, -1); } } /** * 导入数据到Hive表 * @param request 导入请求 * @return 执行结果 */ public QueryResult importData(ImportRequest request) { long startTime = System.currentTimeMillis(); try { // 构建导入数据的SQL语句 String importDataSql = buildImportDataSql(request); log.info("Import data SQL: {}", importDataSql); // 构建查询请求 QueryRequest queryRequest = new QueryRequest(); queryRequest.setQuery(importDataSql); queryRequest.setDatabase(request.getDatabase()); queryRequest.setAdditionalConfigs(request.getAdditionalConfigs()); queryRequest.setAdditionalHiveConfigs(request.getAdditionalHiveConfigs()); queryRequest.setTimeoutSeconds(request.getTimeoutSeconds()); queryRequest.setQueue(request.getQueue()); queryRequest.setNumExecutors(request.getNumExecutors()); queryRequest.setExecutorMemory(request.getExecutorMemory()); return executeHiveQuery(queryRequest); } catch (Exception e) { String errorMsg = "Failed to import data: " + e.getMessage(); log.error(errorMsg, e); return createErrorResult(startTime, new ArrayList<>(), errorMsg, -1); } } /** * 构建导出查询语句 */ private String buildExportQuery(ExportRequest request) { StringBuilder queryBuilder = new StringBuilder(); // 如果有指定数据库,先使用数据库 if (request.getDatabase() != null && !request.getDatabase().isEmpty()) { queryBuilder.append("USE ").append(request.getDatabase()).append("; "); } // 构建导出语句 queryBuilder.append("INSERT OVERWRITE DIRECTORY '") .append(request.getOutputPath()) .append("' "); // 根据格式设置ROW FORMAT switch (request.getFormat().toLowerCase()) { case "csv": queryBuilder.append("ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' "); break; case "tsv": queryBuilder.append("ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t' "); break; case "json": queryBuilder.append("ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe' "); break; case "parquet": // Parquet格式不需要指定ROW FORMAT queryBuilder.append("STORED AS PARQUET "); break; default: throw new IllegalArgumentException("Unsupported export format: " + request.getFormat()); } // 添加SELECT查询 queryBuilder.append("SELECT * FROM (") .append(request.getQuery()) .append(") tmp"); return queryBuilder.toString(); } /** * 构建创建表的SQL语句 */ private String buildCreateTableSql(TableRequest request) { StringBuilder sqlBuilder = new StringBuilder(); // 如果有指定数据库,先使用数据库 if (request.getDatabase() != null && !request.getDatabase().isEmpty()) { sqlBuilder.append("USE ").append(request.getDatabase()).append("; "); } // 添加创建表语句 sqlBuilder.append("CREATE TABLE "); // 添加表名 if (request.getDatabase() != null && !request.getDatabase().isEmpty()) { sqlBuilder.append(request.getDatabase()).append("."); } sqlBuilder.append(request.getTableName()).append(" "); // 添加表定义 sqlBuilder.append(request.getCreateStatement()).append(" "); // 添加表位置 if (request.getLocation() != null && !request.getLocation().isEmpty()) { sqlBuilder.append("LOCATION '").append(request.getLocation()).append("' "); } // 添加表属性 if (request.getTableProperties() != null && !request.getTableProperties().isEmpty()) { sqlBuilder.append("TBLPROPERTIES ("); boolean first = true; for (Map.Entry<String, String> entry : request.getTableProperties().entrySet()) { if (!first) { sqlBuilder.append(", "); } sqlBuilder.append("'").append(entry.getKey()).append("'='").append(entry.getValue()).append("'"); first = false; } sqlBuilder.append(")"); } return sqlBuilder.toString(); } /** * 构建导入数据的SQL语句 */ private String buildImportDataSql(ImportRequest request) { StringBuilder sqlBuilder = new StringBuilder(); // 如果有指定数据库,先使用数据库 if (request.getDatabase() != null && !request.getDatabase().isEmpty()) { sqlBuilder.append("USE ").append(request.getDatabase()).append("; "); } // 添加导入数据语句 if (Boolean.TRUE.equals(request.getOverwrite())) { sqlBuilder.append("INSERT OVERWRITE TABLE "); } else { sqlBuilder.append("INSERT INTO TABLE "); } // 添加表名 if (request.getDatabase() != null && !request.getDatabase().isEmpty()) { sqlBuilder.append(request.getDatabase()).append("."); } sqlBuilder.append(request.getTableName()).append(" "); // 根据格式选择不同的加载方式 switch (request.getFormat().toLowerCase()) { case "csv": sqlBuilder.append("ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' "); break; case "tsv": sqlBuilder.append("ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t' "); break; case "json": sqlBuilder.append("ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe' "); break; case "parquet": // Parquet格式不需要指定ROW FORMAT break; default: throw new IllegalArgumentException("Unsupported import format: " + request.getFormat()); } sqlBuilder.append("STORED AS TEXTFILE ") .append("LOCATION '").append(request.getInputPath()).append("'"); return sqlBuilder.toString(); } /** * 构建Spark CLI命令 */ private List<String> buildCommand(QueryRequest request) { List<String> command = new ArrayList<>(); // 添加Spark客户端路径 command.add(sparkConfig.getBeelinePath()); // 添加Spark提交参数 addParam(command, "--master", sparkConfig.getMaster()); addParam(command, "--deploy-mode", sparkConfig.getDeployMode()); // 使用请求中的队列或默认配置 String queue = request.getQueue() != null ? request.getQueue() : sparkConfig.getQueue(); addParam(command, "--queue", queue); // 使用请求中的执行器数量或默认配置 int numExecutors = request.getNumExecutors() != null ? request.getNumExecutors() : sparkConfig.getNumExecutors(); addParam(command, "--num-executors", String.valueOf(numExecutors)); addParam(command, "--executor-cores", String.valueOf(sparkConfig.getExecutorCores())); // 使用请求中的执行器内存或默认配置 String executorMemory = request.getExecutorMemory() != null ? request.getExecutorMemory() : sparkConfig.getExecutorMemory(); addParam(command, "--executor-memory", executorMemory); addParam(command, "--driver-memory", sparkConfig.getDriverMemory()); // 添加Spark配置 if (sparkConfig.getConf() != null) { for (Map.Entry<String, String> entry : sparkConfig.getConf().entrySet()) { addConfParam(command, entry.getKey(), entry.getValue()); } } // 添加Hive配置 if (sparkConfig.getHiveConf() != null) { for (Map.Entry<String, String> entry : sparkConfig.getHiveConf().entrySet()) { addHiveConfParam(command, entry.getKey(), entry.getValue()); } } // 添加额外的Spark配置 if (request.getAdditionalConfigs() != null) { for (Map.Entry<String, String> entry : request.getAdditionalConfigs().entrySet()) { addConfParam(command, entry.getKey(), entry.getValue()); } } // 添加额外的Hive配置 if (request.getAdditionalHiveConfigs() != null) { for (Map.Entry<String, String> entry : request.getAdditionalHiveConfigs().entrySet()) { addHiveConfParam(command, entry.getKey(), entry.getValue()); } } // 添加Jars if (sparkConfig.getJars() != null && !sparkConfig.getJars().isEmpty()) { addParam(command, "--jars", sparkConfig.getJars()); } // 添加查询 command.add("-e"); command.add(escapeQuery(request.getQuery())); return command; } /** * 添加配置参数到命令 */ private void addParam(List<String> command, String key, String value) { if (value != null && !value.isEmpty()) { command.add(key); command.add(value); } } /** * 添加Spark配置参数 */ private void addConfParam(List<String> command, String key, String value) { if (value != null && !value.isEmpty()) { command.add("--conf"); command.add(key + "=" + value); } } /** * 添加Hive配置参数 */ private void addHiveConfParam(List<String> command, String key, String value) { if (value != null && !value.isEmpty()) { command.add("--hiveconf"); command.add(key + "=" + value); } } /** * 转义查询语句 */ private String escapeQuery(String query) { // 根据需要进行转义处理 return query; // return "\"" + query.replace("\"", "\\\"") + "\""; } /** * 创建错误结果 */ private QueryResult createErrorResult(long startTime, List<String> output, String errorMessage, int exitCode) { return new QueryResult(false, output,null, errorMessage, System.currentTimeMillis() - startTime, exitCode); } public QueryResult executeHiveQuery(QueryRequest request) { long startTime = System.currentTimeMillis(); List<String> output = new ArrayList<>(); int exitCode = -1; try { List<String> command = buildCommand(request); log.info("开始执行 hive查询操作: {}", String.join(" ", command)); ProcessBuilder processBuilder = new ProcessBuilder(command); processBuilder.redirectErrorStream(true); // 创建ShellRequest用于重试逻辑 ShellRequest shellRequest = new ShellRequest(); shellRequest.setCommand(command); shellRequest.setTimeoutSeconds(request.getTimeoutSeconds()); // 使用带重试的执行方法 return executeWithRetry(processBuilder, shellRequest, "Hive查询"); } catch (Exception e) { String errorMsg = "Spark 执行异常: " + e.getMessage(); log.error(errorMsg, e); return createErrorResult(startTime, output, errorMsg, exitCode); } } /** * 带重试的执行方法 */ private QueryResult executeWithRetry(ProcessBuilder processBuilder, ShellRequest shellRequest, String operationType) { int maxRetries = 2; // 最大重试次数 int totalAttempts = maxRetries + 1; // 总尝试次数 long startTm = System.currentTimeMillis(); for (int attempt = 0; attempt < totalAttempts; attempt++) { boolean isLastAttempt = (attempt == totalAttempts - 1); Process process = null; List<String> output = new ArrayList<>(); int exitCode = -1; try { log.info("开始执行 {} 操作,第 {} 次尝试(共 {} 次)", operationType, attempt + 1, totalAttempts); long attemptStartTm = System.currentTimeMillis(); // 如果是重试尝试,进行连接检查和等待 if (attempt > 0) { // 检查连接健康状态 if (!checkConnectionHealth()) { log.warn("连接不健康,重置连接状态"); resetConnection(); } // 重试前等待(指数退避) int waitTime = 2000 * attempt; log.info("重试前等待 {} ms", waitTime); Thread.sleep(waitTime); } // 启动进程 process = processBuilder.start(); // 读取输出流 try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { output.add(line); if (log.isDebugEnabled()) { log.debug("{} 输出: {}", operationType, line); } } } // 设置超时控制 boolean finished; if (shellRequest.getTimeoutSeconds() != null && shellRequest.getTimeoutSeconds() > 0) { finished = process.waitFor(shellRequest.getTimeoutSeconds(), TimeUnit.SECONDS); if (!finished) { process.destroyForcibly(); String errorMsg = String.format("%s 超时(%d 秒),已强制终止", operationType, shellRequest.getTimeoutSeconds()); if (!isLastAttempt) { log.warn("超时失败,准备重试"); continue; // 继续重试 } else { return createErrorResult(startTm, output, errorMsg, -1); } } } else { process.waitFor(); // 无超时则等待命令执行完成 } // 获取退出码 exitCode = process.exitValue(); // 检查执行结果 if (exitCode != 0) { String errorMsg = String.format("%s 执行失败,退出码: %d", operationType, exitCode); if (!isLastAttempt) { log.warn("执行失败,准备重试"); continue; // 继续重试 } else { return createErrorResult(startTm, output, errorMsg + ",输出日志: " + String.join("\n", output), exitCode); } } // 执行成功,返回结果 long endTime = System.currentTimeMillis(); log.info("{} 执行成功,第 {} 次尝试成功,耗时: {} ms", operationType, attempt + 1, (endTime - attemptStartTm)); // 标记连接健康 connectionHealthy = true; lastHealthCheckTime = System.currentTimeMillis(); return new QueryResult(true, output, null, null, endTime - startTm, exitCode); } catch (IOException e) { String errorMsg = String.format("%s IO异常: %s", operationType, e.getMessage()); if (isLastAttempt) { return createErrorResult(startTm, output, String.format("%s 执行失败,所有 %d 次尝试均失败: %s", operationType, totalAttempts, errorMsg), exitCode); } log.warn("第 {} 次尝试IO异常,准备重试: {}", attempt + 1, e.getMessage()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); String errorMsg = String.format("%s 执行被中断: %s", operationType, e.getMessage()); return createErrorResult(startTm, output, errorMsg, exitCode); } finally { // 确保进程被清理 if (process != null && process.isAlive()) { process.destroy(); try { // 等待进程完全终止 process.waitFor(5, TimeUnit.SECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); log.warn("进程清理等待被中断"); } } } // 记录重试间隔(非最后一次尝试) log.info("第 {} 次尝试失败,等待下一次重试", attempt + 1); } // 理论上不会执行到这里,但为了安全 return createErrorResult(startTm, new ArrayList<>(), String.format("%s 执行失败,未知错误", operationType), -1); } /** * 处理进程执行结果 */ private QueryResult processResult(Process process, String operationType, long startTime, List<String> output) throws InterruptedException { int exitCode = process.exitValue(); if (exitCode != 0) { String errorMsg = String.format("%s 执行失败,退出码: %d", operationType, exitCode); log.error(errorMsg); throw new RuntimeException(errorMsg); } long endTime = System.currentTimeMillis(); log.info("{} 执行成功,耗时: {} ms", operationType, (endTime - startTime)); // 标记连接健康 connectionHealthy = true; lastHealthCheckTime = System.currentTimeMillis(); return new QueryResult(true, output, null, null, endTime - startTime, exitCode); } // 添加连接状态监控 private volatile boolean connectionHealthy = true; private long lastHealthCheckTime = 0; private static final long HEALTH_CHECK_INTERVAL = 300000; // 5分钟检查一次 /** * 检查连接健康状态 */ private boolean checkConnectionHealth() { long currentTime = System.currentTimeMillis(); if (currentTime - lastHealthCheckTime > HEALTH_CHECK_INTERVAL) { try { // 执行简单的测试命令检查连接 List<String> testCommand = Arrays.asList( sparkConfig.getBeelinePath(), "-e", "show databases;" ); ProcessBuilder pb = new ProcessBuilder(testCommand); Process process = pb.start(); // 读取输出避免阻塞 try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { while (reader.readLine() != null) { // 消费输出 } } boolean success = process.waitFor(30, TimeUnit.SECONDS); connectionHealthy = (success && process.exitValue() == 0); lastHealthCheckTime = currentTime; log.info("连接健康检查: {}", connectionHealthy ? "健康" : "异常"); } catch (Exception e) { log.error("连接健康检查失败", e); connectionHealthy = false; } } return connectionHealthy; } /** * 重置连接状态 */ private void resetConnection() { connectionHealthy = false; lastHealthCheckTime = 0; // 可以添加一些清理操作,比如清理临时文件等 try { // 执行一些清理命令(可选) List<String> cleanupCommand = Arrays.asList( sparkConfig.getBeelinePath(), "-e", "!q" ); ProcessBuilder pb = new ProcessBuilder(cleanupCommand); Process process = pb.start(); process.waitFor(5, TimeUnit.SECONDS); } catch (Exception e) { log.debug("连接重置清理操作执行异常(可忽略)", e); } log.info("连接状态已重置"); } } package com.duxiaoman.ent.idm.app.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import java.util.Map; @Data @Configuration @ConfigurationProperties(prefix = "spark") public class SparkConfig { // Spark提交参数 private String master = "yarn"; private String deployMode = "client"; private String queue = "fintech"; private int numExecutors = 150; private int executorCores = 2; private String executorMemory = "8G"; private String driverMemory = "10G"; // Spark配置参数 private Map<String, String> conf; // Hive配置参数 private Map<String, String> hiveConf; // Jars路径 private String jars; // Beeline路径 private String beelinePath = "/home/work/software/cloud-hadoop-client/dxm-spark-beeline/bin/beeline"; // hadoop路径 private String hadoopExecutablePath = "/home/work/software/cloud-hadoop-client/hadoop-client/bin/hadoop"; private String hdfsCmdPath = "/home/work/software/cloud-hadoop-client/hadoop-client/bin/hdfs"; // HdfsPath private String downloadHdfsPath = "dgs://baihua/user/fsg_rcc_fintech_datamining_rd/warehouse/dxm_idm_sample"; // 默认导出目录 private String defaultExportDir = "/home/work/localfile/hive_exports"; // 默认导入目录 private String defaultImportDir = "/home/work/localfile/hive_imports/"; // 输出文件格式 private String format = "csv"; // 是否文件上传至bos地址 private boolean ifUploadToBOS = false; // 默认数据库 private String defaultDatabase = "dxm_idm_sample"; // 临时表前缀 private String tableNameTmpPrefix = "tmp_phone_only_"; // 建表字段语句 private String createTableStatementTmp = "(serial_num BIGINT,index_col STRING, name_col STRING,idcard_col STRING,phone_col STRING,date_for STRING)"; // 查询SQL模板 private String querysqlTmp = "SELECT s.index_col AS index_col ,s.name_col AS name_col ,s.idcard_col AS idcard_col ,s.phone_col AS phone_col ,s.date_for AS date_for ,'' AS panshi_birthProvince ,'-1' AS panshi_dxm_birthCitylevel_zone ,m.work_citylevel AS panshi_dxm_workCitylevel ,'' AS panshi_unionid ,m.work_citylevel_zone AS panshi_dxm_workCitylevel_zone ,'' AS panshi_sex ,'-1' AS panshi_dxm_workcity2ndtier_age ,m.phone_isp AS panshi_dxm_phone_isp ,'-1' AS panshi_dxm_birthCitylevel ,'-1' AS panshi_dxm_workOutBirthzone_flag ,m.city_code AS panshi_dxm_citycode ,'' AS panshi_xid ,m.xid_phone AS panshi_xid_phone ,'-1' AS panshi_dxm_workOutBirthcity_flag ,'-1' AS panshi_dxm_workcity1stier_age ,'-1' AS panshi_dxm_workcity3rdtier_age ,'-1' AS panshi_dxm_workOutBirthpro_flag ,'' AS panshi_age,m.md5 AS dxm_md5_phone FROM ${dataBaseName}.${tableName} AS s LEFT JOIN dxm_idm.dim_jk_idm_phone_mapping_s AS m ON s.phone_col = m.${encryptType} ORDER BY s.serial_num "; } 【com.dxm.inf.mmr.client.util.KyuubiManagerApi.getCluterConfig(KyuubiManagerApi.java:29) - get config is error . resp is {"code":0,"data":null,"msg":"集群: 配置不存在"}】 项目启动一段时间后,失效报错,重启java项目后,可正常, 告诉我原理是什么,解决思路,关键修改点
09-25
这个是完整源码 python实现 Django 【python毕业设计】基于Python的天气预报(天气预测分析)(Django+sklearn机器学习+selenium爬虫)可视化系统.zip 源码+论文+sql脚本 完整版 数据库是mysql 本研究旨在开发一个基于Python的天气预报可视化系统,该系统结合了Django框架、sklearn机器学习库和Selenium爬虫技术,实现对天气数据的收集、分析和可视化。首先,我们使用Selenium爬虫技术从多个天气数据网站实时抓取气象数据,包括温度、湿度、气压、风速等多项指标。这些数据经过清洗和预处理后本研究旨在开发一个基于Python的天气预报可视化系统,该系统结合了Django框架、sklearn机器学习库和Selenium爬虫技术,实现对天气数据的收集、分析和可视化。首先,我们使用Selenium爬虫技术从多个天气数据网站实时抓取气象数据,包括温度、湿度、气压、风速等多项指标。这些数据经过清洗和预处理后,将其存储在后端数据库中,以供后续分析。 其次,采用s,将其存储在后端数据库中,以供后续分析。 其次,采用sklearn机器学习库构建预测模型,通过时间序列分析和回归方法,对未来天气情况进行预测。我们利用以往的数据训练模型,以提高预测的准确性。通过交叉验证和超参数优化等技术手段,我们优化了模型性能,确保其在实际应用中的有效性和可靠性。 最后,基于Django框架开发前端展示系统,实现天气预报的可视化。用户可以通过友好的界面查询实时天气信息和未来几天内的天气预测。系统还提供多种图表类型,包括折线图和柱状图,帮助用户直观理解天气变化趋势。 本研究的成果为天气预报领域提供了一种新的技术解决方案,不仅增强了数据获取和处理的效率,还提升了用户体验。未来,该系统能够扩展至其他气象相关的应用场景,为大众提供更加准确和及时的气象服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值