<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Linux 上的 .NET 崩潰了怎么抓 Dump

          共 12022字,需瀏覽 25分鐘

           ·

          2023-08-18 21:24

          一:背景

          1. 講故事

          訓(xùn)練營(yíng)中有朋友問(wèn)在 Linux 上如何抓 crash dump,在我的系列文章中演示的大多是在 Windows 平臺(tái)上,這也沒(méi)辦法要跟著市場(chǎng)走,誰(shuí)讓 .NET 的主戰(zhàn)場(chǎng)在工控醫(yī)療 呢,上一張?jiān)?合肥 分享時(shí)的一個(gè)統(tǒng)計(jì)圖。

          77ec8be7a19ab0bdcc407066478c90d5.webp

          這就導(dǎo)致總有零星的朋友問(wèn) Linux 平臺(tái)上如何生成 crash dump,這一篇就來(lái)整理下來(lái)減少后續(xù)的溝通成本。

          二:如何生成

          1. 案例代碼

          為了方便演示,寫了一段簡(jiǎn)單的 C# 代碼,故意拋異常讓程序崩潰。

                
                
                  static void Main(string[] args)
                  {
                      throw new Exception("OutOfMemory");
                      Console.ReadLine();
                  }

          2. 操作系統(tǒng)層面捕獲

          一般來(lái)說(shuō)操作系統(tǒng)層面都支持當(dāng)一個(gè)進(jìn)程異常退出時(shí)自動(dòng)捕獲Crash Dump,Linux 如此,Windows 也如此,當(dāng)然默認(rèn)是不支持的,需要用 ulimit 開(kāi)啟,這個(gè)命令可以用來(lái)配置當(dāng)前系統(tǒng)資源的使用額度,用 limit -a 觀察。

                
                
          [root@localhost data]# ulimit -a
          core file size          (blocks, -c) 0
          data seg size           (kbytes, -d) unlimited
          scheduling priority             (-e) 0
          file size               (blocks, -f) unlimited
          pending signals                 (-i) 14950
          max locked memory       (kbytes, -l) 64
          max memory size         (kbytes, -m) unlimited
          open files                      (-n) 1024
          pipe size            (512 bytes, -p) 8
          POSIX message queues     (bytes, -q) 819200
          real-time priority              (-r) 0
          stack size              (kbytes, -s) 8192
          cpu time               (seconds, -t) unlimited
          max user processes              (-u) 14950
          virtual memory          (kbytes, -v) unlimited
          file locks                      (-x) unlimited

          卦中的 core file size 就是用來(lái)指定生成 dump 文件的大小,默認(rèn)為 0,即表示不生成,我們可以將其改成 unlimited ,即不限文件大小。

                
                
          [root@localhost data]# ulimit -c unlimited

          如果你想永久保存,可以修改環(huán)境變量文件 /etc/profile, 在末尾新增 ulimit -c unlimited 即可。

                
                
          [root@localhost data]# vim /etc/profile
          [root@localhost data]# source /etc/profile

          c091921769f0bd6beb875b8870c2420b.webp

          接下來(lái)將程序在 CentOS7 上跑起來(lái),從輸出看馬上就產(chǎn)生了崩潰文件,默認(rèn)在應(yīng)用程序目錄下。

                
                
          [root@localhost data]# dotnet Example_1_1.dll
          hello world!
          Unhandled exception. System.Exception: OutOfMemory
             at Example_1_1.Program.Main(String[] args) in D:\skyfly\1.20230528\src\Example\Example_1_1\Program.cs:line 13
          Aborted (core dumped)

          [root@localhost data]# ls
          core.39653   Example_1_1.deps.json  Example_1_1.pdb
          Example_1_1  Example_1_1.dll        Example_1_1.runtimeconfig.json

          core.39653 生成好了之后,可以 copy 到 Windows 平臺(tái)上使用 windbg 分析,這里有一點(diǎn)要注意,linux 上的 dump,windbg 默認(rèn)不自動(dòng)加載 sos 的,需要你手工 .load 一下。

                
                
          0:000> .load  C:\Users\Administrator\.dotnet\sos64\sos.dll
          0:000> !t
          ThreadCount:      3
          UnstartedThread:  0
          BackgroundThread: 2
          PendingThread:    0
          DeadThread:       0
          Hosted Runtime:   no
                                                                                                                      Lock  
           DBG   ID     OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception
             0    1     9ae5 000055DF29280340    20020 Preemptive  00007F352C01EE20:00007F352C01FFD0 000055df29267810 -00001 Ukn <Invalid Object> (00007f352c0138c8)
             7    2     9aea 000055DF2928D990    21220 Preemptive  0000000000000000:0000000000000000 000055df29267810 -00001 Ukn (Finalizer) 
             1    3     9aeb 000055DF292B99E0    21220 Preemptive  0000000000000000:0000000000000000 000055df29267810 -00001 Ukn 

          0:000> !pe
          Exception object00007f352c0138c8
          Exception type:   <Unknown>
          Message:          OutOfMemory
          InnerException:   <none>
          StackTrace (generated):
              SP               IP               Function
              00007FFE584563C0 00007F3561BE2E86 Example_1_1.dll!Unknown+0x96

          StackTraceString: <none>
          HResult: 80131500

          從卦中看,雖然異常信息有,但看不到默認(rèn)的托管函數(shù)名 Main,而是用 Unknown 替代的,這就比較尷尬了,畢竟 Linux 不是微軟弄的,很多地方水土不服。

          可這是無(wú)數(shù) Linux 人及官方首推生成 crash dump 的方式,在 .netcore 上總會(huì)有這樣和那樣的問(wèn)題,那怎么辦呢?問(wèn)題總得要解決,針對(duì)這種場(chǎng)景,微軟巧用開(kāi)機(jī)啟動(dòng)的 dotnet 進(jìn)程為載體,在程序崩潰的時(shí)候通過(guò)讀取 環(huán)境變量 的方式來(lái)生成 crash dump。

                
                
          [root@localhost ~]# ps -ef | grep dotnet
          root       6566   6520  0 12:06 pts/2    00:00:00 grep --color=auto dotnet

          3. 使用 dotnet 環(huán)境變量捕獲

          微軟的 MSDN:https://learn.microsoft.com/en-us/dotnet/core/diagnostics/collect-dumps-crash 上詳細(xì)的記錄了如何通過(guò)讀取環(huán)境變量來(lái)生成 crash dump。

          大體分如下三個(gè)參數(shù):

          • COMPlus_DbgEnableMiniDump

          • COMPlus_DbgMiniDumpType

          • COMPlus_DbgMiniDumpName

          看到這三個(gè)變量,我敢斷定它是借助了 Windows WER 生成 crash dump 的思想,不過(guò)載體不一樣,前者是 dontet父進(jìn)程,后者是 wer系統(tǒng)服務(wù)。

          988c82fc7079826654953cd0220fcc2b.webp

          接下來(lái)將這三個(gè)變量配置到環(huán)境變量文件中,然后把程序跑起來(lái)了,參考如下:

          332de8a0265fac69fbcc0d89cd24089d.webp
                
                
          [root@localhost data]# vim /etc/profile
          [root@localhost data]# source /etc/profile
          [root@localhost data]# dotnet Example_1_1.dll
          hello world!
          Unhandled exception. System.Exception: OutOfMemory
             at Example_1_1.Program.Main(String[] args) in D:\skyfly\1.20230528\src\Example\Example_1_1\Program.cs:line 13
          [createdump] Gathering state for process 40422 dotnet
          [createdump] Crashing thread 9de6 signal 6 (0006)
          [createdump] Writing full dump to file /data2/coredump.dmp
          [createdump] Written 119734272 bytes (29232 pages) to core file
          [createdump] Target process is alive
          [createdumpDump successfully written
          Aborted (core dumped)

          [root@localhost data]# cd /data2
           ; ls
          coredump.dmp

          有了這個(gè) coredump.dmp 之后,再把它拖到 windbg 中觀察。

                
                
          0:000>  .load  C:\Users\Administrator\.dotnet\sos64\sos.dll
          0:000> !t
          ThreadCount:      3
          UnstartedThread:  0
          BackgroundThread: 2
          PendingThread:    0
          DeadThread:       0
          Hosted Runtime:   no
                                                                                                                      Lock  
           DBG   ID     OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception
             0    1     9de6 00005603DBF7C520    20020 Preemptive  00007FF13801EE20:00007FF13801FFD0 00005603dbf639f0 -00001 Ukn System.Exception 00007ff1380138c8
             5    2     9deb 00005603DBF89B70    21220 Preemptive  0000000000000000:0000000000000000 00005603dbf639f0 -00001 Ukn (Finalizer) 
             6    3     9dec 00005603DBFB5C50    21220 Preemptive  0000000000000000:0000000000000000 00005603dbf639f0 -00001 Ukn 
          0:000> !pe
          Exception object00007ff1380138c8
          Exception type:   System.Exception
          Message:          OutOfMemory
          InnerException:   <none>
          StackTrace (generated):
              SP               IP               Function
              00007FFC7A324A10 00007FF16F852E86 Example_1_1!Example_1_1.Program.Main(System.String[])+0x96

          StackTraceString: <none>
          HResult: 80131500

          從卦中看,這次終于有了,不容易,所以在 Linux 平臺(tái)上,首推環(huán)境變量的模式,如果你對(duì) coredump 的名字有自定義要求,也可以修改根據(jù)下圖中的模板參數(shù)修改。

          79b4275dfe8dd1b1d585d2d4e9aa2d94.webp
                
                
          export COMPlus_DbgEnableMiniDump=1
          export COMPlus_DbgMiniDumpType=4
          export COMPlus_DbgMiniDumpName=/data2/%p-%e-%h-%t.dmp

          [root@localhost data2]# ls
          41758-dotnet-localhost.localdomain-1685332206.dmp

          三:總結(jié)

          這篇大概介紹了兩個(gè)抓 dump 的方式:前者適合非托管程序,后者適合托管程序,相信這篇文章能極大的節(jié)省各方的溝通成本,花點(diǎn)時(shí)間整理下很值。

          瀏覽 139
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  秋霞AV一区二区三区 | 亚洲伊人久久久 | 国产综合久久777777麻豆 | 国产精品扒开腿做爽爽爽视频 | 国产欧美色图 |