Mysql8.0以上版本 实现两台服务器互相备份同步 (主主互备) java封装实现,复制即用

mysql指令实现

ServA:192.168.1.1

ServB:192.168.1.2

1.查看3306端口是否互通

telnet 192.168.1.1 3306
telnet 192.168.1.2 3306

2.同步基础数据 保持两个库表数据一致性

将1.1数据库数据同步覆盖到 1.2 数据库中 – 在此之前两个库表的结构要一致
–ignore-table=database库名.table表名 – 表示不需要同步的数据表

mysqldump -h192.168.1.1 -uroot -proot -P3306 
--default-character-set=utf8
--ignore-table=database库名.table表名 
database库名 | mysql -h192.168.1.2 -uroot -proot -P3306 --default-character-set=utf8 database库名

3.修改配置文件my.cnf 两台服务其都要执行

[client]
port=3306
socket=/tmp/mysql.sock

[mysqld]
skip-name-resolve
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
lower_case_table_names=1
port=3306
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
pid-file=/usr/local/mysql/mysql.pid
socket=/tmp/mysql.sock
log_error=/usr/local/mysql/error.log
server-id=102
lower_case_table_names=1
max_connections=1000
secure-file-priv = ''
log-bin=MySQL-bin  # 开启mysql binlog功能
binlog-do-db=database      #需要同步的库
replicate-do-db=database      #需要同步的库
replicate-wild-ignore-table=database.tables #不许需要同步的数据库表
slave-net-timeout=60

4.重启数据库

systemctl restart mysqld

5.创建同步用户 两台服务其都要执行

#mysql8.0创建同步用户   两台服务其都要执行
#删除同步用户 命令 mysql -uroot -p  -e'DROP USER 'slave'@'%';flush privileges;'
# 创建用户 slave  密码123456  设置访问权限 %
mysql -uroot -p -e"CREATE USER 'slave'@'%' IDENTIFIED BY '123456';"
# 赋予权限
mysql -uroot -p -e"GRANT ALL PRIVILEGES ON *.* TO 'slave'@'%' WITH GRANT OPTION;"
# mysql8.0  需要修改下用户的连接方式
mysql -uroot -p -e"ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';flush privileges;"

#mysql8.4创建同步用户   两台服务其都要执行
#删除同步用户 命令 mysql -uroot -p  -e'DROP USER 'slave'@'%';flush privileges;'
# 创建用户 slave  密码123456  设置访问权限 %
mysql -uroot -p -e"CREATE USER 'slave'@'%' IDENTIFIED BY '123456';"
# 赋予权限
mysql -uroot -p -e"GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' WITH GRANT OPTION;"
mysql -uroot -p -e"GRANT SUPER ON *.* TO 'slave'@'%' WITH GRANT OPTION;"
#数据库1.1执行  登录-h1.2 将密钥发送到1.2
mysql -uslave -h192.168.1.2 -p'123456' --get-server-public-key
#数据库1.2执行  登录-h1.1 将密钥发送到1.1
mysql -uslave -h192.168.1.1 -p'123456' --get-server-public-key

6.获取1.1服务器同步信息 配置1.2的同步信息

# mysql8.0获取1.1服务器同步信息  配置1.2的同步信息
# 1.2 执行  获取 master_log_file  和 master_log_pos 信息
mysql -uroot -proot -e"show master status;"
# 1.1 执行
mysql -uroot -proot -e"change master to master_host='192.168.1.2',master_user='slave',master_password='123456',master_log_file='MySQL-bin.000002',master_log_pos=301126;"

# mysql8.4获取1.1服务器同步信息  配置1.2的同步信息
# 1.2 执行  获取 master_log_file  和 master_log_pos 信息
mysql -uroot -proot -e"show binary log status;"
# 1.1 执行
mysql -uroot -proot -e"CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.1.2',SOURCE_USER='slave',SOURCE_PASSWORD='123456',SOURCE_LOG_FILE='MySQL-bin.000002',SOURCE_LOG_POS=301126;"

7.获取1.2服务器同步信息 配置1.1的同步信息

# mysql8.0获取1.2服务器同步信息  配置1.1的同步信息
# 1.1 执行  获取 master_log_file  和 master_log_pos 信息
mysql -uroot -proot -e"show master status;"
# 1.2 执行
mysql -uroot -proot -e"change master to master_host='192.168.1.1',master_user='slave',master_password='123456',master_log_file='MySQL-bin.000002',master_log_pos=301126;"

# mysql8.4获取1.2服务器同步信息  配置1.1的同步信息
# 1.1 执行  获取 master_log_file  和 master_log_pos 信息
mysql -uroot -proot -e"show binary log status;"
# 1.2 执行
mysql -uroot -proot -e"change replication source to source_host='192.168.1.1',source_user='slave',source_password='123456',source_log_file='MySQL-bin.000002',source_log_pos=301126;"

8.启动同步 两台服务其都要执行

#mysql8.0启动同步 
mysql -uroot -proot -e"start slave;"

#mysql8.4启动同步 
mysql -uroot -proot -e"start replica;"

9.查看同步状态

#mysql8.0查看同步状态
mysql -uroot -proot -e"show slave status\G;"
#Slave Io Running:Yes
#Slave sol Running: Yes
#这两项为 yes 为成功
# Last Errno: 会展示异常信息  根据信息 自行查询问题

#mysql8.4查看同步状态
mysql -uroot -proot -e"show replica status\G;"

以下java实现的未写入8.4以后版本的改动,需要根据上面的修改部分代码

创建工具类MysqlSlaveUtil—java工具类版本

package ;

import ch.ethz.ssh2.Connection;
import cn.hutool.core.io.resource.ClassPathResource;
import com.mysql.cj.x.protobuf.MysqlxDatatypes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author lpx
 * 用于数据库数据同步和主主配置  适配8.0以上的数据库版本
 * 在此之前请给root用户足够权限
 * GRANT SYSTEM_USER ON *.* TO 'root'@'%' WITH GRANT OPTION;
 * FLUSH PRIVILEGES;
 * GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
 * FLUSH   PRIVILEGES;
 */
@Slf4j
@Component
public class MysqlSlaveUtil {

    @Autowired
    private DMruntimeUtil dMruntimeUtil ;

    private  final String CONF="[client]\n" +
            "port=3306\n" +
            "socket=/root/mysql/mysql.sock\n" +
            "\n" +
            "[mysqld]\n" +
            "skip-name-resolve\n"+
            "sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION\n" +
            "lower_case_table_names=1\n" +
            "port=3306\n" +
            "basedir=/root/mysql\n" +
            "datadir=/root/mysql/data\n" +
            "pid-file=/root/mysql/mysql.pid\n" +
            "socket=/tmp/mysql.sock\n" +
            "log_error=/root/mysql/error.log\n" +
            "server-id={serverId}\n" +
            "lower_case_table_names=1\n" +
            "max_connections=1000\n" +
            "secure-file-priv = ''\n" +
            "log-bin=MySQL-bin  # 开启mysql binlog功能\n" +
            "binlog-do-db={DBbinlog}      #需要同步的库\n" +
            "replicate-do-db={DBreplicate}    #需要同步的库\n" +
            "replicate-wild-ignore-table={DBreplicate}.tables   #不许需要同步的数据库表--写自己的配置表\n" +
            "slave-net-timeout=60";

    /**
     * 同步数据库数据--方法
     * hostIp   源服务器IP
     * hostUser 源服务器数据库用户名
     * hostPass 源服务器数据库用户密码
     * targetIp 目标服务器IP
     * targetUser 目标服务器数据库用户名
     * targetPass 目标服务器数据库用户密码
     * DBname   需要同步数据的数据库名称
     * @return
     */
    public  List<String> mysqlDump(String hostIp, String hostUser, String hostPass
            , String targetIp, String targetUser, String targetPass, String DBname){
        List<String> cmds = new ArrayList<String>();
        /**  同步两台服务器数据指令-----------------------------
         * mysqldump -h192.168.1.1 -uroot -proot -P3306 --default-character-set=utf8
         * --ignore-table=database库名.table表名
         * | mysql -h192.168.1.2 -uroot -proot -P3306 --default-character-set=utf8 database库名
         */
        String cmd = " mysqldump " +
                "-h"+hostIp+" " +
                "-u"+hostUser+" " +
                "-p"+hostPass+" " +
                "-P3306 --default-character-set=utf8  " +
                "--ignore-table="+DBname+".t_route_info "+
                "--ignore-table="+DBname+".t_virt_net_info "+
                "--ignore-table="+DBname+".t_virt_server_info "+
                DBname+" | mysql " +
                "-h"+targetIp+" " +
                "-u"+targetUser+" " +
                "-p"+targetPass+" " +
                "-P3306 --default-character-set=utf8  " +
                DBname+";";
        cmds.add(cmd);
        return cmds;
    }

    /**
     * 限制3306的端口访问权限
     * 允许来自服务器B的TCP 3306流量:
     * sudo iptables -A INPUT -p tcp -s 192.168.1.2 --dport 3306 -j ACCEPT
     * (可选)拒绝所有其他到3306端口的流量:
     * 这一步实际上是可选的,因为如果你的INPUT链默认是DROP,那么不需要显式拒绝。但如果你想要明确这一点,可以添加以下规则(但请注意,这应该在允许来自服务器B的流量之后添加,以确保不会意外阻止它):
     * sudo iptables -A INPUT -p tcp --dport 3306 -j DROP
     * 然而,通常推荐的做法是设置一个默认的DROP规则在链的末尾,而不是为特定端口添加DROP规则。
     * 确保有默认的DROP规则(如果尚未设置):
     * sudo iptables -P INPUT DROP
     * 这条命令会将INPUT链的默认策略设置为DROP,意味着所有未明确允许的数据包都将被拒绝。注意,这条命令会影响所有进入服务器的数据包,而不仅仅是到3306端口的。
     * 保存iptables规则(根据你的Linux发行版):
     * sudo service iptables save
     */
    public  void  iptablesPort(String masterIp,String backupIp,String masterPort,String backPort){

        String cmd ="sudo iptables -A INPUT -p tcp -s "+backupIp+" --dport 3306 -j ACCEPT";
        DMruntimeUtil(masterIp,masterPort,cmd);
        cmd ="sudo iptables -A INPUT -p tcp -s "+masterIp+" --dport 3306 -j ACCEPT";
        DMruntimeUtil(backupIp,backPort,cmd);
        cmd ="sudo iptables -A INPUT -p tcp --dport 3306 -j DROP";
        DMruntimeUtil(masterIp,masterPort,cmd);
        DMruntimeUtil(backupIp,backPort,cmd);
        cmd ="sudo service iptables save";
        DMruntimeUtil(masterIp,masterPort,cmd);
        DMruntimeUtil(backupIp,backPort,cmd);
    }
    /**
     * 配置数据库主从配置,并开启主从配置的方法
     * @param masterIp   主服务器IP
     * @param masterUser 主服务器数据库用户
     * @param masterPass 主服务器数据库密码
     * @param userName   创建同步用户  用户名
     * @param password   创建同步用户  密码
     * @param backupIp   从服务器IP
     * @param DBname     备份数据库名称
     * @param proPath    数据库配置文件路径
     * @param backupName  从服务器数据库用户
     * @param backupPass    从服务器数据库密码
     * @return
     */
    public  Boolean mysqlPropert(String masterIp,int masterServerId,int backupServerId,String masterUser,
                                            String masterPass, String userName,
                                            String password,String backupIp,
                                            String backupName,String backupPass,
                                            String DBname, String proPath){

        String masterPort  =  "8080";
        String backPort  =  "8080";

        /**
         * 采取http接口方式来同步数据指令----------------
         * cmdA本机执行的mysql命令
         * cmdB另一台要执行的mysql命令
         */
        List<String> cmdA = new ArrayList<String>();
        List<String> cmdB = new ArrayList<String>();

        /**
        1.修改 数据库配置文件  /root/mysql/my.cnf   主从都要改
         */
        String conf = CONF.replace("{DBbinlog}",DBname).replace("{DBreplicate}",DBname).replace("{serverId}",masterServerId+"");
        String cmd ="echo \""+conf+"\"  >  "+proPath;
        if(null == dMruntimeUtil.login(masterIp,masterPort,cmd)){
            log.error("主服务器 修改 数据库配置文件 Linux指令执行失败!");
        }
        conf= CONF.replace("{DBbinlog}",DBname).replace("{DBreplicate}",DBname).replace("{serverId}",backupServerId+"");
        String cmd2 ="echo \""+conf+"\"  >  "+proPath;
        if(null == dMruntimeUtil.login(backupIp,backPort,cmd2)){
            log.error("备服务器 修改 数据库配置文件 Linux指令执行失败!");
        }




        /**
        2.重启mysql数据库  主从都要进行重启
         */
        ClassPathResource resource = new ClassPathResource("system.properties");
        Properties properties = new Properties();
        try {
            properties.load(resource.getStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            cmd = "bash " + properties.getProperty("linux.mysql.path") +" restart";
            if(!DMruntimeUtil(masterIp,masterPort,cmd)){
                return false;
            }
            if(!DMruntimeUtil(backupIp,backPort,cmd)){
                return false;
            }
            /**
             * 睡眠一下----防止数据库没有重启完毕,导致后续指令执行异常
             */
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /**
         3.删除 同步用户DROP USER 'slave'@'%'信息,避免再次添加时的问题;
         */
        cmd ="mysql  -u"+masterUser+" -p"+masterPass+" " +
                "-e'DROP USER \""+userName+"\"@\"%\";flush privileges;'";
        DMruntimeUtil(masterIp,masterPort,cmd);
        DMruntimeUtil(backupIp,backPort,cmd);

        /**
         4.创建用于复制的专门用户,并刷新用户权限
        * mysql8.3
         * 创建用户 slave  密码123456  设置访问权限 %
        * mysql -uroot -p"password" -e"CREATE USER 'slave'@'%' IDENTIFIED BY '123456';"
         * 赋予权限
        * mysql -uroot -p"password" -e"GRANT ALL PRIVILEGES ON *.* TO 'slave'@'%' WITH GRANT OPTION;"
         * */
        cmd ="mysql -hlocalhost -p3306 -u"+masterUser+" -p"+masterPass+" " +
                "-e'CREATE USER \""+userName+"\"@\"%\" IDENTIFIED BY \""
                +password+"\"; flush privileges;'";
        if(!DMruntimeUtil(masterIp,masterPort,cmd)){
            return false;
        }
        cmd ="mysql -hlocalhost -p3306 -u"+masterUser+" -p"+masterPass+" " +
                "-e'GRANT ALL PRIVILEGES ON *.* TO \""+userName+"\"@\"%\" WITH GRANT OPTION; flush privileges;'";
        if(!DMruntimeUtil(masterIp,masterPort,cmd)){
            return false;
        }
        cmd ="mysql -hlocalhost -p3306 -u"+backupName+" -p"+backupPass+" " +
                "-e'CREATE USER \""+userName+"\"@\"%\" IDENTIFIED BY \""
                +password+"\"; flush privileges;'";
        if(!DMruntimeUtil(backupIp,backPort,cmd)){
            return false;
        }
        cmd ="mysql -hlocalhost -p3306 -u"+backupName+" -p"+backupPass+" " +
                "-e'GRANT ALL PRIVILEGES ON *.* TO \""+userName+"\"@\"%\" WITH GRANT OPTION; flush privileges;'";
        if(!DMruntimeUtil(backupIp,backPort,cmd)){
            return false;
        }


        /**
         5.mysql8.0  需要修改用户的连接方式
         * ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';flush privileges;
         */
        cmd = "mysql -hlocalhost -p3306 -u"+masterUser+" -p"+masterPass+" " +
                "-e'ALTER USER  \""+userName+"\"@\"%\" IDENTIFIED WITH mysql_native_password BY \""+password+"\"; flush privileges;'";
        if(!DMruntimeUtil(masterIp,masterPort,cmd)){
            return false;
        }
        cmd = "mysql -hlocalhost -p3306 -u"+backupName+" -p"+backupPass+" " +
                "-e'ALTER USER  \""+userName+"\"@\"%\" IDENTIFIED WITH mysql_native_password BY \""+password+"\"; flush privileges;'";
        if(!DMruntimeUtil(backupIp,backPort,cmd)){
            return false;
        }

        /**
         6.获取1.1主服务器同步信息
        * mysql -uroot -proot -e"show master status;"
        * */
        cmd ="mysql  -u"+masterUser+" -p"+masterPass+" " +
                "-e'show master status;'";
        Map<String, Object> result = dMruntimeUtil.login(masterIp,masterPort,cmd);
        if(null == result){
            log.error("获取主服务器同步信息--Linux指令执行失败:{}");
        }
        String value = (String) result.get("value");
        String[] arrs = value.split("\n");
        String[] arr = arrs[arrs.length-1].split("\t");
        /**
         6.1.配置从服务器  同步信息
        * change master to master_host='192.168.1.1',master_user='slave',master_password='123456',master_log_file='MySQL-bin.000002',master_log_pos=301126;
        * */
        cmd ="mysql -u"+backupName+" -p"+backupPass+" " +
                "-e'change master to master_host=\""+masterIp+"\",master_user=\""+userName+"\"," +
                "master_password=\""+password+"\",master_log_file=\""+arr[0]+"\"," +
                "master_log_pos="+arr[1]+";'";
        cmdB.add(cmd);


        /**
         7.获取1.2备服务器同步信息
         * mysql -uroot -proot -e"show master status;"
         * */
        cmd ="mysql -h"+backupIp+" -u"+backupName+" -p"+backupPass+" " + "--port=3306 "+
                "-e'show master status;'";
        result = dMruntimeUtil.login(backupIp,backPort,cmd);
        if(null == result){
            log.error("mysql数据同步http接口同步Linux指令为 null");
        }
        value = (String) result.get("value");
        arrs = value.split("\n");
        for (int i = 0; i <arrs.length ; i++) {
        }
        arr = arrs[arrs.length-1].split("\t");
        /**
         7.1.配置主服务器  同步信息
         * change master to master_host='192.168.1.2',master_user='slave',master_password='123456',master_log_file='MySQL-bin.000002',master_log_pos=301126;
         * */
        cmd ="mysql -h"+masterIp+" -u"+masterUser+" -p"+masterPass+" " +
                "-e'change master to master_host=\""+backupIp+"\",master_user=\""+userName+"\"," +
                "master_password=\""+password+"\",master_log_file=\""+arr[0]+"\"," +
                "master_log_pos="+arr[1]+";'";
        cmdA.add(cmd);


        /**
         8.启动同步
        * start slave;
        * */
        cmd ="mysql -h"+masterIp+" -u"+masterUser+" -p"+masterPass+" " +
                "-e'start slave;'";
        cmdA.add(cmd);
        cmd ="mysql -h"+backupIp+" -u"+backupName+" -p"+backupPass+" " +
                "-e'start slave;'";
        cmdB.add(cmd);
        for (String cmdt :cmdA) {
            if(DMruntimeUtil(masterIp,masterPort,cmdt)){
            }else{
                return false;
            }
        }
        for (String cmdt :cmdB) {
            if(DMruntimeUtil(backupIp,backPort,cmdt)){
            }else{
                return false;
            }
        }
        return true;
    }

    public  Boolean DMruntimeUtil(String Ip,String ServerPort,String cmd) {
        Map<String, Object> result = dMruntimeUtil.login(Ip,ServerPort,cmd);
        if(null == result){
            log.error("mysql数据同步http接口同步Linux指令为 null");
        }
        String value = (String) result.get("value").toString().replace("error.log","");
        if(value.contains("Error") || value.contains("error") ||value.contains("ERROR")){
            log.error("mysql数据同步http接口同步Linux指令执行失败:"+Ip);
            log.error("mysql数据同步http接口同步Linux指令执行失败:"+cmd);
            log.error("mysql数据同步http接口同步Linux指令执行失败:"+value);
            return false;
        }else{
            return true;
        }
    }


    /**
     * 综合调用 同步以及配置主从开启的方法  统一入参
     * @param masterIp   主服务器IP
     * @param masterServerId   主服务器serverId
     * @param backupServerId   备服务器serverId
     * @param masterUser 主服务器数据库用户
     * @param masterPass 主服务器数据库密码
     * @param userName   创建同步用户  用户名
     * @param password   创建同步用户  密码
     * @param backupIp   从服务器IP
     * @param DBname     备份数据库名称
     * @param proPath    数据库配置文件路径
     * @param backupName  从服务器数据库用户
     * @param backupPass    从服务器数据库密码
     * @return
     */
    public  String msyqlAll(String masterIp,int masterServerId,int backupServerId,String masterUser,
                                  String masterPass, String userName,
                                  String password,String backupIp,
                                  String backupName,String backupPass,
                                  String DBname, String proPath){
        List<String> cmds =  mysqlDump(masterIp,masterUser,masterPass
                ,backupIp,backupName,backupPass,DBname);
        for (String cmd:cmds) {
            Map<String, Object> result = dMruntimeUtil.login(masterIp,cmd);
            if(null == result){
                log.error("mysql数据同步http接口同步Linux指令为 null");
            }
            String value = (String) result.get("value");
            if(value.contains("Error") || value.contains("error")){
                log.error("mysql数据同步http接口同步Linux指令执行失败:"+value);
                return value;
            }
        }
       boolean type =  mysqlPropert(masterIp,masterServerId,backupServerId,masterUser, masterPass,userName,password, backupIp,backupName,
                backupPass, DBname,proPath);
        if(type){
            return "success";
        }
        return "error";
    }

    /**
     *  停止并删除 主从关系以及配置数据信息
     * @param masterIp   主服务器IP
     * @param masterPort   主服务器IP
     * @param backupIp    从服务器IP
     * @param backupPort    从服务器IP
     * @param backupName  从服务器数据库用户
     * @param backupPass  从服务器数据库密码
     * @param masterName  主服务器数据库用户
     * @param masterPass  主服务器数据库密码
     * @return
     */
    public  String stopMysqlSlave(String masterIp, String masterPort, String backupIp, String backupPort, String backupName,String backupPass,
                                  String masterName,String masterPass){
        /*
         * stop slave 停止主从同步
         * reset slave all  删除所有与主库之间的关联,如需再次启动需要重新配置连接信息
         * */
        String  cmd ="mysql -h"+masterIp+" -u"+masterName+" -p"+masterPass+" " +
                "-e'stop slave;reset slave all;'";
        Map<String, Object> result = dMruntimeUtil.login(masterIp,masterPort,cmd);
        if(null == result){
            log.error("mysql数据同步http接口同步Linux指令执行失败:{}",cmd);
        }
        String value = (String) result.get("value");
        if(value.contains("Error") || value.contains("error") ||value.contains("ERROR")){
            log.error("命令::"+cmd+"执行失败::"+value);
            return value;
        }else{
            log.info("命令::"+cmd+"执行成功::"+value);
        }
        cmd ="mysql -h"+backupIp+" -u"+backupName+" -p"+backupPass+" " +
                "-e'stop slave;reset slave all;'";
        result = dMruntimeUtil.login(backupIp,backupPort,cmd);
        if(null == result){
            log.error("mysql数据同步http接口同步Linux指令执行失败:{}",cmd);
        }
        value = (String) result.get("value");
        if(value.contains("Error") || value.contains("error") ||value.contains("ERROR")){
            log.error("命令::"+cmd+"执行失败::"+value);
            return value;
        }else{
            log.info("命令::"+cmd+"执行成功::"+value);
        }
        return "success";
    }
}

工具类 DMruntimeUtil

package utils;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *工具类
 */
@Slf4j
@Component
public class DMruntimeUtil {
    private static final String DEFAULT_CHARSET = "utf-8";

    private static final  Logger LOGGER = LoggerFactory.getLogger(DMruntimeUtil.class);

    private String PRE_SERVER_URL = "http://{ip}:{port}/linuxBash/linuxBash";

    /**
     * 改成发送http请求
     *ip 要执行linux指令的服务器IP
     *cmd 要执行的指令
     *
     */
    public Map<String, Object> login(String ip,String port ,String cmd) {
        Map<String, Object> result = new HashMap<>();
        try {
            //如果是数据库同步  延迟2秒
            if("restart".equals(cmd)){
                 Thread.sleep(2000);
            }
            String url = PRE_SERVER_URL.replace("{ip}",ip);
            url = url.replace("{port}",port);
            //自己做一下数据加密  把cmd给加密了 保证一下安全性
            log.info("发送同步指令url="+url);
            String resp = HttpSendUtils.sendPostWb(url,"application/json",Base64.toBase64String(cmd));
            log.error("-==[linuxBashSyncHttpSyncUtil resp:{} ]==- ",resp);
            if(StringUtils.isNotEmpty(resp)){
                JSONObject jsonObjectResp = JSONObject.fromObject(resp);
                if(StatusCode.SUCCESS.code.intValue() == jsonObjectResp.getInt("code")){
                    result.put("value",jsonObjectResp.getString("value"));
                    return result;
                }else{
                    log.error("-==[linuxBashSyncHttpSyncUtil sendRequest ERROR ]==- ");
                }
            }else{
                log.error("-==[linuxBashSyncHttpSyncUtil sendRequest ERROR ]==- Access server exception");
            }
        } catch (Exception e) {
            log.error("-==[linuxBashSyncHttpSyncUtil sendRequest Exception ]==- ");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 改成发送http请求
     *ip 要执行linux指令的服务器IP
     *cmd 要执行的指令
     *
     */
    public Map<String, Object> login(String ip ,String cmd) {
        Map<String, Object> result = new HashMap<>();
        try {
            //根据IP获取管理平台端口号
            String port ="8080";
            String url = PRE_SERVER_URL.replace("{ip}",ip);
            url = url.replace("{port}",port);
            //自己做一下数据加密  把cmd给加密了 保证一下安全性  
            String resp = HttpSendUtils.sendPostWb(url,"application/json",Base64.toBase64String(cmd));
            log.error("-==[linuxBashSyncHttpSyncUtil resp:{} ]==- ",resp);
            if(StringUtils.isNotEmpty(resp)){
                JSONObject jsonObjectResp = JSONObject.fromObject(resp);
                if(StatusCode.SUCCESS.code.intValue() == jsonObjectResp.getInt("code")){
                    result.put("value",jsonObjectResp.getString("value"));
                    return result;
                }else{
                    log.error("-==[linuxBashSyncHttpSyncUtil sendRequest ERROR ]==- ");
                }
            }else{
                log.error("-==[linuxBashSyncHttpSyncUtil sendRequest ERROR ]==- Access server exception");
            }
        } catch (Exception e) {
            log.error("-==[linuxBashSyncHttpSyncUtil sendRequest Exception ]==- ");
            e.printStackTrace();
        }
        return null;
    }
        /**
     * 远程执行shll脚本或者命令
     *
     * @param cmd 即将执行的命令
     * @return 命令执行完后返回的结果值
     */
    public static Map<String, Object> execute(String cmd) {
    	Map<String, Object> result =  new HashMap<String, Object>(16);
        try {
            Process p = Runtime.getRuntime().exec(new String[]{"sh", "-c", cmd});
            result = processStdout(p.getInputStream(), DEFAULT_CHARSET);
            // 如果为得到标准输出为空,说明脚本执行出错了
            if (StringUtils.isBlank(result.get("value")+"")) {
                LOGGER.info("得到标准输出为空,执行的命令:" + cmd);
                result = processStdout(p.getErrorStream(), DEFAULT_CHARSET);
            } else {
                LOGGER.info("执行命令成功,执行的命令:" + cmd);
            }
        } catch (IOException e) {
            LOGGER.error("执行命令失败,执行的命令:" + cmd + "  " , e);
            result= null;
        }
        System.out.println(result.toString());
        return result;
    }
}

接口 LinuxBashController

package ;


import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/linuxBash")
public class LinuxBashCmdController {

    @PostMapping("")
    public LinuxBashSycnRespVo linuxBashSync(@RequestBody String info) {
       
        try {
        /*
        解密数据 获取cmd info
        */
            Map<String, Object> result = DMruntimeUtil.execute(info);
            if(null != result){
                linuxBashSycnRespVo.setCode(StatusCode.SUCCESS.code.intValue());
                linuxBashSycnRespVo.setValue((String) result.get("value"));
            }else {
                linuxBashSycnRespVo.setCode(StatusCode.ERROR.code.intValue());
            }
            log.info("-==[LinuxBashCmdController linuxBashSync end]==- ");
        } catch (Exception e) {
            linuxBashSycnRespVo.setCode(StatusCode.ERROR.code.intValue());
            e.printStackTrace();
        }
        return linuxBashSycnRespVo;
    }

  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Heart&Fire

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值