SSH从远程服务器备份还原文件

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);

    }  
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值