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

简介: 你以为程序员只是闷着头疯狂写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日志并进行多维度分析。
目录
相关文章
|
6天前
|
程序员 测试技术
程序员的“Bug之旅”:为何无法一次性写出完美代码?
程序员在软件开发过程中难以一次性写出完美代码,需要不断修改和调试,即“改Bug”,这是由多个因素共同作用的结果。技术层面的复杂性、管理和流程上的不足以及个人能力和认知的局限性都是导致这一现象的重要原因。然而,这并不意味着无法避免或改进。通过加强需求管理、建立有效的版本控制和测试机制、推动团队知识共享以及鼓励代码审查和自我反思等措施,可以降低改Bug的频率和成本,提高软件开发的效率和质量。辩证地看待这一问题,既要理解其存在的合理性,也要积极寻求改进之道,以实现更好的产品和服务。
14 2
|
6天前
|
人工智能 小程序 算法
分享64个JavaGame源码总有一个是你想要的
分享64个JavaGame源码总有一个是你想要的
54 0
|
6天前
|
人工智能 Java 关系型数据库
分享66个JavaGame源码总有一个是你想要的
分享66个JavaGame源码总有一个是你想要的
71 0
|
7月前
|
SQL JSON 前端开发
【改BUG】项目遇到的奇葩bug
【改BUG】项目遇到的奇葩bug
|
8月前
|
SQL 安全 前端开发
Web安全性测试包括哪些要点?梳理下,总算搞明白了
Web安全性测试包括哪些要点?梳理下,总算搞明白了
177 0
Web安全性测试包括哪些要点?梳理下,总算搞明白了
|
运维 架构师 Java
你目前写过最大的bug
你目前写过最大的bug
125 0
|
缓存 JavaScript 小程序
接手前同事代码,特别烂,各种BUG,看麻了。。。
接手前同事代码,特别烂,各种BUG,看麻了。。。
|
监控 安全 架构师
抱歉,你测试的项目上线之后bug太多了!
抱歉,你测试的项目上线之后bug太多了!
|
Java 中间件 程序员
最网最全bug定位套路,遇见bug再也不慌了
最网最全bug定位套路,遇见bug再也不慌了
242 0
|
SQL 运维 测试技术
被问:这个BUG为什么没测出来?该如何回答
被问:这个BUG为什么没测出来?该如何回答
142 0
被问:这个BUG为什么没测出来?该如何回答