1. 配置文件# windows 和 linux 不同
# database_backup_mysqldump = mysqldump
database_backup_mysqldump = C:\\Program Files\\MySQL\\MySQL Server 5.7\\bin\\mysqldump.exe
# 数据库配置(路径不以/结尾) 注意:该目录只存放备份SQL,否则会误删其他文件
database_backup_dir = D:/home/backup
# 清除30天前的备份文件
database_backup_clear_before_days = 30
# 数据库执行备份的定时任务
cron4j=mysqlBackup
mysqlBackup.cron=0 1 * * *
mysqlBackup.class=com.sohnny.jfinal.task.BackupMySqlTask
mysqlBackup.enable=true
2.定时备份MySQL任务类import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.cron4j.ITask;
import com.sohnny.MainConfig;
import com.sohnny.jfinal.common.kit.ClearFileKit;
public class BackupMySqlTask implements ITask {
String url = MainConfig.jdbcProp.get("jdbcUrl");
Path dir = Paths.get(MainConfig.sysProp.get("database_backup_dir"));
String mysqldump = MainConfig.sysProp.get("database_backup_mysqldump");
int beforeDays = MainConfig.sysProp.getInt("database_backup_clear_before_days");
@Override
public void run() {
//获取IP和PORT
String[] arrays = url.split("/");
String host = arrays[2];
String ip, port;
if (host.contains(":")) {
ip = host.split(":")[0];
port = host.split(":")[1];
} else {
ip = host;
port = "3306";
}
//获取数据库名称
System.out.println(arrays[3]);
System.out.println(arrays[3].substring(0, arrays[3].indexOf("?")));
String dataBaseName = arrays[3].substring(0, arrays[3].indexOf("?"));
//创建备份目录
if (!Files.exists(dir)) {
try {
Files.createDirectories(dir);
} catch (IOException e) {
e.printStackTrace();
}
}
//生成备份文件名
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss"));
Path path = Paths.get(dir.toString(), dataBaseName+"-"+date+".sql");
Process process = null;
try {
String cmd = mysqldump+" -h "+ip+" -P "+port+" -u "+MainConfig.jdbcProp.get("user")+" -p"+MainConfig.jdbcProp.get("password").trim()+" --databases "+dataBaseName+" ";
System.out.println(cmd);
process = Runtime.getRuntime().exec(cmd);
try (
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
) {
backup(stdoutReader, path);
errOut(stderrReader, path);
} catch (IOException e) {
e.printStackTrace();
}
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("数据库备份完成");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
//清除过期文件
ClearFileKit.clearFileByMonth(dir, beforeDays);
// 每次调度启动时,向 task_run_log 写日志,用于检查调度的时间是否与预期的一致,避免出现 bug 却不知道
Record taskRunLog = new Record().set("taskName", "backupMySql").set("createAt", new Date());
Db.save("task_run_log", taskRunLog);
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
private void backup (BufferedReader stdReader, Path path) throws IOException {
Path backupPath = null;
if (Files.notExists(path)) backupPath = Files.createFile(path);
String line;
try (BufferedWriter bw = Files.newBufferedWriter(backupPath, StandardOpenOption.WRITE)) {
while ((line = stdReader.readLine()) != null) {
bw.write(line+"\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void errOut (BufferedReader stdReader, Path path) throws IOException {
String line;
try {
while ((line = stdReader.readLine()) != null) {
System.err.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Thread(new BackupMySqlTask()).start();
}
}
3. 清除过期文件类import static java.nio.file.FileVisitResult.CONTINUE;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDateTime;
import java.time.ZoneId;
public class ClearFileKit {
/**
* 清除某个目录下某几天前的文件
* @param dir
* @param days
*/
public static void clearFileByMonth(Path dir, int days) {
class DeleteFiles extends SimpleFileVisitor {
LocalDateTime beforeDateTime = LocalDateTime.now().minusDays(days);
boolean isDeleteDir = false;
public DeleteFiles(boolean isDeleteDir) {
this.isDeleteDir = isDeleteDir;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
if (attr.isSymbolicLink()) {
System.out.format("Symbolic link: %s%n ", file);
} else if (attr.isRegularFile()) {
try {
boolean isHarfYearBefore = attr.creationTime().toInstant().isBefore(beforeDateTime.atZone(ZoneId.systemDefault()).toInstant());
if (isHarfYearBefore) {
Files.delete(file);
System.out.format("Delete Regular file: %s%n ", file);
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.format("Other: %s%n ", file);
}
//System.out.println("(" + attr.size() + "bytes)");
return CONTINUE;
}
// Print each directory visited.
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
if (isDeleteDir) {
try {
Files.delete(dir);
System.out.format("Delete Directory: %s%n ", dir);
} catch (NoSuchFileException x) {
System.err.format("%s: no such" + " directory%n", dir);
} catch (DirectoryNotEmptyException x) {
//System.err.format("%s not empty%n", dir);
} catch (IOException x) {
// File permission problems are caught here.
System.err.println(x);
}
}
return CONTINUE;
}
// If there is some error accessing
// the file, let the user know.
// If you don't override this method
// and an error occurs, an IOException
// is thrown.
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
System.err.println(exc);
return CONTINUE;
}
}
long startTime = System.currentTimeMillis();
System.out.println("开始删除过期文件...");
Path startingDir = dir;
DeleteFiles pf = new DeleteFiles(false);
try {
Files.walkFileTree(startingDir, pf);
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long time = endTime-startTime;
System.out.println("删除过期文件完成, 耗时: " +time/1000+" 秒");
}
}