ExecuteBackupAndRestore.Java
package cn.easted.edm.web.task;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.Session;
import cn.easted.edm.core.exception.CommonException;
import cn.easted.edm.core.generic.common.Constant;
import cn.easted.edm.core.service.impl.LogServiceImpl;
import cn.easted.edm.core.utils.SFTPUploadAndDownloadUtils;
import cn.easted.edm.core.utils.SSHConnection;
/**
* 备份还原类
* @ClassName: Execute
* @Description:
* @author Wanghao
* @date 2017年5月31日 下午4:03:54
*/
public class ExecuteBackupAndRestore {
private static Logger logger = Logger.getLogger(ExecuteBackupAndRestore.class);
private static String SERVER_HOSTIP = getValueByKey("server_hostIp"); //"10.10.139.157";
private static int PORT = 22;
private static String USERNAME = getValueByKey("server_username"); //"root";
private static String PASSWORD = getValueByKey("server_pwd"); //"easted2013";
private static String DB_URL = getValueByKey("jdbc.url"); //"jdbc:postgresql://10.10.139.157:5432/db_edm";
private static String DB_USERNAME = getValueByKey("jdbc.username"); //"edm";
private static String DB_PASSWORD = getValueByKey("jdbc.password"); //"easted2013";
//是否安装expect命令
private static String CMD1 = "cd /mnt/update; ./isExpectInstall.sh";
//安装zip/unzip
private static String CMD1_1 = "cd /mnt/update; yum install -y unzip zip";
//备份命令
private static String CMD2 = "cd /mnt/update; ./backup.sh";
//压缩文件命令
private static String CMD3 = "cd /mnt/update; zip -rqmP easted2013 edm.zip backup";
//目标路径
// private static String DESTDIR = "http://" + SERVER_HOSTIP + ":" + "22" + "/mnt/update";
private static String DEST_DIR = "/mnt/update";
//保存路径
private static String SAVE_FILE_NAME = "edm.zip";
//解压命令
private static String CMD4 = "cd /mnt/update; unzip -o -P easted2013 edm.zip";
//还原
private static String CMD5 = "cd /mnt/update; ./restore.sh";
/**
* 备份
* @author Wanghao
*/
public void backup(HttpServletRequest req, HttpServletResponse res){
ChannelSftp sftp = null;
Session session = null;
LogServiceImpl logService = new LogServiceImpl();
//1.首先上传脚本到服务器
logger.info("start upload script to "+SERVER_HOSTIP+"...");
// String userdir = System.getProperty("user.dir");
String userdir = getClass().getResource("/").getPath();
File srcfile = new File(userdir + File.separator + "shell");
try {
session = SFTPUploadAndDownloadUtils.connect(SERVER_HOSTIP, PORT, USERNAME, PASSWORD);
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
SFTPUploadAndDownloadUtils.upload(DEST_DIR, srcfile.getAbsolutePath(), sftp);
logger.info("upload script finished");
//2. 安装expect
SSHConnection.exeCommand(SERVER_HOSTIP, PORT, USERNAME, PASSWORD, CMD1);
//安装zip unzip命令
SSHConnection.exeCommand(SERVER_HOSTIP, PORT, USERNAME, PASSWORD, CMD1_1);
//3.备份
String backupCmd = CMD2 + " " + SERVER_HOSTIP + " " + PASSWORD;
SSHConnection.exeCommand(SERVER_HOSTIP, PORT, USERNAME, PASSWORD, backupCmd);
logger.info("backup file finished");
//4.压缩文件
SSHConnection.exeCommand(SERVER_HOSTIP, PORT, USERNAME, PASSWORD, CMD3);
logger.info("zip file finished");
//5.下载文件到本地
String srcFile = DEST_DIR + "/edm.zip";
SFTPUploadAndDownloadUtils.download(DEST_DIR, srcFile, SAVE_FILE_NAME, sftp, req, res);
logService.saveBackupRestore(Constant.BACKUP, Constant.OPERATION_SUCCESS);
} catch (Exception e) {
logService.saveBackupRestore(Constant.BACKUP, Constant.OPERATION_ERROR);
logger.error(e);
throw new CommonException("100", "备份文件失败");
}finally{
if(sftp != null)sftp.disconnect();
if(session != null)session.disconnect();
}
}
/**
* 还原
* @author Wanghao
*/
@SuppressWarnings("unused")
public void restore(HttpServletRequest request){
ChannelSftp sftp = null;
Session session = null;
LogServiceImpl logService = new LogServiceImpl();
//1.首先上传压缩包到服务器
logger.info("start upload zipFile to " + SERVER_HOSTIP + "...");
MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = mRequest.getFileMap();
int i = 0;
for (Iterator<Map.Entry<String, MultipartFile>> it = fileMap.entrySet().iterator(); it.hasNext(); i++) {
Map.Entry<String, MultipartFile> entry = it.next();
MultipartFile mFile = entry.getValue();
try {
session = SFTPUploadAndDownloadUtils.connect(SERVER_HOSTIP, PORT, USERNAME, PASSWORD);
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
//上传文件
SFTPUploadAndDownloadUtils.copyFile(DEST_DIR, mFile.getOriginalFilename(), mFile.getInputStream(), sftp);
logger.info("upload file finished");
//删掉backup文件夹
SFTPUploadAndDownloadUtils.deleteDic("/mnt/update/backup", sftp);
//文件重命名
String cmd6 = "cd /mnt/update; mv " + mFile.getOriginalFilename() +" edm.zip";
SSHConnection.exeCommand(SERVER_HOSTIP, PORT, USERNAME, PASSWORD, cmd6);
//解压缩文件
SSHConnection.exeCommand(SERVER_HOSTIP, PORT, USERNAME, PASSWORD, CMD4);
//判断/mnt/update/backup是否存在
SFTPUploadAndDownloadUtils.isDicExist("/mnt/update/backup", sftp);
logger.info("upzip file finished");
//数据库还原前清空原数据
deleteDBData(DB_URL, DB_USERNAME, DB_PASSWORD);
//数据库还原
String restoreCmd = CMD5 + " " + SERVER_HOSTIP + " " + PASSWORD;
SSHConnection.exeCommand(SERVER_HOSTIP, PORT, USERNAME, PASSWORD, restoreCmd);
logService.saveBackupRestore(Constant.RESTORE, Constant.OPERATION_SUCCESS);
logger.info("restore database finished");
}catch (Exception e) {
logService.saveBackupRestore(Constant.RESTORE, Constant.OPERATION_ERROR);
e.printStackTrace();
throw new CommonException("100", "还原文件失败");
}finally{
if(sftp != null)sftp.disconnect();
if(session != null)session.disconnect();
}
}
}
/**
* 清空数据库中表数据
* @param url
* @param username
* @param pwd
*/
private static void deleteDBData(String url, String username, String pwd){
Connection c = null;
Statement stmt = null;
try {
Class.forName(getValueByKey("jdbc.driver")); //org.postgresql.Driver
c = DriverManager.getConnection(url, username, pwd);
c.setAutoCommit(false);
System.out.println("Opened database successfully");
stmt = c.createStatement();
String sql = "select tablename from pg_tables where tablename like 't_%'";
// stmt.executeUpdate(sql);
ResultSet resultSet = stmt.executeQuery(sql);
List<String> names = new ArrayList<String>();
while(resultSet.next()){
String name = resultSet.getString(1);
names.add(name);
System.out.println(name);
}
if (names != null && names.size() > 0){
for (String name : names){
String desql = "delete from " + name;
stmt.executeUpdate(desql);
}
}
stmt.close();
c.commit();
c.close();
} catch (Exception e) {
if (c != null){
try {
c.close();
} catch (SQLException e1) {
throw new CommonException("100", "清除数据库错误");
}
}
// System.err.println(e.getClass().getName() + ": " + e.getMessage());
// System.exit(0);
throw new CommonException("100", "清除数据库错误");
}
}
/**
* 读取配置文件
* @return
*/
public Map<String, String> getProperties() {
Properties props = new Properties();
Map<String, String> map = new HashMap<String, String>();
try {
InputStream in = null;
if (getClass().getResource("/dev/jdbc.properties") != null){
in = getClass().getResourceAsStream("/dev/jdbc.properties");
} else if (getClass().getResource("/pro/jdbc.properties") != null){
in = getClass().getResourceAsStream("/pro/jdbc.properties");
}
props.load(in);
Enumeration<?> en = props.propertyNames();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String property = props.getProperty(key);
map.put(key, property);
}
} catch (Exception e) {
e.printStackTrace();
throw new CommonException("100", "读取配置文件出错");
}
return map;
}
public static String getValueByKey(String key){
ExecuteBackupAndRestore ex = new ExecuteBackupAndRestore();
String value = ex.getProperties().get(key);
return value;
}
public static void main(String[] args) throws FileNotFoundException, IOException {
// backup();
// restore(null);
// deleteDBData(DB_URL, DB_USERNAME, DB_PASSWORD);
ExecuteBackupAndRestore ex = new ExecuteBackupAndRestore();
Map<String, String> map = ex.getProperties();
Set<Entry<String, String>> set = map.entrySet();
for (Entry<String, String> e : set){
System.out.println(e.getKey() + ":" + e.getValue());
}
// String s = getValueByKey("server_hostIp");
// System.out.println(s);
}
}
SFTPUploadAndDownloadUtils.java
package cn.easted.edm.core.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import cn.easted.edm.core.exception.CommonException;
/**
* 通过SSH上传下载文件
* @author Wanghao
*/
public class SFTPUploadAndDownloadUtils {
private static Log log = LogFactory.getLog(SFTPUploadAndDownloadUtils.class);
/**
* 连接sftp服务器
* @param host 远程主机ip地址
* @param port sftp连接端口,null 时为默认端口
* @param user 用户名
* @param password 密码
* @return
* @throws JSchException
*/
public static Session connect(String host, Integer port, String user, String password) throws JSchException{
Session session = null;
try {
JSch jsch = new JSch();
if(port != null){
session = jsch.getSession(user, host, port.intValue());
}else{
session = jsch.getSession(user, host);
}
session.setPassword(password);
//设置第一次登陆的时候提示,可选值:(ask | yes | no)
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
//30秒连接超时
session.connect(30000);
log.info("SFTPUitl 连接成功");
} catch (JSchException e) {
e.printStackTrace();
log.error("SFTPUitl 获取连接发生错误");
System.out.println("SFTPUitl 获取连接发生错误");
throw e;
}
return session;
}
/**
* sftp上传文件(夹)
* @param directory
* @param uploadFile
* @param sftp
* @throws Exception
* @author Wanghao
*/
@SuppressWarnings({ "rawtypes", "static-access" })
public static void upload(String directory, String uploadFile, ChannelSftp sftp) throws Exception{
System.out.println("sftp upload file [directory] : "+directory);
System.out.println("sftp upload file [uploadFile] : "+ uploadFile);
File file = new File(uploadFile);
if(file.exists()){
//因为ChannelSftp无法去判读远程linux主机的文件路径
try {
Vector content = sftp.ls(directory);
if(content == null){
sftp.mkdir(directory);
}
} catch (SftpException e) {
sftp.mkdir(directory);
}
//进入目标路径
sftp.cd(directory);
if(file.isFile()){
InputStream ins = new FileInputStream(file);
//中文名称的
sftp.put(ins, new String(file.getName().getBytes(),"UTF-8"));
//修改权限
sftp.chmod(777, file.getName());
}else{
File[] files = file.listFiles();
for (File file2 : files) {
String dir = file2.getAbsolutePath();
if(file2.isDirectory()){
String str = dir.substring(dir.lastIndexOf(file2.separator));
System.out.println(directory +"/"+str.substring(1));
String directory1 = directory +"/"+str.substring(1);
upload(directory1, dir, sftp);
}else{
upload(directory, dir, sftp);
}
System.out.println("sftp upload file [uploadFile] : " + dir + " successfully");
}
}
}
}
/**
* 上传本地文件到远程服务器
* @param directory
* @param fileName
* @param is
* @param sftp
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public static void copyFile(String directory, String fileName, InputStream is, ChannelSftp sftp) throws Exception{
if(is != null){
try {
Vector content = sftp.ls(directory);
if(content == null){
sftp.mkdir(directory);
}
} catch (SftpException e) {
sftp.mkdir(directory);
}
//进入目标路径
sftp.cd(directory);
sftp.put(is, new String(fileName.getBytes(),"UTF-8"));
sftp.chmod(777, fileName);
} else {
throw new CommonException("100", "上传文件失败");
}
}
/**
* 判断文件夹是否存在
* @param directory
* @param sftp
* @return
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public static boolean isDicExist(String directory, ChannelSftp sftp) throws Exception{
try {
Vector content = sftp.ls(directory);
if(content != null){
return true;
}
} catch (SftpException e) {
throw new CommonException("100", "还原文件失败");
}
return true;
}
/**
* 删除文件夹
* @param directory
* @param sftp
* @return
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public static boolean deleteDic(String directory, ChannelSftp sftp) throws Exception{
try {
Vector content = sftp.ls(directory);
if(content != null){
sftp.rmdir(directory);
}
} catch (SftpException e) {
return true;
// sftp.rmdir(directory);
// throw new CommonException("100", e.getMessage());
}
return true;
}
/**
* 下载文件到本地
* @param directory 目标文件夹
* @param srcFile 目标文件路径
* @param saveFile 保存到本地文件名
* @param sftp
* @param request
* @param response
* @throws UnsupportedEncodingException
* @author Wanghao
*/
@SuppressWarnings({ "rawtypes", "unused" })
public static void download(String directory,String srcFile, String saveFile, ChannelSftp sftp, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
Vector conts = null;
try{
conts = sftp.ls(directory);
} catch (SftpException e) {
e.printStackTrace();
log.debug("罗列文件发生错误", e);
throw new CommonException("100", "下载文件失败");
}
File file = new File(saveFile);
if(!file.exists()) file.mkdir();
//文件
if(srcFile.indexOf(".") > -1){
try {
InputStream in = sftp.get(srcFile);
InputStream fis = new BufferedInputStream(in);
response.reset();
response.setCharacterEncoding("utf-8");
//解决各浏览器的中文乱码问题
String userAgent = request.getHeader("User-Agent");
byte[] bytes = userAgent.contains("MSIE") ? file.getName().getBytes() : file.getName().getBytes("UTF-8");
String fileName = new String(bytes, "ISO-8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + new String( fileName.getBytes("gb2312"), "ISO8859-1" ));
response.setContentType("application/x-msdownload");
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
int size = 0;
int len = 0;
byte[] buf = new byte[1024];
while ((size = fis.read(buf)) != -1) {
len += size;
toClient.write(buf, 0, size);
}
toClient.flush();
toClient.close();
log.info("备份成功...");
} catch (SftpException | IOException e) {
e.printStackTrace();
log.error("sftp下载文件发生错误", e);
throw new CommonException("100", "下载文件失败");
}
}else{
//文件夹(路径)
for (Iterator iterator = conts.iterator(); iterator.hasNext();) {
LsEntry obj = (LsEntry) iterator.next();
String filename = new String(obj.getFilename().getBytes(),"UTF-8");
if(!(filename.indexOf(".") > -1)){
directory = directory + System.getProperty("file.separator") + filename;
srcFile = directory;
saveFile = saveFile + System.getProperty("file.separator") + filename;
}else{
//扫描到文件名为".."这样的直接跳过
String[] arrs = filename.split("\\.");
if((arrs.length > 0) && (arrs[0].length() > 0)){
srcFile = directory + System.getProperty("file.separator") + filename;
}else{
continue;
}
}
download(directory, srcFile, saveFile, sftp, request, response);
}
}
}
}
SSHConnection .java
package cn.easted.edm.core.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Properties;
import org.apache.log4j.Logger;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class SSHConnection {
private static Logger logger = Logger.getLogger(SSHConnection.class);
public static String exeCommand(String host, int port, String username, String password, String command) throws JSchException, IOException {
// PropertyConfigurator.configure("log4j.properties");
JSch jsch = new JSch();
Session session = jsch.getSession(username, host, port);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
int timeout = 60000000;
session.setTimeout(timeout);
session.connect();
ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
channelExec.setCommand(command);
channelExec.setInputStream(null);
channelExec.setErrStream(System.err);
channelExec.connect();
logger.info("连接成功...");
InputStream in = channelExec.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.forName("GBK")));
String buf = null;
StringBuffer sb = new StringBuffer();
while ((buf = reader.readLine()) != null) {
sb.append(buf);
System.out.println(buf);
logger.info(buf);
}
// System.out.println(sb);
close(session, channelExec, reader);
// return sb.toString();
return buf;
}
private static void close(Session session, ChannelExec channelExec, BufferedReader reader) throws IOException {
reader.close();
channelExec.disconnect();
if (null != session) {
session.disconnect();
}
}
public static void main(String[] args) throws Exception {
String userName = "root";
String password = "easted2013";
String host = "10.10.139.157";
int port = 22;
String cmd = "cd /root;ls";
exeCommand(host, port, userName, password, cmd);
}
}