欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何在 Docker 环境下自动给 .NET 程序生成 Dump

程序员文章站 2022-05-18 14:20:32
之前“一线码农”大佬有写文章介绍了如何在windows下自动dump,正好手里有个在 docker 环境下 dump 的需求,所以在参考大佬文章的基础上,有了本篇。 ......

前言

之前“一线码农”大佬有写文章介绍了,正好手里有个在 docker 环境下 dump 的需求,所以在参考大佬文章的基础上,有了本篇。

工具

dotnet-dump ()
procdump for linux (https://github.com/sysinternals/procdump-for-linux)

dotnet-dump

dotnet-dump是微软官方推出的一个.net全局工具,安装和使用都非常简单。
安装:

dotnet tool install --global dotnet-dump

使用:

dotnet-dump collect --process-id 1902 # pid

但是它不能够自动dump(也可能是我不知道),所以本文主要讨论下面这个工具

procdump for linux

本工具是 procdump 的社区 linux 移植版,不过主要开发人员也是微软的员工。
它可以实现根据 cpu 占用 、内存占用、线程数等情况进行自动 dump,我们以此来应对程序出现异常时需要dump文件进行分析的场景。

安装
在 dockerfile中添加以下命令:
注意我们要在运行时的镜像中添加,并且最好是自行构建一个基础镜像,而不是每次都进行安装。

# final stage/image
from mcr.microsoft.com/dotnet/aspnet:5.0

# 安装所需依赖
run apt-get update \
    && apt-get install -y --no-install-recommends \
        wget \
        gdb \
        lldb

# 安装 procdump
run wget https://packages.microsoft.com/repos/microsoft-debian-buster-prod/pool/main/p/procdump/procdump_1.1.1-220_amd64.deb -o procdump.deb \
    && dpkg -i procdump.deb \
    && rm procdump.deb

本文基于 aspnet:5.0 镜像,即 debian 10,如果基于其他镜像,可去下面目录中寻找对应的包

也可参考作者提供的安装说明

运行
因为 docker 容器并不能很方便的在启动时同时执行多个进程,所以我们需要一个sh文件以便在启动时同时执行dotnet和procdump。
因为我个人不喜欢在 dockerfile 之外还要依赖其他文件,所以我直接在 dockerfile 里进行了sh文件的创建

run echo "#!/bin/bash \n\
procdump -m 200 -w dotnet & \n\
dotnet \$1 \n\
" > ./start.sh
run chmod +x ./start.sh
entrypoint ["./start.sh", "<yourapp>.dll"]

如果有需要的话,也可以自行创建一个start.sh,内容为

#!/bin/bash
procdump -m 200 -w dotnet &
dotnet $1

dockerfile 改为

copy start.sh ./start.sh
run chmod +x ./start.sh
entrypoint ["./start.sh", "<yourapp>.dll"]

这样就可以了,在docker run的时候会同时启动dotnet和procdump,并且当内存大于200m的时候会自动dump。
还有一点要注意,docker run的时候需要添加--privileged 以提高权限。例如docker run --privileged -it xx

其中 procdump 的各个参数为

usage: procdump [options...] target
   options
      -h          prints this help screen
      -c          当cpu超过或等于指定值(0到100 * ncpu)时,触发核心转储生成。
      -c          当cpu小于指定值(0到100 * ncpu)时触发核心转储生成。
      -m          当内存提交超过或等于指定值(mb)时,触发核心转储生成
      -m          当内存提交小于指定值(mb)时,触发核心转储生成。
      -t          当线程数超过或等于指定值时触发。
      -f          当文件描述符计数超过或等于指定值时触发。
      -i          polling frequency in milliseconds (default is 1000)
      -n          number of core dumps to write before exiting (default is 1)
      -s          consecutive seconds before dump is written (default is 10)
      -d          writes diagnostic logs to syslog
    target 以下二选一:
      -p          进程的 pid
      -w          进程的名字

举例来说,以下命令表示当 cpu 使用率为>= 65%或内存为>= 100 mb 时创建一个 dump 文件

procdump -c 65 -m 100 -p 1234

其他

dump 文件的持久化
大家都知道 docker 容器消失的话,那么其中的 dump 文件也会消失。
所以需要输出 dump 文件到一个指定的、进行过持久化挂载的卷中,不过可惜的是,当前procdump for linux还没有一个输出参数来控制输出目录,只会在应用程序的同级目录生成,所以现在需要手动移动一下。
我看已经有人提了 pr,未来会增加一个 -o 参数以控制输出。

参考