重新整理 .net core 實踐篇 ———— linux上排查問題實用工具 [外篇]

2022-11-05 21:06:16

前言

介紹下面幾個工具:

Lldb
createdump
dotnet-dump
dotnet-gcdump
dotnet-symbol
Procdump

該文的前置篇為:

https://www.cnblogs.com/aoximin/p/16839812.html

獻給初學者,這篇就只介紹下看下紀錄檔和lldb,畢竟東西太多了。

正文

我以官網的例子作為演示:https://buggyambfiles.blob.core.windows.net/bin/buggyamb_v1.1.zip

專案地址:https://github.com/ahmetmithat/buggyamb

我這裡就已經發布可以存取了,並且使用者nginx 作為轉發,已經啟動起來了。

步驟在前面兩篇,如果看需要釋出的,可以往前面兩篇看看,這裡就不多複述了。

[Unit]
Description=BuggyAmb

[Service]
WorkingDirectory=/var/buggyamb
ExecStart=/usr/bin/dotnet /var/buggyamb/BuggyAmb.dll
Restart=aways
RestartSec=10
SyslogIdentifier=BuggyAmb
User=root
Environment=ASPNETCORE_ENVIRONMENT=Development
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS=http://0.0.0.0:6000
[Install]
WantedBy=multi-user.target

service 的設定如上。

頁面測試如下:

裡面分別是:

慢、處理異常、不處理異常、崩潰、未找到頁面、批次處理

崩潰情況

這種比較好排查的,其實一般看紀錄檔就行。

我這裡點一下Crash2,讓程式崩潰。 這裡說明一下,上面我用的是官方例子,直接可以看程式碼怎麼崩潰的哈。

public class Crash2Model : PageModel
{
	public string quote;
	~Crash2Model()
	{
		if (quote.ToString() != string.Empty)
		{
			quote = null;
		}
	}
	public void OnGet()
	{
	}
}

這個可以看下。

那麼我們進行紀錄檔排查一下錯誤。

journalctl -r --identifier=BuggyAmb --since "10 minute ago"

告訴我們15行錯誤。

-r:按反向順序列印紀錄檔,以便首先列出最新紀錄檔。
--identifier:請記住 SyslogIdentifier=buggyamb-identifier 測試應用程式的服務檔案中的行。 (可以使用此方法強制紀錄檔僅顯示適用於有問題的應用程式的條目。)
--since:顯示在指定的上一時期記錄的資訊。 範例: --since "10 minute ago" 或 --since "2 hour ago".

journalctl 還有很多其他的功能,這裡就不一一舉例了。

核心轉儲

centos 預設不開啟的:

可以看下這個怎麼開啟的:

https://blog.csdn.net/ProgramVAE/article/details/105921381

#!/bin/bash

#me: coredumpshell.sh
### Description: enable coredump and format the name of core file on centos system

# enable coredump whith unlimited file-size for all users
echo -e "\n# enable coredump whith unlimited file-size for all users\n* soft core unlimited" >> /etc/security/limits.conf

# set the path of core file with permission 777 
cd /var/buggyamb && mkdir corefile && chmod 777 corefile

# format the name of core file.   
# %% – 符號%
# %p – 程序號
# %u – 程序使用者id
# %g – 程序使用者組id
# %s – 生成core檔案時收到的訊號
# %t – 生成core檔案的時間戳(seconds since 0:00h, 1 Jan 1970)
# %h – 主機名
# %e – 程式檔名
echo -e "/var/buggyamb/corefile/core-%e-%s-%u-%g-%p-%t" > /proc/sys/kernel/core_pattern

# for centos7 system(update 2017.2.3 21:44)
echo -e "/var/buggyamb/corefile/core-%e-%s-%u-%g-%p-%t" > /etc/sysctl.conf

# suffix of the core file name
echo -e "1" > /proc/sys/kernel/core_uses_pid

執行之後就開啟了。

centos 一般用不上,我也沒有去偵錯過,這裡就不演示了,只能說有這種東西。

使用lldb

安裝:yum install lldb

前文提及到這個要安裝lldb 3.9 以上的。

按照這個檔案來編譯安裝也行:

https://github.com/dotnet/diagnostics/blob/main/documentation/lldb/linux-instructions.md

在 lldb 中開啟核心轉儲檔案之前,請按照以下必需步驟設定符號路徑,下載符號,並在開啟 lldb 時自動載入 SOS :

安裝 dotnet 符號工具:

dotnet tool install -g dotnet-symbol

下載目標轉儲檔案的符號:

dotnet-symbol <path_of_dump_file>

安裝 SOS:

安裝 dotnet-sos 全域性工具:

dotnet tool install -g dotnet-sos

安裝 SOS:

dotnet-sos install

最後成功的樣子:

使用createdump:

Createdump 會與每個 .NET Core 執行時一起自動安裝。

如 建立的ump 設定策略 檔案中所述,可以設定具有環境變數的設定選項。 這些將作為引數傳遞給建立的ump 命令。 下面是支援的環境變數:

COMPlus_DbgEnableMiniDump:如果設定為 1,則在終止時啟用自動核心轉儲生成。 預設值為 0 。
COMPlus_DbgMiniDumpType:這是將要建立的微型轉儲檔案的型別。 此值的預設值為 2 (或列舉型別 MiniDumpWithPrivateReadWriteMemory) 。 這意味著生成的轉儲檔案將包括 GC 堆以及捕獲程序中所有現有執行緒的堆疊跟蹤所需的資訊。
COMPlus_DbgMiniDumpName:如果設定,請用作模板來建立轉儲檔案路徑和檔名。 可以使用引數將 PID 放入名稱中 %d 。 預設模板為 /tmp/coredump.%d. 通過使用此環境變數,可以設定輸出目錄。
COMPlus_CreateDumpDiagnostics:如果設定為 1,則啟用建立的ump 工具診斷訊息 (TRACE 宏) 。 如果 createdump 不能按預期工作並且不生成記憶體轉儲檔案,則此設定可能很有用。

詳細資訊如下:https://github.com/dotnet/coreclr/blob/master/Documentation/botr/xplat-minidump-generation.md

進行開啟:

然後重啟,再來點選clash3進行崩潰一下。

可以看到這裡就有了。

這裡我們先轉儲檔案符號一下:

dotnet-symbol /tmp/coredump.9784-o /dumps/symbols/ --host-only

然後進去一下:

lldb --core /tmp/coredump.9784

這個時候要載入一下dotnet 符號。

setsymbolserver -directory /dumps/symbols/

然後載入轉儲檔案符號:

loadsymbols

這樣就搞定了。

clrsthread 檢視一下執行緒的情況:

這裡可以看到裡面有個異常是15號執行緒。

切到15號執行緒:

setthread 15:

然後檢視一下clrstack(呼叫棧資訊):

這個似乎沒有告訴我們很多很有用的資訊,只能告訴我們執行緒異常了,當然也告訴我們具體的行,可以去看下去原始碼看下什麼型別異常,但是有跟好用的pe。

用pe檢視下:

pe  -- Displays and formats fields of any object derived from the Exception class at the specified address.

這樣就定位到具體的崩潰檔案了。

知道了崩潰是因為HttpWebRequest,希望的是能查到到底是哪個存取url造成了崩潰。

下面這個圖,證明可呼叫了HttpWebRequest引發的:

使用dumpheap:dumpheap -stat -type System.Net.HttpWebRequest 檢視httpwebrequest 呼叫棧:

檢視棧地址:

然後是根據地址檢視物件:dumpobj 00007fe0c4442f28

這個webrequest 裡面有一個是system.url 我們寫程式的知道這是存取地址。

然後繼續查這個物件,上面那個value 就是地址哈。

00007fe0c4437cf8

然後可以看到url 地址:

第一個就是了,為什麼確認第一個就是,看名字。

這樣就查到了。

先到這裡吧,介紹這個lldb 是為了檢視非託管棧的,如果檢視託管的一般使用dotnet-dump 就好了。

而且一般是用來分析cpu 和 記憶體高的地方,一般伺服器端錯誤會有紀錄檔的。

繼續後面演示cpu 和 記憶體高的例子,這個對伺服器端更有實用性。