当前位置: 首页 > 科技观察

别小看tail命令,难倒技术总监

时间:2023-03-15 13:40:15 科技观察

转载本文请联系味觉小姐姐公众号。tail命令可以看到日志的滚动,很方便。于是xjjdog就想,既然我们可以用这个命令看到所有的日志,那我们是不是可以用tail命令来做日志收集呢?想象力归想象力,如果你想要一个快速的实时日志收集工具,tail确实是一个非常Great的工具。它比flume、logstatsh和filebeat快得多。其实我以前在工具匮乏的时候就是这样做的,效果还不错。下面是一段用Java语言写的代码。我们可以逐行阅读日志并用我们最喜欢的语言做任何我们想做的事情。importjava.io.BufferedReader;importjava.io.InputStreamReader;publicclassTailReader{publicstaticvoidmain(String[]args)throwsException{ProcessBuilderps=newProcessBuilder("tail","-f","/tmp/tail0");//错误输出为还打印ps.redirectErrorStream(true);Processprocess=ps.start();//不断读取tail的输出{setLogToKafka(line);//这里注意不要产生异常,否则while循环会中断}}}//模拟发送到kafka,我们这里简单打印一下staticvoidsetLogToKafka(Stringline){System.out.println(line);}}主要思路是利用Java的Process启动一个sub-tail进程,一直监听文件的输出。然后标准输出和标准错误流都被定向到BufferedReader。接下来,你可以做任何你想做的事。这有一定的风险。如果tail命令被杀死,我们的Java程序就失去了功能。程序很简单,但是xjjdog这里讨论的不是这个简单的采集程序,而是tail命令的一些有趣的特性,从中可以窥见一些日志采集工具对文件的特殊处理。你知道tail-f和tail-F的区别吗?在回答这个问题之前,我们先来回顾一下Java中常用的处理日志的日志框架。truelogFile.%d{yyyy-MM-dd}.log303GB<编码器>%-4relative[%thread]%-5level%logger{35}-%msg%n以上配置会在每晚凌晨滚动形成一个新的文件。这个滚动是如何完成的?我们可以收工并模拟这个过程。mvrun.logrun.2020-11-02.logtouchrun.log测试文件滚动,会生成一个新文件。tail命令还能被跟踪吗?让我们测试一下。第一步,创建监控touch/tmp/tail0的文件第二步,启动我们的Java代码第三步,生成一个不间断流watch-n1'echo`date`>>/tmp/tail0'上面的命令打印当前日期到我们每隔1秒读取一次文件,可以看到Java端已经收到数据了。第四步模拟文件滚动mv/tmp/tail0/tmp/tail.baktouch/tmp/tail0此时我们可以看到Java端此时已经接收不到数据了。为什么?要了解原因,让我们使用两个命令查看进程的一些状态。首先使用ps命令查看当前tail进程。ps-ef|greptail501213742137301:51PM??0:00.01tail-f/tmp/tail0这正是我们的命令。我们使用lsof命令查看与此进程关联的文件。lsof-p21374|awk'{print$4"\t"$9}'FDNAMEcwd/tmp/txt/usr/bin/tailtxt/usr/lib/dyld3r/private/tmp/tail.bak我们看到tail进程监听的文件,其实就是tail.bak文件,与tail命令无关。让我们尝试输入类似tail.bak的内容。echo"haha:xjjdog,iamfromtail.bak">>/tmp/tail.bak这时候Java进程如我们所愿,响应了,这句话就正常输出了。该怎么办?正如我们在问题中所问的,只需将tail-f替换为tail-F。tail-f表示根据文件描述符进行跟踪。tail-F表示根据文件名进行跟踪,会有重试动作。因此,我们的日志收集程序,无疑是根据日志名称进行追溯的,应该将f改为F。既然End知道了这些细微的差别,那么我们在日常工作中遇到的一些灵异问题就有了解释。rm命令大家都知道,可以删除一个文件。如果有这个文件,正在被其他进程使用,那么你好像删除了这些文件,但它的内容并没有被释放。lsof|grepdeleted上面的命令可以看到这些失控的文件。一般杀掉相应的进程,这些句柄就会被释放。但是你删除这些文件的原因是为了避免重启应用程序,这确实很混乱。cat/dev/null>logpath所以我们在删除文件的时候,一般不会使用rm,而是应该使用重定向符号。向他们发送/dev/null,其中所有内容都是空的。作者简介:品味小姐姐(xjjdog),一个不允许程序员走弯路的公众号。专注于基础架构和Linux。十年架构,每天百亿流量,与你探讨高并发世界,给你不一样的滋味。我的个人微信xjjdog0,欢迎加好友进一步交流。