首页 > 技术文章 > Java读取Linux实时文件阻塞的一个折中解决办法

fanpc 2020-08-27 09:49 原文

其实也是无奈之举,远程连接Linux,通过bufferReader()不能获取到实时刷新的输出,获取不到换行符,造成readline()方法阻塞,网上查了下,没有很好的解决办法,使用read也获取不到,于是用了一种比较折中的办法:

首先是远程执行命令的executeBack()方法,这个之前有写过,不再说啥了:

public String executeBack(String ip, String cmd) {
        String username = "root";
        String password = "password";
        try {
            // 创建连接
            Connection conn = new Connection ( ip, 22 );
            // 启动连接
            conn.connect ();
            // 验证用户密码
            conn.authenticateWithPassword ( username, password );
            Session session = conn.openSession ();
            //执行命令
            session.execCommand ( cmd );
            InputStream stdout = new StreamGobbler ( session.getStdout () );
            BufferedReader br = new BufferedReader ( new InputStreamReader ( stdout ) );
            StringBuffer stringBuffer = new StringBuffer ();

            while (true) {
               
                String line = br.readLine ();
                stringBuffer.append ( line );
                if (line == null) {
                    session.close ();
                    break;
                }
            }
            String result = stringBuffer.toString ();
            conn.close ();
            return result;
        } catch (IOException e) {
            e.printStackTrace ();
            return null;
        }
    }

然后,我是想读取xtrabackup的实时备份输出,当读取到"was copied"证明copy成功了,但是这样并不行,于是把输出先重定向到文件里,之后再读文件这样:

public void xtraBack(String port) {

        String backupIp = "xx.xx.xx.xx";
        int checkResult = 0;

        System.out.println ( executeBack ( backupIp, "echo 开始备份" + port + "端口:" ) );
        executeBack ( backupIp, "rm -rf /data/XtraBackup/*" );
        executeBack ( backupIp, "mkdir /data/XtraBackup/" + port );
        executeBack ( backupIp, "innobackupex --defaults-file=/data/" + port + "/conf/my.cnf --socket=/data01/" + port + "/tmp/mysql.sock --user=root --password=password /data0/XtraBackup/" + port+">/data/shell/logs/backup.log 2>&1");
        System.out.println (  port + "端口备份完成,开始验证备份是否成功..." ) ;
       
        //这里加了个定时读取文件的操作,因为备份需要时间,不能一直去查
        if (timeCheck( port ) > 0) {
            System.out.println ( "completed OK! " + port + "端口数据库备份成功!" );
            //return flag;
        } else {
            System.out.println ( "备份失败" );
        }
    }

主要就是把输出通过重定向到log文件里,>/data/shell/logs/backup.log 2>&1,这样就不会阻塞,可以正常结束流程,执行之后的方法 。实时读取真的是太坑了

推荐阅读