Created
December 18, 2014 09:13
-
-
Save numtel/2e9771a16b3470be7101 to your computer and use it in GitHub Desktop.
Tail mysqlbinlog in row mode with Node JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env node | |
| var determineDb = function(lines, startIndex){ | |
| // Look backward from statement at startIndex to find database name used | |
| var result; | |
| for(var i = startIndex; i >= 0; i--){ | |
| result = lines[i].match(/^use (`([^\.]+)`|[^\.\/]+)?/i); | |
| if(result === null) continue; | |
| if(result[2] === undefined){ | |
| return result[1]; | |
| }else{ | |
| return result[2]; | |
| } | |
| } | |
| }; | |
| var tableModEvents = [ | |
| { | |
| type: 'alterTable', | |
| match: /^ALTER TABLE/i | |
| }, | |
| { | |
| type: 'dropTable', | |
| match: /^DROP TABLE/i | |
| }, | |
| { | |
| type: 'createTable', | |
| match: /^CREATE TABLE( IF NOT EXISTS)?/i | |
| }, | |
| { | |
| type: 'truncateTable', | |
| match: /^TRUNCATE/i | |
| }, | |
| { | |
| type: 'insert', | |
| match: /^### INSERT INTO/ | |
| }, | |
| { | |
| type: 'update', | |
| match: /^### UPDATE/ | |
| }, | |
| { | |
| type: 'delete', | |
| match: /^### DELETE FROM/ | |
| } | |
| ]; | |
| var checkTableMod = function(lines, index){ | |
| for(var m = 0; m < tableModEvents.length; m++){ | |
| var result = lines[index].match(tableModEvents[m].match); | |
| var table, db; | |
| if(!result) continue; | |
| var target = lines[index].substr(result[0].length) | |
| .match(/^ (`([^\.]+)`|[^\.]+)?(\.`(.+)`|\..+)?/); | |
| // Map possible regex results to data | |
| // x: value must not be undefined but discard | |
| // t: table name | |
| // d: database name | |
| // -: undefined | |
| var checkRes = ['xt---', 'xxt--', 'xd-xt', 'xd-t-', 'xxdt-', 'xxdxt' ]; | |
| var expect; | |
| for(var p = 0; p < checkRes.length; p++){ | |
| table = undefined; | |
| db = undefined; | |
| for(var i = 0; i < checkRes[p].length; i++){ | |
| expect = checkRes[p][i]; | |
| if((expect === '-' && target[i] !== undefined) || | |
| ((expect === 'x' || expect === 't') && target[i] === undefined)){ | |
| break; | |
| } | |
| if(expect === 't') table = target[i]; | |
| else if(expect === 'd') db = target[i]; | |
| } | |
| if(i === checkRes[p].length) break; | |
| } | |
| if(!db) db = determineDb(lines, index); | |
| if(table.substr(0, 1) === '.') table = table.substr(1); | |
| return { | |
| type: tableModEvents[m].type, | |
| table: table, | |
| db: db | |
| }; | |
| } | |
| }; | |
| // include db in cmd params | |
| var binlog = '/usr/bin/mysqlbinlog -v --base64-output=DECODE-ROWS --start-position=%d %s', | |
| exec = require('child_process').exec, | |
| fs = require('fs'), | |
| output = function (e, out, err) { | |
| console.log(out); | |
| // event emitters | |
| var lines = out.split("\n"); | |
| for (var i=0; i < lines.length; i++) { | |
| var tableMod = checkTableMod(lines, i); | |
| tableMod && console.log(tableMod); | |
| } | |
| }, | |
| util = require('util'), | |
| tail = function (e, out, err) { | |
| var logfile = out.replace(/(\n|\r)+$/, ''); | |
| var prev = fs.statSync(logfile); | |
| console.log('tailing ' + logfile + '...'); | |
| fs.watch(logfile , function (evt, filename) { | |
| console.log(arguments, prev); | |
| var cmd = util.format(binlog, prev.size, logfile); | |
| console.log(cmd); | |
| exec(cmd, output); | |
| prev = fs.statSync(logfile); | |
| }); | |
| }; | |
| exec('ls -t /var/log/mysql/mysql-bin* | head -n1', tail ); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I began working on this as an update to https://gist.github.com/petethomas/1572119 but am not going to use this approach. Instead, the
zongjiNPM module seems like a better way to accomplish this task.