dotnet core调试docker下生成的dump文件
最近公司预生产环境.net core应用的docker容器经常出现内存暴涨现象,有时会突然吃掉几个G,触发监控预警,造成容器重启。
分析了各种可能原因,修复了可能发生的内存泄露,经测试本地正常,但是发到预生产还是会有内存暴涨现象,反而更改GC模式后内存使用保持较低水平,百思不得其解,所以想到使用调试dump文件方式来分析应用内存状况。
环境:
lldb:3.9
dotnetcore:2.1.6
docker image:microsoft/dotnet:2.1.6-aspnetcore-runtime
(根据文档,dotnetcore2.0需要使用lldb3.6,但是我尝试了没有成功,lldb使用的dotnetcore版本与dump应用的dotnetcore版本要一致,由于core2.1现在官方只提供2.1.6的runtime文件,故本次测试使用2.1.6版本,如果哪位童鞋在core2.0上调试成功了,麻烦告诉我方法)
linux下需要使用lldb来进行dump分析,但是安装这个太慢,所以我找了个安装好的docker image使用,有兴趣的也可以自行安装,这里就不介绍安装过程了,.net core 本身提供了lldb sos 插件,只要加载使用就好。
启动一个.net core应用容器,这里需要多加几个参数,不然无法创建dump(另外多说一句,docker内crash coredump文件无法生成也是权限原因,我这边启动时都给了权限,如果仅仅是需要使用.netcore提供createdump工具,只需要加--privileged=true):
docker run -d -p 80:80 --name dumptest --ulimit core=-1 --security-opt seccomp=unconfined --privileged=true dumptest:v1
--ulimit core=-1 不限制coredump大小
--security-opt seccomp=unconfined 允许容器执行全部系统调用
--privileged=true 允许createdump访问其他进程
进入容器:
docker exec -it dumptest /bin/bash
创建dump文件:
/usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.6/createdump 1
(经观察,容器内的跑的应用进程ID都是1,所以直接使用,也可以使用top命令来查看进程ID,创建dump文件在/tmp/coredump.1)
退出容器:
exit
在宿主机创建文件夹/data/docker,并将容器中的dump文件拷贝到宿主机:
cd /&&mkdir data&&cd data&&mkdir docker
docker cp dumptest :/tmp/coredump.1 /data/docker
拉取lldb镜像(此镜像是lldb3.9的dotnetcore版本为2.1.5,有其他需求请自行查找):
docker pull yyoda/dotnet-lldb
启动lldb容器,并将coredump文件路径映射到容器内(如果想要长期使用不要带--rm参数):
docker run -d -v /data/docker:/dump --rm -it --name lldb yyoda/dotnet-lldb:latest /bin/bash
镜像内需要安装dotnetcore2.1.6,为了方便安装,在容器内部使用阿里源:
cd /data/docker
touch sources.list
将下面的源加入sources.list:
deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
进入lldb容器:
docker exec -it lldb /bin/bash
更新源:
mv /dump/sources.list /etc/apt/source.list
apt-get update
安装dotnetcore2.1.6 runtime(由于网络等原因,如果失败多试几次):
wget -q https://packages.microsoft.com/config/ubuntu/14.04/packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb
apt-get install apt-transport-https
apt-get update
apt-get install dotnet-runtime-2.1
启动lldb:
lldb-3.9 dotnet -c /dump/coredump.1 -o "plugin load /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.6/libsosplugin.so"
(如果sos加载失败,启动后输入命令:plugin load /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.6/libsosplugin.so
如果runtime加载失败,启动后输入命令:setclrpath /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.6)
输入soshelp命令,出现下图:

查看堆上的对象类型分配情况(由于结果太多,这里加入大于1024byte过滤):
dumpheap -stat -min 1024

查看指定类型对象情况:
dumpheap -mt 00007f2a28b874e8 -min 1024

查看指定对象情况:
dumpobj 00007f2a1400fc88

剩下的就是熟悉sos命令,不在赘述了,大家自行研究吧。。。
ps:附上docker容器内应用崩溃时生成dump方法:
1.容器启动时要带下面两个参数:
--ulimit core=-1
--security-opt seccomp=unconfined
2.宿主机上执行命令,更改dump文件输出路径:
echo '/tmp/core.%t.%e.%p' | sudo tee /proc/sys/kernel/core_pattern
(因为系统在产生 coredump 文件时是根据 /proc/sys/kernel/core_pattern 的设定模板来的,而默认的设定是 /usr/share/apport/apport %p %s %c %P,也就是用管道传apport。然而 Docker 里面的系统不一定有装 apport,并且 /proc 又是直接挂到 Docker 里面的,所以需要设置固定存放位置 /tmp。
%p 所dump进程的进程ID
%t core dump的时间
%e 程序文件名)
测试:
进入容器后执行 kill -s SIGSEGV $$ 触发当前shell终端的段错误。
再次进入容器,在/temp路径下可以看到刚刚生成的dump文件

参考资料:
https://github.com/mikem8361/coreclr/blob/5c22cb85c7cc9173f2fb783bf24c0cbbb6096c89/Documentation/building/debugging-instructions.md
http://blogs.microsoft.co.il/sasha/2017/02/26/analyzing-a-net-core-core-dump-on-linux/
dotnet core调试docker下生成的dump文件的更多相关文章
- [Android]生成heap dump文件(.hprof)
Android生成heap dump文件(.hprof) 一个heap dump就是一个程序heap的快照,能够获知程序的哪些部分正在使用大部分的内存. 它保存为一种叫做HPROF的二进制格式.对于A ...
- dotnet core 在 MIPS 下的移值进度
本文仍处于修订中 写在开始前 我们的主要业务基于 dotnet core 2.x 与 3.1 完成,目前 dotnet core 3.1 支持的 CPU 架构列表中还不包含龙芯,且在 gitlab i ...
- win8商店应用验证,二进制文件是在调试模式下生成的解决方案。
程序是在release模式下生成的,并且arm和x64通过了验证,但是x86就出现了这个奇葩问题. 搞了半天发现是要把“优化代码”的选项勾上.
- 记录linux 生成crash dump文件步骤
执行文件编译时加入-g 命令 例如 g++ -g test.cpp 查看当前系统限制情况 ulimit -a 设置crash dump 文件大小 ulimit -c unlimited unlimit ...
- dotnet core 发布只带必要的依赖文件
在使用 dotnet core 发布独立项目的时候,会带上大量依赖的库,但是通过微软提供的工具可以去掉一些在代码没有用到的库. 本文介绍的工具是 Microsoft.Packaging.Tools.T ...
- visual studio 2017发布dotnet core到docker
docker的好处不用多说,有不了解的可移步<docker入门>,作为一个.net方面的老鸟也想早点搭上docker末班车,减少布署中的各种坑.以下我是在Visual Studio 201 ...
- 【dotNet Core】Swagger下简单的给WebApi分组
Startup.cs下ConfigureServices代码 这里主要在DocInclusionPredicate控制输出那些api. Startup.cs下Configure代码 给Controll ...
- /var/spool/clientmqueue 下生成太多文件处理
问题现象: linux操作系统中的/var/spool/clientmqueue/目录下存在大量文件. 原因分析: 系统中有用户开启了cron,而cron中执行的程序有输出内容,输出内容会以邮件形式发 ...
- OpenModelica 在特定目录下生成仿真结果文件
OMEdit的仿真结果文件存放在:C:\Users\***\AppData\Local\Temp\OpenModelica\OMEdit 可以在仿真时设置仿真结果文件名,可使用用绝对路径或相对路径 使 ...
随机推荐
- Java——string类型与date类型之间的转化
String类型转化为Date类型 方法一 Date date=new Date("2019-01-25"); 方法二 String =(new SimpleDateFormat( ...
- css3实现小程序的动画
<view class="biground" > <block wx:for="{{Namelist}}" wx:key=" ...
- 小程序radio样式修改
.city-radio-group-label .city-label-radio { //label样式 padding: 15rpx 50rpx; position: relativ ...
- day09三目运算
内容详细 1.三目运算(三元运算) v=前面 if 条件 else 后面 if 条件: v="前面" else: v="后面" #让用户输入值,如果值是整数,则 ...
- FragmentXlistview
package com.example.lenovo.tablayout; /** * Created by lenovo on 2018/7/18. */ import android.os.Asy ...
- C++报错
编译的时候会报如下错误:warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable ...
- SDL播放YUV——循环
#include "SDL.h" #include "as_lesson_log.h" #define PATH_YUV420 "/sdcard/ou ...
- python八荣八耻
Python八荣八耻 以动手实践为荣 , 以只看不练为耻; 以打印日志为荣 , 以单步跟踪为耻; 以空格缩进为荣 , 以制表缩进为耻; 以单元测试为荣 , 以人工测试为耻; 以模块复用为荣 , 以复制 ...
- 2019嘉韦思杯线上初赛writeup
1 土肥原贤二 看到页面怀疑是sql注入,写了个4'进去就发生报错.could not to the database You have an error in your SQL syntax; ch ...
- React 组件间通信介绍
React 组件间通信方式简介 React 组件间通信主要分为以下四种情况: 父组件向子组件通信 子组件向父组件通信 跨级组件之间通信 非嵌套组件间通信 下面对这四种情况分别进行介绍: 父组件向子 ...