文章目录
- 概要
- 1、查看mysql版本
- 2、相关依赖
- 3、具体代码
- 技术细节
概要
Springboot执行shell命令备份数据库。
1、查看mysql版本
mysql --version
2、相关依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.20</version>
</dependency>
3、具体代码
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.time.LocalDate;
import org.springframework.core.io.ResourceLoader;@Component
@Slf4j
public class BackupJob {//数据库连接地址@Value("${spring.datasource.url}")private String dbUrl;//数据库名@Value("${spring.datasource.name}")private String dbName;//用户名@Value("${spring.datasource.username}")private String dbUserName;//密码@Value("${spring.datasource.password}")private String dbPassWord;//存放路径@Value("${backup.path}")private String filePath;// 在你的类中注入ResourceLoader,用来获取备份的sql文件@Autowiredprivate ResourceLoader resourceLoader;/*** 数据库版本是否为 8.0 + (false=否 true=是), mysql8+ 需要参数 --column-statistics=0 , mysql8- 不需要* 新版的mysqldump默认启用了一个新标志,通过--column-statistics=0来禁用*/boolean isDbVersion8 = true;@SneakyThrowspublic void backup() {log.info("【备份数据库】--START");String dbUrl2 = dbUrl.replace("jdbc:mysql://", "");// 获取数据库地址String[] serverPath = dbUrl2.substring(0, dbUrl2.indexOf("/")).split(":");String ip = serverPath[0];String port = serverPath[1];// 数据库账号String username = dbUserName;// 数据库密码String password = dbPassWord;String dbParam = "";// 备份文件目录+名称 备份文件存放目录+名称(名称 = 数据库名+时间字符串.sql)String timeStr = LocalDate.now().toString();String pathFileName = filePath + dbName + "_" + timeStr + ".sql";String newCmd = "mysqldump -h{SERVER-PATH} -P{SERVER-PORT} -u{USERNAME} -p{PASSWORD} {DBNAME} {DB-PARAM} > {FILEPATH}";if(isDbVersion8){dbParam = "--column-statistics=0";}// 执行命令newCmd = newCmd.replace("{USERNAME}", username).replace("{PASSWORD}", password).replace("{SERVER-PATH}", ip).replace("{DBNAME}", dbName).replace("{SERVER-PORT}", port).replace("{FILEPATH}", pathFileName).replace("{DB-PARAM}", dbParam);//这里打印出来的命令是可以直接在 终端执行的。System.out.println(newCmd);System.out.println(pathFileName);// 创建进程构建器ProcessBuilder processBuilder = new ProcessBuilder();// 设置命令和参数processBuilder.command(getOsShell(), "-c" , newCmd);
// processBuilder.command(getOsShell(), "/c" , newCmd);// 启动进程Process process = processBuilder.start();// 获取命令执行的输出流InputStream inputStream = process.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));// 读取输出String line;while ((line = reader.readLine()) != null) {log.info(line);}// 等待命令执行完成int exitCode = process.waitFor();System.out.println("命令执行完成,退出码:" + exitCode);if (exitCode == 0) {log.info("数据库备份成功!");} else {log.info("数据库备份失败!");}//TODO 获取文件备份的文件、上传到云服务。
// Resource resource = resourceLoader.getResource("file:" + pathFileName);
// InputStream inputStream = resource.getInputStream();
// byte[] bytes = IoUtil.readBytes(resource.getInputStream());//TODO 同步备份记录到数据库//TODO 删除指定文件
// FileUtil.del(pathFileName);}public String getOsShell() {String osName = System.getProperty("os.name");// TODO Windows未测试if (osName.toLowerCase().contains("windows")) {return "cmd.exe";} else if (osName.toLowerCase().contains("mac")) {return "/bin/bash";} else if (osName.toLowerCase().contains("linux")) {return "/bin/bash";}return "";}}
技术细节
主要就是使用ProcessBuilder创建系统进程,执行终端命令。