|
|
|
@ -0,0 +1,152 @@
|
|
|
|
|
package com.dsideal.YunXiaoTools;
|
|
|
|
|
|
|
|
|
|
import com.jfinal.kit.PropKit;
|
|
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
public class MySQLBackup {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 执行MySQL备份
|
|
|
|
|
*/
|
|
|
|
|
public String backup() {
|
|
|
|
|
// 获取配置
|
|
|
|
|
String host = getHostFromJdbcUrl(PropKit.get("read.jdbcUrl"));
|
|
|
|
|
String port = getPortFromJdbcUrl(PropKit.get("read.jdbcUrl"));
|
|
|
|
|
String database = getDatabaseFromJdbcUrl(PropKit.get("read.jdbcUrl"));
|
|
|
|
|
String username = PropKit.get("read.user");
|
|
|
|
|
String password = PropKit.get("read.password");
|
|
|
|
|
|
|
|
|
|
// 生成备份文件名
|
|
|
|
|
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
|
|
|
|
String backupFileName = database + "_" + timestamp + ".sql";
|
|
|
|
|
|
|
|
|
|
// 创建临时目录
|
|
|
|
|
String tempDir = System.getProperty("java.io.tmpdir");
|
|
|
|
|
String backupPath = tempDir + File.separator + backupFileName;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 获取mysqldump路径
|
|
|
|
|
String mysqldumpPath = getMySQLDumpPath();
|
|
|
|
|
|
|
|
|
|
// 构建命令(不包含密码)
|
|
|
|
|
ProcessBuilder pb = new ProcessBuilder(
|
|
|
|
|
mysqldumpPath,
|
|
|
|
|
"-h" + host,
|
|
|
|
|
"-P" + port,
|
|
|
|
|
"-u" + username,
|
|
|
|
|
"--skip-ssl", // 禁用SSL
|
|
|
|
|
"--no-tablespaces", // 避免权限问题
|
|
|
|
|
"--default-character-set=utf8",
|
|
|
|
|
"--single-transaction",
|
|
|
|
|
"--routines",
|
|
|
|
|
"--triggers",
|
|
|
|
|
"--events",
|
|
|
|
|
"--complete-insert",
|
|
|
|
|
"--add-drop-database",
|
|
|
|
|
"--add-drop-table",
|
|
|
|
|
database,
|
|
|
|
|
"-r",
|
|
|
|
|
backupPath
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 设置环境变量传递密码
|
|
|
|
|
pb.environment().put("MYSQL_PWD", password);
|
|
|
|
|
|
|
|
|
|
// 执行备份命令
|
|
|
|
|
Process process = pb.start();
|
|
|
|
|
|
|
|
|
|
// 读取错误输出
|
|
|
|
|
StringBuilder errorOutput = new StringBuilder();
|
|
|
|
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
|
|
|
|
|
String line;
|
|
|
|
|
while ((line = reader.readLine()) != null) {
|
|
|
|
|
errorOutput.append(line).append("\n");
|
|
|
|
|
System.out.println("备份进度: " + line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 等待命令执行完成
|
|
|
|
|
int exitCode = process.waitFor();
|
|
|
|
|
if (exitCode == 0) {
|
|
|
|
|
System.out.println("数据库备份成功: " + backupPath);
|
|
|
|
|
return backupPath;
|
|
|
|
|
} else {
|
|
|
|
|
throw new RuntimeException("数据库备份失败,错误信息:\n" + errorOutput.toString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new RuntimeException("备份过程出错: " + e.getMessage(), e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取mysqldump路径
|
|
|
|
|
*/
|
|
|
|
|
private String getMySQLDumpPath() {
|
|
|
|
|
try {
|
|
|
|
|
String resourcePath = PropKit.get("mysqldump_path");
|
|
|
|
|
// 处理路径中的空格和特殊字符
|
|
|
|
|
if (resourcePath.startsWith("/")) {
|
|
|
|
|
resourcePath = resourcePath.substring(1);
|
|
|
|
|
}
|
|
|
|
|
// URL解码
|
|
|
|
|
return java.net.URLDecoder.decode(resourcePath, "UTF-8");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new RuntimeException("获取mysqldump路径失败", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从JDBC URL中提取主机地址
|
|
|
|
|
*/
|
|
|
|
|
private String getHostFromJdbcUrl(String jdbcUrl) {
|
|
|
|
|
String[] parts = jdbcUrl.split("://")[1].split(":");
|
|
|
|
|
return parts[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从JDBC URL中提取端口号
|
|
|
|
|
*/
|
|
|
|
|
private String getPortFromJdbcUrl(String jdbcUrl) {
|
|
|
|
|
String[] parts = jdbcUrl.split("://")[1].split(":");
|
|
|
|
|
return parts[1].split("/")[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从JDBC URL中提取数据库名
|
|
|
|
|
*/
|
|
|
|
|
private String getDatabaseFromJdbcUrl(String jdbcUrl) {
|
|
|
|
|
try {
|
|
|
|
|
// 使用正则表达式匹配数据库名
|
|
|
|
|
Pattern pattern = Pattern.compile("jdbc:mysql://[^/]+/(\\w+)\\??.*");
|
|
|
|
|
Matcher matcher = pattern.matcher(jdbcUrl);
|
|
|
|
|
if (matcher.find()) {
|
|
|
|
|
return matcher.group(1);
|
|
|
|
|
}
|
|
|
|
|
throw new RuntimeException("无法从JDBC URL中提取数据库名: " + jdbcUrl);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new RuntimeException("解析数据库名失败: " + jdbcUrl, e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
PropKit.use("application.properties");
|
|
|
|
|
try {
|
|
|
|
|
MySQLBackup backup = new MySQLBackup();
|
|
|
|
|
String backupFile = backup.backup();
|
|
|
|
|
System.out.println("备份文件已生成: " + backupFile);
|
|
|
|
|
|
|
|
|
|
// 如果需要,可以进一步将文件上传到OBS
|
|
|
|
|
// ... 上传代码 ...
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
System.err.println("备份失败: " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|