【区块链】关于ETH/BTC区块的监控
此次我写的是一个小型的shell, 链接钉钉的机器人, 使用过的应该会比较娴熟的了,下面就简述一下把
主要的功能就是, 当发现本地数据库区块跟网络上的区块差距相差较大的时候就代表, 数据同步有问题, 这个时候, 发出一条告警出来,
对于比特网络来说,我用的是https://blockchair.com/
注意到的哥们已经发现了, 在首页的下方就是它的API, 我用的是比较愚蠢的方式去调用它, 直接用curl吧, 躁一把.
也可以点进去查询它的相关调用, 这里面所调用的币种也是换汤不换药, 比如以下的, 就是取到指定币种的网络信息, 先拿下来分析一下把
1 2 3 4 5 6 7 8 | https: //api .blockchair.com /bitcoin/stats https: //api .blockchair.com /bitcoin-cash/stats https: //api .blockchair.com /litecoin/stats https: //api .blockchair.com /bitcoin-sv/stats https: //api .blockchair.com /dogecoin/stats https: //api .blockchair.com /dash/stats https: //api .blockchair.com /groestlcoin/stats https: //api .blockchair.com /bitcoin/testnet/stats 我 |
直接用curl了,取到信息了, 如下
但是有时候使用curl会给我弹出total这些渣渣字段, 很不喜欢, 所以, 发招用s参数吧, 以防万一
1 | curl -s https: //api .blockchair.com /ethereum/stats |
取到的数据很明显了, 就是一个json格式的, 难道我还要去弄一个工具去格式化它? 非也
在linux中, 想必大家都知道,jq命令就能显示格式化json, 如果没有的话安装一下
1 | yum install jq -y |
这样就好办很多了, 我们可以先把curl定义下来的东西重定向到一个文件中去啊, 然后用jq去分析那个文件不就行了吗, 接下来数据就变成这样了
1 2 3 | [root@tx ~] # curl -s https://api.blockchair.com/ethereum/stats > block [root@tx ~] # jq ".data.blocks" block 9551780 |
你看, 直接取到网络上最新块的高度了, 但是, 为什么会这样取呢, 其实用了jq之后格式是这样的了, 用过的应该就很清楚
看, 活生生就是一个json, 我用的是.data.blocks, 就是直接把高度过滤出来而已.
那么接下来就是, 去取本地数据库中的高度了, 我这边用的是mysql, 直接就拿他开刀
1 2 3 4 5 6 7 8 9 | [root@tx ~] # /data/tools/mysql -uroot -prkm2020 -S /tmp/mysql.sock -P 3306 -e "select cfg_val from db_config.tb_sysconfig where cfg_name='cache.usdt_erc20_sync_bcnum';" mysql: [Warning] Using a password on the command line interface can be insecure. +---------+ | cfg_val | +---------+ | 9519439 | +---------+ [root@tx ~] # [root@tx ~] # |
看, 这就是我本地的高度, 但是, 如果你想拿这个9519439跟上面网络上取到的高度去对比, 那么就不得不去掉mysql查询格式出来的框框, 其实这里可以使用-N -s参数, 到底有什么用呢, 自行百度
1 2 3 4 5 | [root@tx ~] # /data/tools/mysql -uroot -prkm2020 -S /tmp/mysql.sock -P 3306 -N -s -e "select cfg_val from db_config.tb_sysconfig where cfg_name='cache.usdt_erc20_sync_bcnum';" mysql: [Warning] Using a password on the command line interface can be insecure. 9519439 [root@tx ~] # [root@tx ~] # |
看, 直接抠出来了, 上面还有一个提醒是吧, 其实不影响, 你直接把值取出来, 然后扔给一个变量去做对比, 是没问题的
那么直接就看shell吧
这是一个完整的shell !
解析器在写的时候可以自行添加.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | currencyType= "ethereum" MYSQL_CONN= "/data/tools/mysql -uroot -prkm2020 -S /tmp/mysql.sock -P 3306 -N -s" N=0 function dingding(){ hostname =` hostname ` webhook= "https://oapi.dingtalk.com/robot/send?access_token=4db55f9cd1f96921acd6187d4431641e68bc39923d84d24fe0dbd" currTime1=` echo $( date + "%Y-%m-%d.%T" )` curl '' $webhook '' \ -H 'Content-Type: application/json' \ -d '{ "msgtype" : "text" , "text" : { "content" : " 服务器: '$hostname' 发生: '$currencyType' 区块数据同步异常! [ 提醒主机: '$hostname' 提醒信息: 区块数据同步异常 监控币种: '$currencyType' 进程同步区块: '$local_height' 网络最新区块: '$netwo_height' 区块差距: '$value' 提醒时间: '$currTime1' ] " } }' } function check(){ local_height=`$MYSQL_CONN -e "select cfg_val from db_config.tb_sysconfig where cfg_name='cache.usdt_erc20_sync_bcnum';" ` curl -s https: //api .blockchair.com/${currencyType} /stats > /tmp/netwo_height netwo_height=`jq ".data.blocks" /tmp/netwo_height ` value=$[netwo_height - local_height] echo $( date + "%Y-%m-%d.%T" ),$value if [ $value - ge 6 ]; then dingding N=$[N+1] sleep 600; else N=0 fi } function main(){ while : do sleep 180; if [ $N == 0 ]; then check else if [ $N - ge 2 ]; then sleep 300; check else sleep 50; check fi fi done } main |
首先, 我把币种声明变量扔在了文件的开头位置, 下面就直接去识别, 就是这个
1 | currencyType= "ethereum" |
需要监控其他的可以换成其他的, 比如bitcoin等
然后我为了偷懒, 把mysql的连接code, 塞进一个变量里面去, 为了下面方便调用它
dingding模块应该没什么好说的了, 检查模块, 无非就是拿出数据库中的高度, 跟网络上重定向分析出来的高度做对比, 用最新的高度减去本地区块, 得出差距, 我这边设置是在6个节点, 如果大于等于6, 那发个信息出来吧,
肯定有人疑问, N是什么鬼, N就是一个统计告警数, 为了不让告警太频繁
比如我下面的main的主体调用模块, 3分钟检测一下,如果N等于0, 那就是说, 一切正常, 那么如果说, 发现了一次告警, 那么N+1, 发了一次信息, 等待10分钟, 再检测, 如果10分钟后还是没有恢复, 还来告警, 那么N再+1, 那就是跑了下面的大于或等于2的时候那个条件了, 再等待5分钟然后再检查, 如果说, 在这次死循环中, 告警过后恢复正常了, 然后N会被重置为0, 一切还是原来的模样.
那么钉钉出来是怎么样的呢, 这样的
目的是什么, 主要是为了让服务器本地环境与网络上的区块环境实现一致同步, 如果服务器的程序出现问题, 那么就能第一时间知道, 然后着手处理,
对于为什么不用golang去写, 因为golang不会写, bash更简单, 但最不完美的就是, 可能死循环造成的资源消耗远比golang小工具的多?
有待研究。
就到这里。