使用Java程序对Windows&Linux系统MySQL和Dm数据库进行备份以及文件夹的压缩备份和文件夹的复制备份 以及接口超时后报错中止线程

直接上代码  有更好方案可以直接分享出来  大家一起进步
//每天2:10执行
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void BackUpFileTasks() {
        try {
            semaphoreGetSealRandom.acquire();
            logger.info("...BackUpFileTasks start...");
            DuplicateCatalog duplicateCatalog = new DuplicateCatalog();

            ExecutorService executorService = Executors.newFixedThreadPool(2);

            FutureTask<String> future = new FutureTask<>(
                    new Callable<String>() {
                        public String call() {
                            //备份数据库
                            duplicateCatalog.backUpMysql();
                            return "...";
                        }
                    });
            // 加载future
            Future<?> submit = executorService.submit(future);
            Future<Boolean> booleanFuture = executorService.submit(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    //备份文件夹
                    return duplicateCatalog.fileToZip();
                }
            });
            try {
                System.out.println(submit.get(10, TimeUnit.SECONDS));
                booleanFuture.get(60,TimeUnit.MILLISECONDS);
            } catch (Exception e) {
                logger.error("备份数据库超时!");  // 超时报个错
                future.cancel(Boolean.TRUE);
            } finally {
                executorService.shutdown();  // 关闭线程池
            }

            //删除之前备份文件夹
            duplicateCatalog.deleteBackUpFile();
            //备份文件夹
            duplicateCatalog.fileToZip();
            //备份程序包
            duplicateCatalog.backProject();
            logger.info("...BackUpFileTasks end...");
        } catch (Throwable e) {
            logger.error("备份数据:", e);
        } finally {
            semaphoreGetSealRandom.release();   //返回一个信号量
        }
    }
/**
 * @Author libai
 * @Date 2023/2/17 9:40
 */
public class DuplicateCatalog {
    // 保存temp里面内容
    private List<String> listFile = new ArrayList<String>();

    private Logger logger = LoggerFactory.getLogger(DuplicateCatalog.class);

    /**
     * 数据库用户名
     */
    @Value("${database.username}")
    private String username;

    /**
     * 数据库密码
     */
    @Value("${database.password}")
    private String password;

    /**
     * 数据库url
     */
    @Value("${database.url}")
    private String url;

    /**
     * 数据库类型
     */
    @Value("${spring.profiles.active}")
    private String type;

    /**
     * 文件存储路径
     */
    @Value("${upload.path}")
    private String zippath;

    //备份地址
    private String tmppath = "";

    //windows dm数据库bin目录
    private String dmpath = "D:\\kaifa\\dmdatabase\\dmdbms\\bin ";

    //linux dm数据库bin目录
    private String dmlinuxpath = "/opt/dmdbms/bin ";

    //Linux mysqldump所在路径
    private String mysqldumppath = "/usr/bin/mysqldump ";


    //备份数据库
    public void backUpMysql() {
        zippath = zippath + "\\";
        Calendar cal = new GregorianCalendar();
        cal.setTime(new Date());
        String year = Integer.toString(cal.get(Calendar.YEAR));
        Integer month = cal.get(Calendar.MONTH) + 1;
        Integer day = cal.get(Calendar.DATE);


        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith("lin")) {
            zippath = "/opt/temp/";
        }
        tmppath = zippath + year + "-" + (month >= 10 ? month : "0" + month) + "-" + (day >= 10 ? day : "0" + day) + "备份";
        File saveFile = new File(tmppath);
        // 如果目录不存在
        if (!saveFile.exists()) {
            // 创建文件夹
            saveFile.mkdirs();
        }
        Process proc = null;
        Runtime run = Runtime.getRuntime();
        if ("mysql".equals(type)) {
            try {
                String backPath = "";
                //拼接sql文件名称
                String fileName = "/" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(System.currentTimeMillis()) + ".sql";
                backPath = tmppath + fileName;
                //开始拼接命令
                StringBuilder command = appendCmd(backPath);
                // 调用外部执行exe文件的javaAPI
                logger.info("执行mysql指令:" + command);
                logger.info("OS Name:" + os);
                try {
                    if (os.toLowerCase().startsWith("win")) {
                        proc = Runtime.getRuntime().exec(command.toString());
                    } else {
                        proc = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", command.toString()});
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                // 0 表示线程正常终止。
                Integer waitFor = proc.waitFor();
                Integer exitValue = proc.exitValue();
                logger.info("proc.waitFor()-proc.exitValue()===>{},{}", waitFor, exitValue);
                try {
                    InputStream errorStream = proc.getErrorStream();
                    File file = new File(tmppath + "/备份error/");
                    writeToLocal(file.getPath() + "日志.txt", errorStream);
                } catch (Exception e) {
                    logger.info("未产生异常信息,备份正常");
                }
                if (waitFor != 0) {
                    logger.info("===========backup failure================");
                } else {
                    logger.info("===========backup successful================");
                    proc.destroy();
                }
            } catch (InterruptedException e) {
                logger.info("backUpSystemLogs InterruptedException", e);
                e.printStackTrace();
                throw new RuntimeException(e.getMessage());
            } catch (Throwable e) {
                logger.info("appear Throwable--------->");
                e.printStackTrace();
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Execute MysqlDumpExec::backUpSystemLogs() end.");
            }
        } else if ("rdjc".equals(type)) {
            System.out.println(5);
        } else {
            //达梦数据库备份
            logger.info("dm数据库备份开始");
            try {
                if (os.toLowerCase().startsWith("lin")) {
                    proc = run.exec("/bin/bash");
                } else {
                    proc = run.exec("cmd");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            String dmlIp = "";
            String dmPort = "";
            String dmName = "";
            if (StringUtils.isNotBlank(url)) {
                //从配置中解析出数据库ip+名+端口
                String[] datas = url.split("\\?")[0].split("/");
                dmName = datas[datas.length - 1];
                String allIp = datas[datas.length - 2];
                String[] ips = allIp.split(":");
                dmlIp = ips[0];
                dmPort = ips[1];
            }

            if (proc != null) {
                try {
                    if (os.toLowerCase().startsWith("lin")) {
                        String command = "cd " + dmlinuxpath + " && ./dexp " + username + "/" + password + "@" + dmlIp + ":" + dmPort +
                                " file=" + dmName + ".dmp  NOLOG=Y  LOG=dm备份日志.log SCHEMAS=" + dmName + " directory=" + tmppath;

                        proc = run.exec(new String[]{"/bin/bash", "-c", command});
                    } else {
                        proc = run.exec("cmd /c cd /d  " + dmpath + " && dexp " + username + "/" + password + "@" + dmlIp + ":" + dmPort +
                                " file=" + dmName + ".dmp  NOLOG=Y  LOG=dm备份日志.log SCHEMAS=" + dmName + " directory=" + tmppath);
                    }
                    InputStreamReader inst = null;
                    SequenceInputStream sis = new SequenceInputStream(proc.getInputStream(), proc.getErrorStream());
                    if (os.toLowerCase().startsWith("lin")) {
                        inst = new InputStreamReader(sis, "UTF-8");//设置编码格式并转换为输入流
                    } else {
                        inst = new InputStreamReader(sis, "GBK");//设置编码格式并转换为输入流
                    }

                    BufferedReader br = new BufferedReader(inst);//输入流缓冲区
                    String line = null;
                    StringBuilder sb = new StringBuilder();
                    while ((line = br.readLine()) != null) {//循环读取缓冲区中的数据
                        sb.append(line).append("\n");
                    }
                    br.close();
                    proc.waitFor();
                    proc.destroy();
                    logger.info(sb.toString());//输出获取的数据;//输出获取的数据
                    logger.info("dm数据库备份结束");
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("dm数据库备份异常");
                }
            }
        }
    }

    /**
     * 拼接执行命令
     */
    private StringBuilder appendCmd(String backPath) {
        StringBuilder command = new StringBuilder();
        String mysqlIp = "";
        String mysqlPort = "";
        String mysqlData = "";
        if (StringUtils.isNotBlank(url)) {
            //从配置中解析出数据库ip+名+端口
            String[] split = url.split("\\?")[0].split("/");
            mysqlData = split[split.length - 1];
            String allIp = split[split.length - 2];
            String[] ips = allIp.split(":");
            mysqlIp = ips[0];
            mysqlPort = ips[1];
        }
        // 拼接命令行的命令
        // windows: D:\MySQL Server 5.7\bin\mysqldump  --opt -h127.0.0.1 --user=root -P33306 --password=123#! --databases test --tables test_user --result-file=D:\logsql\sql.sql --default-character-set=utf8
        // linux: /usr/local/mysql/bin/mysqldump  --opt -h111.144.210.30 --user=root --password='23!@#' -P33306 --databases test --tables test_t1 test_t2 --result-file=/syslog/backUpSystemLog_20211118_030951_sql.sql
        // 区分系统
        String os = System.getProperty("os.name");

        if (os.toLowerCase().startsWith("win")) {
            command.append("cmd.exe /C " + "mysqldump");
        } else {
            command.append(mysqldumppath).append(" mysqldump");
        }
        command.append(" --column-statistics=0");
        command.append("  --opt -h");
        command.append(mysqlIp);
        command.append(" --user=");
        command.append(username);

        if (os.toLowerCase().startsWith("win")) {
            command.append(" --password=");
            command.append(password);
        } else {
            //linux需要引号密码,否则会执行失败
            command.append(" --password=");
            command.append("'" + password + "'");
        }
        //端口用大写的P指向
        command.append(" -P" + mysqlPort);
        command.append(" --databases " + mysqlData);
        command.append(" --result-file=");
        command.append(backPath);
        return command;
    }

    //备份MySQL将错误日志写入txt文件
    private void writeToLocal(String destination, InputStream input) throws IOException {
        int index;
        byte[] bytes = new byte[1024];
        FileOutputStream downloadFile = new FileOutputStream(destination);
        while ((index = input.read(bytes)) != -1) {
            downloadFile.write(bytes, 0, index);
            downloadFile.flush();
        }
        input.close();
        downloadFile.close();
    }


    //备份文件夹
    public boolean fileToZip() {
        boolean flag = false;
        System.out.println("正在压缩中、、、");
        long start = System.currentTimeMillis();
        getFile(zippath);
        String fileName = new SimpleDateFormat("yyyyMMdd_HHmmss").format(System.currentTimeMillis());
        try {
            File zipFile = new File(tmppath + "/" + fileName + ".zip");
            if (zipFile.exists()) {
                System.out.println(tmppath + "目录下存在名字为:" + fileName + ".zip" + "的打包文件");
            } else {
                if (!zipFile.exists()) {
                    zipFile.getParentFile().mkdirs();
                }
                flag = Compresseddirectory(zipFile);
            }
            System.out.println("压缩完成、、、");
            long end = System.currentTimeMillis();
            System.out.println("用时" + ((end - start) / 1000) + "秒");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return flag;
    }

    //获取文件夹下所有文件路径
    private void getFile(String path) {
        File file = new File(path);
        File[] tempList = file.listFiles();
        assert tempList != null;
        //如果是空文件夹就删除
        if (tempList.length == 0) {
            file.delete();
        }
        for (File f : tempList) {
            if (f.isFile()) {
                listFile.add(f.getPath());
                continue;
            }
            if (f.isDirectory()) {
                getFile(f.getPath());
            }
        }
    }

    //执行压缩操作
    private boolean Compresseddirectory(File zipFile) {
        boolean flag = false;
        BufferedInputStream bis = null;
        FileInputStream fis = null;
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        try {
            fos = new FileOutputStream(zipFile);
            zos = new ZipOutputStream(new BufferedOutputStream(fos));
            byte[] bufs = new byte[2048 * 2048];
            for (int i = 0; i < listFile.size(); i++) {
                try {
                    //创建ZIP实体,并添加进压缩包
                    ZipEntry zipEntry = new ZipEntry(listFile.get(i));
                    zos.putNextEntry(zipEntry);
                    // 读取待压缩的文件并写进压缩包里
                    fis = new FileInputStream(listFile.get(i));
                    bis = new BufferedInputStream(fis, 1024 * 1024);
                    int read = 0;
                    while ((read = bis.read(bufs, 0, 1024 * 1024)) != -1) {
                        zos.write(bufs, 0, read);
                    }
                } catch (Exception e) {
                    logger.error("文件读取处理有误");
                    e.printStackTrace();
                }
            }
            flag = true;
            listFile.clear();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            // 关闭流
            try {
                if (null != bis)
                    bis.close();
                if (null != zos)
                    zos.close();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
        return flag;
    }

    //备份程序包
    public void backProject() {
        System.out.println("复制开始~~~~");
        long start = System.currentTimeMillis();
        //获取项目位置 
        URL resource = Thread.currentThread().getContextClassLoader().getResource("");
        assert resource != null;
        String[] split = resource.toString().split("/");
        StringBuilder projectpath = new StringBuilder();
        String projectname = "/";
        for (int i = 1; i <= split.length; i++) {
            projectpath.append(split[i]).append("/");
            if (i == split.length - 3) {
                projectname += split[i];
                break;
            }
        }
        //fileToZip(projectname, tmppath, split[3]);
        String newFileName = tmppath + projectname;
        String os = System.getProperty("os.name");
        File file1 = new File(projectpath.toString());//需要复制的文件/文件夹
        if (!file1.exists()) {
            file1.mkdir();
        }
        File file2 = new File(newFileName);//需要复制到的位置
        if (!file2.exists()) {
            file2.mkdir();
        }
        if (os.toLowerCase().startsWith("lin")) {
            //cp -r  /opt/tomcat-sursen/webapps/* /opt/temp/2023-02-17备份
            try {
                Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", "cp -r /" + projectpath + "/*  " + newFileName});
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            try {
                copy(file1, file2);
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("copy:error");
            }
        }
        System.out.println("复制结束~~~~");
        long end = System.currentTimeMillis();
        System.out.println("用时" + ((end - start) / 1000) + "秒");
    }

    private void copy(File file1, File file2) throws IOException {
        File[] files = file1.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                File file3 = new File(file2, f.getName());
                if (!file3.exists()) {//文件夹不存在
                    //创建多层文件夹
                    file3.mkdirs();
                }
                copy(f, file3);
            } else {
                String name = f.getName();
                File newFile = new File(file2, name);
                if (!newFile.exists()) {//文件不存在
                    //创建文件
                    newFile.createNewFile();
                }
                copyFile(f, newFile);
            }
        }
    }

    //使用带缓冲区的字符流复制
    private void copyFile(File oldFile, File newFile) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(oldFile));
            bos = new BufferedOutputStream(new FileOutputStream(newFile));
            byte[] bs = new byte[1024];
            int len;
            while ((len = bis.read(bs)) != -1) {
                bos.write(bs, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //删除某天备份的数据
    public void deleteBackUpFile() {
        try {
            Calendar now = Calendar.getInstance();
            now.add(Calendar.DAY_OF_MONTH, -3);//删除多少天之前备份的文件夹
            String endDate = new SimpleDateFormat("yyyy-MM-dd").format(now.getTime());
            //按照文件大小升序排序
            List<File> files = Arrays.asList(Objects.requireNonNull(new File(zippath).listFiles()));
            for (File file : files) {
                if (file.getName().contains("备份")) {
                   /* if ((file.getName().split("签"))[0].compareTo(endDate) < 0) {
                        System.out.println(file.getPath());
                    }*/
                    if (file.getName().compareTo(endDate) < 0) {
                        deleteFolder(new File(file.getPath()));
                        logger.info("删除文件夹" + file.getPath());
                    }
                }
            }
        } catch (Exception e) {
            logger.error("删除备份数据异常");
        }
    }

    //递归删除文件夹内的文件
    private void deleteFolder(File file) {
        for (File subFile : Objects.requireNonNull(file.listFiles())) {
            if (subFile.isDirectory()) {
                deleteFolder(subFile);
            } else {
                subFile.delete();
            }
        }
        file.delete();
    }


}

猜你喜欢

转载自blog.csdn.net/qq_46264836/article/details/129194595