日志回收 shell 脚本
PS: 后来发现这方法实在太蠢了,还是 awk 靠谱,具体戳这里
接到一个日志回收记录的活,本来想着用 node 或者 python 快速搞定就好了, 结果线上机居然啥都没有,看来只能用 shell 了,正巧之前都没怎么写过太复杂的 shell, 刚好练下手。
读取文件
shell 读取文件有很多方法,可以用 read line 也可以用 cat,怎么顺手怎么来就好了。 由于提取日志须要做正则,为了避免做太多多余的匹配,使用的是 grep 来过滤掉不带有回收标记的日志,然后再用管道传给 sed 方法提取须要的字段。
过滤数据
过滤数据时使用的是 sed 命令,回到了熟悉的正则表达式,本以为一下子就搞定了, 但结果写了一下午才把这个正则写完。 sed 支持的正则跟 js 差别还是很大的,主要是两点
- 诡异的转义。 这个主要还是我太先入为主了,照着 js 那规则来写,怎么都不对, 后来还是老老实实去看 sed 手册 才搞明白哪里错了,原来 * + ? {n, m} 这些里面,其他的都要转义,唯独星号不转义才是特殊字符, 就不能统一一下吗
- 非贪婪匹配。 日志的格式大概是 key[value] key[value] 这样的一串,过滤的目标是只把须要的几个 key 提取出来。如果允许非贪婪匹配的话,还蛮简单的 key[.*?] 就裁出来了。 但不能用 *? 的话,就会变成 key[[^[]*] 这还没考虑数据中的方括号的转义呢。 写起来还是很蛋疼的
最后正则写出来差不多是这样的
确实挺难看的
PS: 另外就是用 markdown 写东西的时候,* 号的转义也是特别的难受,规则十分诡异。 md 文件里面双星号是粗体,所以星号相当于特殊字符,如果平时使用的话是要带上斜杠转义的。 但写正则的时候就会很尴尬了,由于是写在代码块里面,所以所有转义都没用, 都会显示出来,但 vim 的语法插件还会会把它当成一个粗体/斜体的边界,到现在还没有找到很好的方法解决这个问题。
定时任务
linux 开发机用 crontab 还是很方便的,但就是要自己跑上线上机上去操作,总是感觉有点虚。 crontab 用起来方便是方便,就是线上机跑脚本,权限的问题太蛋疼,还是自己做 op 方便一些。 定时跑一份脚本,将线上日志过滤后备份起来。
merge 日志
在各个机器上生成备份日志之后,还要找一台开发机把所有日志 merge 起来,同样的, 也是使用 crontab 进行日志的收集。下载日志很简单,直接放一个有 http 服务的地方, 然后 webget 就好了,比较麻烦的是按时间 merge 日志的操作。 日志的每一行大概是这样
time[1478247635187] key1[xx] key2[yy] key3[zz]
须要做的工作是切出 time 字段的值,再进行归并操作。但 shell 里面的数据结构非常简单, 基本上就是简单的变量还有数组。
如果将日志文件一口气读进来,内存是肯定装不下的,但如果每次只读一行, 进行归并,访问文件的次数又会非常多,非常的尴尬。
所以决定换个方案,直接把几个日志文件写到一起,然后再使用 awk 排序,这样就不用管太多的排序细节, 放着晚上跑跑排序就好了,只要把日志格式改一下,去掉字段名,用特殊符号分隔字段并不是很复杂。
PS: 不过最后在不懈努力下,总算在服务器上能用 python 了,可以直接拿到文件句柄, 归并数据也就不是很么大问题了。大概是这样
summary
shell 虽然是很方便,但局限性还是太强了,基本上没什么好用的数据结构, 稍微复杂一点的工作还是高级一点的脚本语言会方便些。也可能是我 linux 还是用的太少了, 文件访问的时候不得要领吧。