0x00 發生了什么
最近 楊海象 負責開發的某平臺上線,效果不錯,但是在使用期間出現了核心轉儲,占用了大量磁盤空間,如下圖,可見,近1T,
平臺上線當天楊海象和老王嘗試關閉核心轉儲,執行了命令
ulimit -c 0
核心仍然繼續生成,雖然磁盤空間夠用,且平臺運行正常,但是這個問題找不到原因,且無法解決核心一直產生的問題,頭疼,終于,他來了,他帶著一杯7分甜的奶茶來找我了,
0x01 什么是核心轉儲
百度百科解釋的還不錯,我稍微修改一點:
在UNIX系統中,常將“主記憶體”(main memory) 稱為核心(core),因為在上世紀,計算機還沒使用半導體作為記憶體材料之前,記憶體的實作便是使用的核心(core),而核心映像(core image) 就是 記憶體中的“行程”(process)當前正在執行的內容,當行程發生錯誤或意外收到指定“信號”(signal) 而終止執行時,系統會將核心映像寫入一個檔案,以供開發人員跟蹤除錯錯誤之用,這就是所謂的核心轉儲(core dump),
核心轉儲簡單解釋就是當一個程式崩潰時,在該行程當前作業目錄的core檔案中復制了該行程的存盤影像,core檔案僅僅是一個記憶體映象(同時加上除錯資訊),主要是用來除錯的,
0x02 核心轉儲產生的原因及相關知識
1.行程收到特定信號指令而終止1,便會核心轉儲,
部分信號(核心轉儲)說明:
| 符號常量 | 說明 | 預設動作 |
|---|---|---|
| SIGABRT | 非正常終止信號 | 終止w/core |
| SIGBUS | 獲取記憶體中不確定的部分 | 終止w/core |
| SIGEMT | 硬體故障 | 終止w/core |
| SIGFPE | 算術例外 | 終止w/core |
| SIGILL | 無效硬體信號的檢測 | 終止w/core |
| SIGIOT | 硬體故障 | 終止w/core |
| SIGQUIT | 互動式終止信號 | 終止w/core |
| SIGSEGV | 無效記憶體參考檢測信號 | 終止w/core |
| SIGSYS | 無效系統呼叫 | 終止w/core |
| SIGTRAP | 軟中斷 | 終止w/core |
| SIGXCPU | 超過CPU限制(setrlimit) | 終止w/core |
| SIGXFSZ | 超過檔案長度限制(setrlimit) | 終止w/core |
2.POSIX標準
可移植作業系統界面(Portable Operating System Interface,POSIX),是IEEE為運行在UNIX系統上的程式而定義的一系列互相關聯的API標準的總稱,POSIX這個名稱基本上是Portable Operating System Interface(可移植作業系統介面)的縮寫,而X則表明其對Unix API的傳承,
由于以前各應用開發廠商自己玩自己的C語言,互相之間不兼容,于是出現了該標準,統一了C語言語法等,同時規定了所有信號常量及對應值,
(根據記憶寫的,如果說錯了的話就評論告訴我吧,我把這段刪了)
3.信號
懶得寫了,可以閱讀<signal.h>頭檔案,它宣告了sigset_t型別和sigaction結構,定義了三類信號:
(1)必需的信號;
(2)任務控制信號;
(3)記憶體保護信號,
略了,,,
0x03 核心轉儲復現
1.撰寫demo程式制造核心轉儲

2.查看當前ulimit的設定,并開啟核心轉儲
執行命令
ulimit -a
查看配置情況,根據輸出資訊對ulimit進行設定操作:
ulimit -c unlimited
將核心轉儲檔案的大小設定為無限大,即開啟核心轉儲

3.編譯并執行demo,復現核心轉儲

執行demo,核心檔案自動轉儲到當前作業目錄

4.除錯core檔案,追蹤呼叫堆疊,分析錯誤點及錯誤原因
可以看到錯誤發生在null_ptr()函式中,在檔案第14行,錯誤原因是信號SIGSEGV,產生信號SIGSEGV的可能原因是陣列越界,空指標解參考等,
0x04 修改ulimit配置不生效問題分析
1.情景分析
平臺上線,使用時,生成了大量內核轉儲檔案,但平臺運行正常,老王和楊海象擔心磁盤被占滿,所以決定先關閉內核轉儲,
執行
ulimit -c 0
再查看
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) 63157
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65535
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 63157
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
可是發現仍有核心檔案在轉儲,持續在生成,直到活動結束,平臺未出現崩潰,因此該問題未當天處理完,
2.問題分析
由于核心轉儲檔案生成的時候是用的pid做后綴,不知道崩潰的是哪個行程/執行緒,但是根據file的提示資訊知道具體是哪個行程/執行緒崩潰:
這里給的圖是測驗demo,分析了生產環境產生的核心轉儲,知道了是哪個行程,老王告訴我這個行程是由守護行程拉起的,也存在主動kill的情況,ok,大膽猜測一下核心轉儲產生的原因可能就是主動kill,一會兒去gdb看看,先分析下為什么設定了
ulimit -c 0
卻仍核心轉儲,
是否是由于崩潰行程不是終端shell拉起(行程),而是作為一個執行緒執行的,
3.問題復現
撰寫python起執行緒驗證上述猜想:
demo撰寫完成后,先確認環境:
(1)關閉核心轉儲;

(2)驗證是否關閉,

環境確認無誤后,運行demo驗證猜想

轉儲檔案未生成,猜想錯誤,繼續分析和猜想,
首先分析ulimit命令,這個命令事shell內置的命令,所以是否和shell有關?那開始驗證:
新開一個shell,cd到同目錄,查看ulimit屬性,兩個終端的ulimit屬性配置不同(file size),如下圖:

則先在file size = 0的終端(右)上先運行python demo,發現未生成核心轉儲;同時在終端(右)demo結束前,讓file size = unlimited的終端(左)運行demo,發現核心轉儲了,說明核心轉儲的配置屬性與當前終端相關,

0x05 總結
1.問題原因
阿西吧,終于搞清楚了,ulimit命令設定的是當前終端的屬性,要想全域修改,則需要修改以下兩個檔案中的一個2
/proc/sys/kernel/core_pattern
/proc/sys/kernel/core_uses_pid
有個小坑,就是這倆檔案需要root權限修改,且vi不能修改該檔案,可以使用nano或者echo重定向,
2.解決辦法
修改ulimit配置,使所有核心轉儲保存到 /dev/null
echo "/dev/null/core.%p" > /proc/sys/kernel/core_pattern
下班,回家,喂狗,睡覺,
參考自: http://www.mamicode.com/info-detail-1355384.html ??
參考自: https://blog.csdn.net/phmatthaus/article/details/107182265 ??
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/4325.html
標籤:python
上一篇:Linux檔案操作及屬性
