天天看點

如何在 Docker 環境下自動給 .NET 程式生成 Dump

如何在 Docker 環境下自動給 .NET 程式生成 Dump

2021-06-02 08:31 

Rwing 

閱讀(8) 

評論(0) 

編輯 

收藏

之前“一線碼農”大佬有寫文章介紹了如何在windows下自動dump,正好手裡有個在 docker 環境下 dump 的需求,是以在參考大佬文章的基礎上,有了本篇。

前言

之前“一線碼農”大佬有寫文章介紹了如何在 windows 下自動 dump,正好手裡有個在 docker 環境下 dump 的需求,是以在參考大佬文章的基礎上,有了本篇。

工具

dotnet-dump (https://docs.microsoft.com/en-us/dotnet/core/diagnostics/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,如果基于其他鏡像,可去下面目錄中尋找對應的包

https://packages.microsoft.com/repos/

也可參考作者提供的安裝說明

運作

因為 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 參數以控制輸出。

參考

https://www.cnblogs.com/huangxincheng/p/14661031.html

https://docs.docker.com/config/containers/multi-service_container/

https://github.com/msbrz/procdump-docker

  • 分類 01.文章
  • 标簽 Dump

    , Docker

    , .net