看了这篇文章,比同事更快找到bug!

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 你以为程序员只是闷着头疯狂写bug,写好了发布到服务器就完了?不,你还要修bug!但在那之前,你还要找bug!

你以为程序员只是闷着头疯狂写bug,写好了发布到服务器就完了?

不,你还要修bug!但在那之前,你还要找bug!

那么问题来了,程序都部署都服务器了,怎么找bug呢?下面给大家介绍几种方法,帮助你轻松找到程序的bug。


日志篇


在上篇文章中,笔者介绍了《在Java代码中打日志需要注意什么?》。打日志是非常重要的,因为日志能够提供一些运行时的信息,非常有助于我们快速定位问题。

那么怎么通过日志去分析问题呢?我们首先从单机服务器说起,因为有时候可能bug是测试发现的,而测试环境一般机器都比较少,可能不会专门搭建ELK等日志收集器,所以可能是要到服务器上去看日志。

统一日志配置标准

这个其实是非常重要的,因为我们首先要找到日志文件的路径,才能找到日志进行分析。尤其在一个大点的团队,服务非常多,比较忌讳每个服务的日志文件路径乱放,找半天找不到日志放在哪。

所以建议团队有一个统一的日志配置标准。不论是格式、路径、保存日期和清理策略等,最好都保持一致,并写进团队的建设文档里,这样开发人员才能够快速地找到自己想要的日志。

分析日志常用命令

现在服务端大多部署在Linux服务器上,所以这里介绍一些在Linux上常用的分析日志的命令。

tail

tail命令是笔者最常用的命令。我们知道,日志文件大多都是追加的方式进行的。所以最新发生的问题一般都是在日志文件的末尾。tail命令可以打印出日志倒数第n行的日志,还可以通过-f参数来实时追踪。

# 打印x.log的末尾1000行日志,默认是10
tail x.log -n1000;
# 打印x.log末尾10行日志,并继续打印出后面新增的日志
tail x.log -f
# 这个跟上面是等价的
tailf x.log

cat + grep

上面介绍的tail命令,可以输出文件的末尾n行。但有时候我们发现问题时已经有点晚了,这个时候可以在整个日志文件里面找。

通过cat命令,可以打印出整个日志文件的内容。但整个日志文件内容太多了,所以我们通常需要通过管道加上grep来结合,只提取我们需要的信息。

cat x.log | grep 'xxx'
复制代码

这里grep的内容“xxx”,通常建议以下值:

  • 日志中的数据的id或者uid,比如43432413;
  • 日志中的traceId;
  • 日志中的问题描述,比如“call userService failed”;
  • 日志中的文件,比如“UserServiceImpl”

当然了,这里的管道和grep,也可以和上面的tail命令相结合。另外,如果grep出来的内容比较多,后续还想分析,管道还可以将输出流输出到一个文件里,比如:

cat x.log | grep 'xxx' > temp.log

输出到一个单独的文件里了,我们就能够对它进行下一步分析了,比如发生这个异常的数据有多少条,提取里面的关键信息。还可以通过sed命令来做。

比如:

# 打印temp.log
$ cat temp.log
error data: 124
error data: 121j
error data: 124fdsfsd
# 用正则提取里面的id
$ cat temp.log | sed -r "s/error data: (.*)/\1/g"
124
121j
124fdsfsd

vi

cat + grep虽然好,但是不是很方便查看异常周围的日志。比如我们想查看完整的日常堆栈,可以通过vi的搜索功能来做。

vi是在Linux平台上常用的文本编辑器,功能非常强大。当然,很多朋友更习惯用功能更强的vim,用法是类似的。今天要介绍的是它的一些常用的搜索功能和跳转功能。

# 从前到后搜索
/searchKey
# 从后到前搜索
?SearchKey
# 定位光标到下一个搜索的地方
快捷键n
# 定位到光标上一个搜索的地方
快捷键N
# 设置显示行号
:set nu
复制代码

以上差不多能够在服务器上定位和分析日志了。如果你的服务器是分布式的,部署在很多台机器上,比如UAT环境和生产环境,那其实不建议再去服务器上手动分析日志,而是用成熟的日志框架去收集和分析日志。

比较常用的开源日志收集框架是ELK、Splunk等,它们都提供了web界面和丰富的查询语句支持。


远程Debug篇


现在JVM支持远程调试。其原理是因为Java是跨平台的,只要远程的字节码文件和本地的字节码文件相同,两个JVM可以通过调试协议进行通信。

所以这里需要保证本地和服务端的代码要一致,不然可能导致某个端点无法进入。尤其使用分支开发的同学需要注意分支是否一致

IDEA上有一个非常好用的远程Debug工具,下面简单介绍一下如何在IDEA上如何Debug。首先通过Run -> EditConfigurations进去,然后添加一个Remote。

然后配置一下host和端口就行了,这里需要注意的是端口是服务器上面的新端口,不要与服务本身的web端口冲突了,可以在应用启动时传入下图中的JVM参数指定端口和远程debug配置。

remote debug

创建好以后,在IDEA打开你的远程debug,就可以愉快地Debug了。

不推荐在生产环境使用远程Debug


神器Arthas

Arthas是阿里开源的一款Java诊断工具,功能非常强大。官网上有一个在线的交互式教程,几分钟入门,非常方便。支持命令的自动补全、历史命令补全,管道等。这里介绍它的一些常用的功能。

Dashboard

Arthas的dashboard命令可以显示当前系统和JVM的实时状态。包括线程的状态、JVM的状态。

dashboard

查看线程

通过thread 1可以打印线程id为1的栈。而且Arthas也支持管道,可以对输出通过管道进行grep:

[arthas@37]$ thread 1
"main" Id=1 TIMED_WAITING
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at demo.MathGame.main(MathGame.java:17)
Affect(row-cnt:0) cost in 9 ms.
[arthas@37]$ thread 1 | grep main(
    at demo.MathGame.main(MathGame.java:17)

查看方法的运行时信息

通过watch命令可以查看方法的运行时参数/返回值/异常信息。

[arthas@37]$ watch demo.MathGame primeFactors returnObj
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 40 ms.
ts=2020-05-10 02:53:46; [cost=1.129697ms] result=null
ts=2020-05-10 02:53:47; [cost=0.056254ms] result=null
ts=2020-05-10 02:53:48; [cost=0.056249ms] result=null
ts=2020-05-10 02:53:49; [cost=0.210126ms] result=@ArrayList[
    @Integer[2],
    @Integer[3],
    @Integer[5],
    @Integer[1039],
]
ts=2020-05-10 02:53:50; [cost=0.204834ms] result=@ArrayList[
    @Integer[3],
    @Integer[3],
    @Integer[3],
    @Integer[7],
    @Integer[839],
]

动态执行代码

这是我觉得Arthas里最强大的一个功能了!使用ognl命令可以让你的应用代码执行执行任意方法,用你制定的任何参数!比如:

[arthas@37]$ ognl '@java.lang.System@out.println("hello ognl")'

这个时候,你的应用代码会输出“hello ognl”。

Arthas还有很多非常强大的功能,它甚至可以热更新代码,就是动态替换你想替换的某个类!

当然,笔者觉得Arthas的命令强大归强大,使用起来还是有一些复杂的,毕竟是一个基于命令行的程序。IDEA有一个arthas idea插件,可以生成arthas命令,有兴趣的同学可以试试~

arthas idea

以上就是关于如何更快更方便地找bug的介绍。早一秒找到bug,就早一秒挽救损失,说不定就能升职加薪哦~

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
SQL JSON 前端开发
【改BUG】项目遇到的奇葩bug
【改BUG】项目遇到的奇葩bug
|
4月前
|
安全 JavaScript Java
若依修改,若依bug整理集合资料在那?作者亲自解决bug
若依修改,若依bug整理集合资料在那?作者亲自解决bug
|
运维 架构师 Java
你目前写过最大的bug
你目前写过最大的bug
156 0
|
缓存 JavaScript 小程序
接手前同事代码,特别烂,各种BUG,看麻了。。。
接手前同事代码,特别烂,各种BUG,看麻了。。。
|
监控 安全 架构师
抱歉,你测试的项目上线之后bug太多了!
抱歉,你测试的项目上线之后bug太多了!
|
Python
遇到bug不要慌,先发个文章看看
遇到bug不要慌,先发个文章看看
128 0
|
Java 中间件 程序员
最网最全bug定位套路,遇见bug再也不慌了
最网最全bug定位套路,遇见bug再也不慌了
318 0
|
存储 算法 安全
我用一个小小的开放设计题,干掉了40%的面试候选人
去年团队招聘需求比较大,本人参与了近百次的面试工作。今天来跟大家聊聊,面试候选人过程中,一个常见的开放类设计题目的解题思路,以及候选人的理解设计误区分析。
我用一个小小的开放设计题,干掉了40%的面试候选人
设置的下载器的bug整理
1,流不小心关闭了,那就把流打开就好了:
127 0
设置的下载器的bug整理
|
数据可视化 前端开发 NoSQL
BUG记录 | 【内附前端福利】
今天在安装VMWare软件的时候,突然报了这个错误
143 0
BUG记录 | 【内附前端福利】