Springboot使用ProcessBuilder创建系统进程执行shell命令备份数据库

文章目录

概要

Springboot执行shell命令备份数据库。

1、查看mysql版本

bash 复制代码
mysql --version

2、相关依赖

xml 复制代码
<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、具体代码

java 复制代码
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文件
    @Autowired
    private ResourceLoader resourceLoader;

    /**
     * 数据库版本是否为 8.0 + (false=否  true=是), mysql8+ 需要参数  --column-statistics=0  , mysql8- 不需要
     * 新版的mysqldump默认启用了一个新标志,通过--column-statistics=0来禁用
     */
    boolean isDbVersion8 = true;

    @SneakyThrows
    public 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创建系统进程,执行终端命令。

相关推荐
对空六课35 分钟前
两个统计平台数据不同:用同一时间窗和事件样本做差异定位
大数据·前端·网络·数据库
wno7046 小时前
postgresSQL压缩版安装与基本命令
数据库·postgresql
聚美智数8 小时前
智能结构化识别-图片结构解析-图像结构化解析-照片结构化解析
android·java·数据库
十年Java程序媛8 小时前
Java枚举Enum完整教程|替代静态常量,开发与面试要点
java·开发语言·spring boot·后端·面试
瀚高PG实验室8 小时前
瀚高数据库常用系统表查询入门指南(附常用SQL)
数据库·sql·postgresql·瀚高数据库
我是人✓8 小时前
SpringBoot静态资源映射揭秘
java·spring boot·后端
全栈弄潮儿8 小时前
Python实战第7期:字典与集合
后端·python·编程语言
ben9518chen8 小时前
mysql数据库基本操作
数据库·mysql
2603_965148118 小时前
电商选品调研:通过关键词搜索API获取市场热销商品,结合商品详情API分析竞品卖点与定价
开发语言·数据库·人工智能·python·信息可视化
码事漫谈8 小时前
DeepSeek 又更新!但怎么有个分数往下掉?
后端