自动数据库备份,备份后用sftp上传
This commit is contained in:
parent
ed5d7fff69
commit
c943cd82fb
|
@ -64,3 +64,5 @@ $RECYCLE.BIN/
|
||||||
/base-common/target/
|
/base-common/target/
|
||||||
/base-core/target/
|
/base-core/target/
|
||||||
/base-webapp/target/classes/com/hzya/frame/
|
/base-webapp/target/classes/com/hzya/frame/
|
||||||
|
/fw-weixin/target/
|
||||||
|
/E:/yongansystem/log/2024-10-15/
|
||||||
|
|
|
@ -0,0 +1,386 @@
|
||||||
|
package com.hzya.frame.plugin.BackUpDatabase.plugin;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.hzya.frame.base.PluginBaseEntity;
|
||||||
|
import com.hzya.frame.web.entity.BaseResult;
|
||||||
|
import com.hzya.frame.web.entity.JsonResultEntity;
|
||||||
|
|
||||||
|
import com.jcraft.jsch.Channel;
|
||||||
|
import com.jcraft.jsch.ChannelSftp;
|
||||||
|
import com.jcraft.jsch.JSch;
|
||||||
|
import com.jcraft.jsch.Session;
|
||||||
|
import com.jcraft.jsch.SftpATTRS;
|
||||||
|
import com.jcraft.jsch.SftpException;
|
||||||
|
import org.apache.commons.net.ftp.FTPClient;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主数据模版(MdmModule)表服务接口
|
||||||
|
*
|
||||||
|
* @author makejava
|
||||||
|
* @since 2024-06-18 10:33:32
|
||||||
|
*/
|
||||||
|
public class BackUpDatabaseInitializer extends PluginBaseEntity {
|
||||||
|
Logger logger = LoggerFactory.getLogger(BackUpDatabaseInitializer.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
logger.info(getPluginLabel() + "執行初始化方法initialize()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
logger.info(getPluginLabel() + "執行銷毀方法destroy()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPluginId() {
|
||||||
|
return "BackUpDatabasePlugin";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPluginName() {
|
||||||
|
return "数据库备份下发";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPluginLabel() {
|
||||||
|
return "BackUpDatabasePlugin";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPluginType() {
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value("${database.filePase:}")
|
||||||
|
private String filePase;//文件保存路径
|
||||||
|
|
||||||
|
@Value("${database.fileName:data.sql}")
|
||||||
|
private String fileName;//文件保存名称
|
||||||
|
|
||||||
|
@Value("${database.databaseName:}")
|
||||||
|
private String databaseName;//库名
|
||||||
|
|
||||||
|
@Value("${database.host:}")
|
||||||
|
private String host;//地址
|
||||||
|
|
||||||
|
@Value("${database.port:}")
|
||||||
|
private String port;//端口
|
||||||
|
|
||||||
|
@Value("${database.username:}")
|
||||||
|
private String username;//用户名
|
||||||
|
|
||||||
|
@Value("${database.password:}")
|
||||||
|
private String password;//密码
|
||||||
|
|
||||||
|
|
||||||
|
@Value("${sftp.host:}")
|
||||||
|
private String sftpHost;
|
||||||
|
|
||||||
|
@Value("${sftp.port:}")
|
||||||
|
private Integer sftpPort;
|
||||||
|
|
||||||
|
@Value("${sftp.username:}")
|
||||||
|
private String sftpUsername;
|
||||||
|
|
||||||
|
@Value("${sftp.password:}")
|
||||||
|
private String sftpPassword;
|
||||||
|
|
||||||
|
@Value("${sftp.filePase:}")
|
||||||
|
private String sftpFilePase;
|
||||||
|
|
||||||
|
|
||||||
|
private ChannelSftp sftp = null;
|
||||||
|
private Session sshSession = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonResultEntity executeBusiness(JSONObject requestJson) {
|
||||||
|
try {
|
||||||
|
if(filePase == null || "".equals(filePase)
|
||||||
|
|| databaseName == null || "".equals(databaseName)
|
||||||
|
|| fileName == null || "".equals(fileName)
|
||||||
|
|| host == null || "".equals(host)
|
||||||
|
|| port == null || "".equals(port)
|
||||||
|
|| username == null || "".equals(username)
|
||||||
|
|| password == null || "".equals(password)
|
||||||
|
){
|
||||||
|
return BaseResult.getSuccessMessageEntity("系统参数未配置不执行,数据库备份");
|
||||||
|
}
|
||||||
|
//查找是否存在当天数据库
|
||||||
|
//格式化日期
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
String data = sdf.format(new Date());
|
||||||
|
//当天路径
|
||||||
|
String nowDatabasePase = filePase + File.separator + data;
|
||||||
|
//不判断文件是否存在,直接执行
|
||||||
|
if(!backFile(nowDatabasePase)){
|
||||||
|
return BaseResult.getFailureMessageEntity("备份失败");
|
||||||
|
}
|
||||||
|
//判断是否有sftp配置,有的备份,没有的不备份
|
||||||
|
if(sftpHost != null && !"".equals(sftpHost)
|
||||||
|
&& sftpPort != null && !"".equals(sftpPort)
|
||||||
|
&& sftpUsername != null && !"".equals(sftpUsername)
|
||||||
|
&& sftpPassword != null && !"".equals(sftpPassword)
|
||||||
|
&& sftpFilePase != null && !"".equals(sftpFilePase)
|
||||||
|
){
|
||||||
|
String sftpnowDatabasePase = sftpFilePase + File.separator + data;
|
||||||
|
if(!sendFile(nowDatabasePase,sftpnowDatabasePase)){
|
||||||
|
return BaseResult.getFailureMessageEntity("备份失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("执行成功");
|
||||||
|
return BaseResult.getSuccessMessageEntity("执行成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("执行失败{}", e.getMessage());
|
||||||
|
return BaseResult.getFailureMessageEntity("备份失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean backFile(String nowDatabasePase) {
|
||||||
|
try {
|
||||||
|
// 构建 mysqldump 命令
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(
|
||||||
|
"mysqldump",
|
||||||
|
"--ssl-mode=DISABLED",
|
||||||
|
"-h", host,
|
||||||
|
"-u", username,
|
||||||
|
"-p" + password,
|
||||||
|
"-P" + port,
|
||||||
|
databaseName);
|
||||||
|
// 启动进程并获取输入流
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
File f = creatFile(nowDatabasePase,fileName);
|
||||||
|
// 将备份内容写入文件
|
||||||
|
FileWriter writer = new FileWriter(f);
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine())!= null) {
|
||||||
|
writer.write(line + "\n");
|
||||||
|
}
|
||||||
|
// 关闭资源
|
||||||
|
reader.close();
|
||||||
|
writer.close();
|
||||||
|
process.waitFor();
|
||||||
|
logger.info("文件备份成功路径:"+nowDatabasePase+ File.separator +fileName);
|
||||||
|
return true;
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
logger.info("文件备份失败:"+e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @Author lvleigang
|
||||||
|
* @Description 创建目录及文件
|
||||||
|
* @Date 8:59 上午 2024/10/22
|
||||||
|
* @param filePath
|
||||||
|
* @param fileName
|
||||||
|
* @return java.io.File
|
||||||
|
**/
|
||||||
|
public File creatFile(String filePath, String fileName) {
|
||||||
|
File folder = new File(filePath);
|
||||||
|
//文件夹路径不存在
|
||||||
|
if (!folder.exists()) {
|
||||||
|
boolean mkdirs = folder.mkdirs();
|
||||||
|
}
|
||||||
|
// 如果文件不存在就创建
|
||||||
|
File file = new File(filePath + File.separator + fileName);
|
||||||
|
if (!file.exists()) {
|
||||||
|
try {
|
||||||
|
file.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("创建备份文件失败:"+e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendFile(String localFilePath,String remoteFileName) {
|
||||||
|
try {
|
||||||
|
connect();
|
||||||
|
uploadFile(remoteFileName,fileName,localFilePath,fileName);
|
||||||
|
disconnect();
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("sftp文件上传失败:"+e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
try {
|
||||||
|
JSch jsch = new JSch();
|
||||||
|
jsch.getSession(sftpUsername, sftpHost, sftpPort);
|
||||||
|
sshSession = jsch.getSession(sftpUsername, sftpHost, sftpPort);
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("Session created.");
|
||||||
|
}
|
||||||
|
sshSession.setPassword(sftpPassword);
|
||||||
|
Properties sshConfig = new Properties();
|
||||||
|
sshConfig.put("StrictHostKeyChecking", "no");
|
||||||
|
sshSession.setConfig(sshConfig);
|
||||||
|
sshSession.connect();
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("Session connected.");
|
||||||
|
}
|
||||||
|
Channel channel = sshSession.openChannel("sftp");
|
||||||
|
channel.connect();
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("Opening Channel.");
|
||||||
|
}
|
||||||
|
sftp = (ChannelSftp) channel;
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("Connected to " + host + ".");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭连接
|
||||||
|
*/
|
||||||
|
public void disconnect() {
|
||||||
|
if (this.sftp != null) {
|
||||||
|
if (this.sftp.isConnected()) {
|
||||||
|
this.sftp.disconnect();
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("sftp is closed already");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.sshSession != null) {
|
||||||
|
if (this.sshSession.isConnected()) {
|
||||||
|
this.sshSession.disconnect();
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("sshSession is closed already");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传单个文件
|
||||||
|
*
|
||||||
|
* @param remotePath:远程保存目录
|
||||||
|
* @param remoteFileName:保存文件名
|
||||||
|
* @param localPath:本地上传目录(以路径符号结束)
|
||||||
|
* @param localFileName:上传的文件名
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean uploadFile(String remotePath, String remoteFileName, String localPath, String localFileName) {
|
||||||
|
FileInputStream in = null;
|
||||||
|
try {
|
||||||
|
createDir(remotePath);
|
||||||
|
File file = new File(localPath + File.separator + localFileName);
|
||||||
|
in = new FileInputStream(file);
|
||||||
|
sftp.put(in, remoteFileName, 65536);
|
||||||
|
return true;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
} catch (SftpException e) {
|
||||||
|
} finally {
|
||||||
|
if (in != null) {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建目录
|
||||||
|
*
|
||||||
|
* @param createpath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean createDir(String createpath) {
|
||||||
|
try {
|
||||||
|
if (isDirExist(createpath)) {
|
||||||
|
this.sftp.cd(createpath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String pathArry[] = createpath.split("/");
|
||||||
|
StringBuffer filePath = new StringBuffer("/");
|
||||||
|
for (String path : pathArry) {
|
||||||
|
if (path.equals("")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
filePath.append(path + "/");
|
||||||
|
if (isDirExist(filePath.toString())) {
|
||||||
|
sftp.cd(filePath.toString());
|
||||||
|
} else {
|
||||||
|
// 建立目录
|
||||||
|
sftp.mkdir(filePath.toString());
|
||||||
|
// 进入并设置为当前目录
|
||||||
|
sftp.cd(filePath.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
this.sftp.cd(createpath);
|
||||||
|
return true;
|
||||||
|
} catch (SftpException e) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断目录是否存在
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isDirExist(String directory) {
|
||||||
|
boolean isDirExistFlag = false;
|
||||||
|
try {
|
||||||
|
SftpATTRS sftpATTRS = sftp.lstat(directory);
|
||||||
|
isDirExistFlag = true;
|
||||||
|
return sftpATTRS.isDir();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e.getMessage().toLowerCase().equals("no such file")) {
|
||||||
|
isDirExistFlag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isDirExistFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果目录不存在就创建目录
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
*/
|
||||||
|
public void mkdirs(String path) {
|
||||||
|
File f = new File(path);
|
||||||
|
|
||||||
|
String fs = f.getParent();
|
||||||
|
|
||||||
|
f = new File(fs);
|
||||||
|
|
||||||
|
if (!f.exists()) {
|
||||||
|
f.mkdirs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -61,4 +61,22 @@ cbs8:
|
||||||
OA:
|
OA:
|
||||||
data_source_code: yc_oa
|
data_source_code: yc_oa
|
||||||
server:
|
server:
|
||||||
port: 10086
|
port: 10086
|
||||||
|
|
||||||
|
# mysqldump -d mylm -hhzya.ufyct.com -p9096 -uroot -phzya1314 >%dirName%\table_view.sql
|
||||||
|
|
||||||
|
|
||||||
|
database:
|
||||||
|
databaseName: businesscenter
|
||||||
|
host: 192.168.2.237
|
||||||
|
port: 3306
|
||||||
|
username: root
|
||||||
|
password: hzya@1314
|
||||||
|
filePase: /Users/apple/Desktop/log
|
||||||
|
fileName: data.sql
|
||||||
|
#sftp:
|
||||||
|
# host: 192.168.2.237
|
||||||
|
# port: 9091
|
||||||
|
# username: cs237
|
||||||
|
# password: hzya@1314
|
||||||
|
# filePase: /databaseBack
|
||||||
|
|
|
@ -126,3 +126,17 @@ jeecg :
|
||||||
bucketName: ??
|
bucketName: ??
|
||||||
data:
|
data:
|
||||||
use: true
|
use: true
|
||||||
|
database:
|
||||||
|
databaseName:
|
||||||
|
host:
|
||||||
|
port:
|
||||||
|
username:
|
||||||
|
password:
|
||||||
|
filePase:
|
||||||
|
fileName:
|
||||||
|
sftp:
|
||||||
|
host:
|
||||||
|
port:
|
||||||
|
username:
|
||||||
|
password:
|
||||||
|
filePase:
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plugin>
|
||||||
|
<id>BackUpDatabasePlugin</id>
|
||||||
|
<name>BackUpDatabasePlugin插件</name>
|
||||||
|
<category>20241021</category>
|
||||||
|
</plugin>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||||
|
<beans default-autowire="byName">
|
||||||
|
<bean name="backUpDatabaseInitializer" class="com.hzya.frame.plugin.BackUpDatabase.plugin.BackUpDatabaseInitializer" />
|
||||||
|
</beans>
|
10
pom.xml
10
pom.xml
|
@ -406,6 +406,16 @@
|
||||||
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
|
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
|
||||||
<version>2.0.0</version>
|
<version>2.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-net</groupId>
|
||||||
|
<artifactId>commons-net</artifactId>
|
||||||
|
<version>3.8.0</version> <!-- 这里的版本号可根据实际情况修改 -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jcraft</groupId>
|
||||||
|
<artifactId>jsch</artifactId>
|
||||||
|
<version>0.1.53</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
Loading…
Reference in New Issue