作为一名法医,他不怕高度腐烂的尸体或复杂的案件。最可怕的是什么都没有了。没有什么,任何精湛的技术,丰富的经验,都无从下手。生产环境错综复杂,几分钟前还活着的进程现在躺在那里奄奄一息,奄奄一息。作为第一时间发现的目击者,一定要注意把现场保持好。有时候,最坏的情况就是被卷入火中被卷入其中,这是我们不愿看到的。在进程的生命结束之前,我们还有很多工作要做。在这篇文章中,我们将介绍常用的留住线索的方法。最后,使用Shell脚本自动执行此过程。系统环境,不说谎的犯罪现场1.系统当前网络连接ss-antp>$DUMP_DIR/ss.dump2>&1该命令将系统所有网络连接输出到ss.dump文件中。使用ss命令而不使用netstat的原因是当有很多网络连接时netstat执行速度非常慢。对于后续的处理,通过查看各种网络连接的状态来排查TIME_WAIT或者CLOSE_WAIT,或者其他高连接问题是非常有用的。2、网络状态统计netstat-s>$DUMP_DIR/netstat-s.dump2>&1将网络统计状态输出到netstat-s.dump文件中。它可以根据每个协议进行统计输出,这对于掌握当时整个网络的状态非常有用。sar-nDEV12>$DUMP_DIR/sar-traffic.dump2>&1以上命令将使用sar输出当前网络流量。在一些非常高速的模块上,比如redis、kafka,经常会出现网卡满的情况。3、进程资源lsof-p$PID>$DUMP_DIR/lsof-$PID.dump这是一个非常强大的命令。您可以检查进程打开了哪些文件。这是一个神器,可以在进程的维度查看整个资源的使用情况。在资源很多的情况下,这个命令的输出有点慢,请耐心等待。4.CPU资源mpstat>$DUMP_DIR/mpstat.dump2>&1vmstat13>$DUMP_DIR/vmstat.dump2>&1sar-pALL>$DUMP_DIR/sar-cpu.dump2>&1uptime>$DUMP_DIR/uptime.dump2>&1这些命令,我??们有在文章《Linux之《荒岛余生》(2)CPU"中已经有比较详细的介绍。主要输出当前系统的CPU和负载,方便后续排查。这些命令的功能有很多重叠,用户要注意5.I/O资源iostat-x>$DUMP_DIR/iostat.dump2>&1一般来说,计算型服务节点的I/O资源会比较正常,但有时也会出现问题,比如太多日志输出,或者磁盘问题。该命令可以输出各个磁盘的基本性能信息,用于排查I/O问题。6.内存问题free-h>$DUMP_DIR/free.dump2>&1内存问题比较复杂,如果你是有兴趣可以看看xjjdog堆外内存排查总结文章,通常出现的问题是JVM内存overflow,我们在流程部分解释。free命令可以大致显示操作系统的内存概况,这是故障排除中非常重要的一点。7、其他全局ps-ef>$DUMP_DIR/ps.dump2>&1dmesg>$DUMP_DIR/dmesg.dump2>&1sysctl-a>$DUMP_DIR/sysctl.dump2>&1在xjjdog的其他文章中,不止一次提到了dmesg。dmesg是许多悄然消亡的服务的最后遗迹。当然,由于ps是最常执行的命令,它当时的输出信息肯定有一定的参考价值。由于内核的配置参数,会对系统产生非常大的影响。所以我们也导出了一份。进程快照,遗言1.jinfo${JDK_BIN}jinfo$PID>$DUMP_DIR/jinfo.dump2>&1该命令会输出java的基本进程信息。包括环境变量和参数配置。2.gc信息${JDK_BIN}jstat-gcutil$PID>$DUMP_DIR/jstat-gcutil.dump2>&1${JDK_BIN}jstat-gccapacity$PID>$DUMP_DIR/jstat-gccapacity.dump2>&1jstat会输出当前的gc信息.一般大体能看出一个端倪,如果看不到,就借助jmap分析一下。3.堆信息${JDK_BIN}jmap$PID>$DUMP_DIR/jmap.dump2>&1${JDK_BIN}jmap-heap$PID>$DUMP_DIR/jmap-heap.dump2>&1${JDK_BIN}jmap-histo$PID>$DUMP_DIR/jmap-histo.dump2>&1${JDK_BIN}jmap-dump:format=b,file=$DUMP_DIR/heap.bin$PID>/dev/null2>&1jmap会得到当前java进程的dump信息。如上所示,第四条命令其实是最有用的,但前三个命令可以让你对系统概况做出初步判断。因为第四条命令生成的文件一般都很大。而且,需要下载并导入到MAT等工具中进行深入分析,才能得到结果。4.执行栈${JDK_BIN}jstack$PID>$DUMP_DIR/jstack.dump2>&1jstack会得到当前的执行栈。一般这个值会取多次,我们这里可以取一次。这个信息非常有用,可以恢复你java进程中的线程情况。top-Hp$PID-b-n1-c>$DUMP_DIR/top-$PID.dump2>&1为了获取更详细的信息,我们使用top命令获取进程中所有线程的cpu信息。这样就可以看到资源被消耗到哪里了。5.高级替代kill-3$PID有时jstack无法运行。原因有很多,比如java进程几乎没有响应。我们将尝试向进程发送kill-3信号。这个信号是java进程共享的,会把jstack的trace信息打印到log文件中。它是jstack的替代品。gcore-o$DUMP_DIR/core$PID对于jmap无法执行的问题也有一个替代,那就是GDB组件中的gcore。将生成一个核心文件。我们可以使用下面的命令生成dump${JDK_BIN}jhsdbjmap--exe${JDK}java--core$DUMP_DIR/core--binaryheaptransientstateandhistoricalstatexjjdog在这里创建两个名词。瞬态是指当时发生的快照类型的元素;历史状态是指按照频率和固定监控项捕获的资源变化图。上面有很多信息,比如CPU,系统内存等等。暂态的值没有历史状态那么直观,因为它还是有一个baseline的问题。所以如果有监控系统之类的工具就更好了。但是对于lsof、heap等,这种没有时间序列概念的混合信息无法进入监控系统产生有用的价值,所以只能通过瞬态来分析。在这种情况下,瞬态的价值更大。我已经把上面的过程写成shell脚本了。你可以在github上找到它。点击左下角查看原文,也可以遇见。https://github.com/sayhiai/shell但值得注意的是,在分布式环境中失败的原因往往是出乎意料的,你的单机证据可能只是表象。它没有说谎,但其背后的含义往往会误导问题的本质。
